/// <summary> /// Run Aggregation /// This method /// 1) loads the aggregation definition /// 2) Fetch all required observations using the DataProxy /// 3) Calls the PerformAggregation method to perform the aggregation and returns a new observation /// /// </summary> /// <param name="patientId">Patient Id</param> /// <param name="code">Meta observation Code</param> /// <param name="lastExecutionTime"></param> /// <param name="aggregationType">Overrides the default aggregation type</param> /// <param name="filterType">Overrides the default filter type</param> /// <returns></returns> public async Task <IEnumerable <IObservation> > Run(string patientId, string code, DateTime?lastExecutionTime, string aggregationType = null, string filterType = null) { if (patientId == null) { throw new ArgumentNullException(nameof(patientId)); } if (code == null) { throw new ArgumentNullException(nameof(code)); } // Get Definition File Name from AggrDefinitionDictionary if (_definition == null) { _definition = AggrConfig.FromString(_aggrDefinitionDictionary.GetJsonConfigFromCode(code)); } if (_definition == null) { throw new AggrDefinitionNotFoundException(nameof(_definition)); } if (!string.IsNullOrEmpty(aggregationType)) { _definition.AggregationType = aggregationType; } if (!string.IsNullOrEmpty(filterType)) { _definition.MetaAggregationType = filterType; } var lastExecutionTimeStamp = lastExecutionTime.HasValue ? lastExecutionTime.Value.ToUnixTimestamp() * 1000 : 0; //Get Data List <PDObservation> observations = new List <PDObservation>(); foreach (var c in _definition.Variables) { try { //Get Observations For patient var ret = await _proxy.Get <PDObservation>(MAXTAKE, 0, GetFilter(patientId, c.Code, lastExecutionTimeStamp, _definition.AggregationType), null); observations.AddRange(ret); } catch (Exception ex) { _logger?.LogError(ex, "Error in aggregation"); } } var metaObservation = PerformAggregation(_definition, patientId, lastExecutionTimeStamp, observations); return(metaObservation); }
/// <summary> /// Get Alert Level /// </summary> /// <param name="alert">Alert Input</param> /// <param name="patientId">Patient Id</param> /// <returns>0: No Alert, 1: Low Priority Alert, 2: Medium Priority Alert, 3: High Priority Alert</returns> public async Task <AlertLevel> GetAlertLevel(IAlertInput alert, string patientId) { if (alert.TargetValueSource.ToLower() == ObservationType) { if (!alert.TargetValueNumeric) { throw new InvalidCastException("Target value should be numeric"); } try { var observations = await _dataProxy.Get <PDObservation>(10, 0, String.Format("{{patientid:\"{0}\",datefrom:\"{2}\",dateto:\"{3}\",codeid:\"{1}\",aggr:\"total\"}}", patientId, alert.TargetValueSource, (DateTime.Now.AddDays(-alert.AggregationPeriodDays).ToUnixTimestampMilli()), (DateTime.Now.ToUnixTimestampMilli())), null); var value = observations.Select(e => e.Value).DefaultIfEmpty(0).Average(); return(ApplyFilter(alert, value)); } catch (Exception ex) { Debug.WriteLine(ex); throw ex; } } else if (alert.TargetValueSource.ToLower() == MetaObservationType) { //Get Aggregated observation var aggrObservation = await _aggregator.Run(patientId, alert.TargetValueCode, DateTime.Now.AddDays(-alert.AggregationPeriodDays)); var value = aggrObservation.Select(e => e.Value).Average(); return(ApplyFilter(alert, value)); } else if (alert.TargetValueSource.ToLower() == ClinicalInfoType) { //Clinical Info Input try { var patient = await _dataProxy.Get <PDPatient>(patientId); var clinicalInfoList = patient.GetClinicalInfoList(); var clinicalInfo = clinicalInfoList.FirstOrDefault(e => e.Code.ToLower() == alert.TargetValueCode.ToLower()); return(ApplyFilter(alert, clinicalInfo.Value)); } catch (Exception ex) { throw ex; } } else if (alert.TargetValueSource.ToLower() == DSSInfoType) { //DSS Input try { var observations = await _dssRunner.Run(patientId, _dssDefinitionProvider.GetJsonConfigFromCode(alert.TargetValueCode)); var value = observations.Where(e => e.Code == alert.TargetValueCode).Select(e => e.Value).FirstOrDefault(); return(ApplyFilter(alert, value)); } catch (Exception ex) { Debug.WriteLine(ex); throw ex; } } else { throw new NotSupportedException($"Source type not supported from PDManager Alert Evaluator"); } }
/// <summary> /// /// </summary> /// <param name="patientId"></param> /// <param name="config"></param> /// <returns></returns> private async Task <IEnumerable <DSSValue> > GetInputValues(string patientId, DSSConfig config) { List <DSSValue> values = new List <DSSValue>(); //Codes from observations List <string> observationCodes = new List <string>(); //Codes from Meta o List <string> metaObservationCodes = new List <string>(); //Codes from Patient Clinical Info List <string> clinicalInfoCodes = new List <string>(); foreach (var c in config.Input) { if (string.IsNullOrEmpty(c.Source)) { //TODO: Add some error to response continue; } if (c.Source.ToLower() == ObservationType) { if (!observationCodes.Contains(c.Code)) { observationCodes.Add(c.Code); } } else if (c.Source.ToLower() == MetaObservationType) { if (!metaObservationCodes.Contains(c.Code)) { metaObservationCodes.Add(c.Code); } } else if (c.Source.ToLower() == ClinicalInfoType) { if (!clinicalInfoCodes.Contains(c.Code)) { clinicalInfoCodes.Add(c.Code); } } else { throw new NotSupportedException($"Source type {c.Source} not supported from PDManager DSS"); } } #region Observation Codes //TODO: Join observations codes in a single request in case foreach (var code in observationCodes) { try { var observations = await _dataProxy.Get <PDObservation>(10, 0, String.Format("{{patientid:\"{0}\",deviceid:\"\",datefrom:{2},dateto:{3},codeid:\"{1}\",aggr:\"total\"}}", patientId, code, (DateTime.Now.AddDays(-config.AggregationPeriodDays).ToUnixTimestampMilli()), (DateTime.Now.ToUnixTimestampMilli())), null); foreach (var observation in config.Input.Where(e => e.Code == code)) { values.Add(new DSSValue() { Name = observation.Name, Code = observation.Code, Value = observations.Select(e => e.Value).DefaultIfEmpty(0).Average().ToString() }); } // } } catch (Exception ex) { Debug.WriteLine(ex); } } #endregion Meta Observation Codes #region Meta Observation Codes foreach (var code in metaObservationCodes) { try { //Get Aggregated observation var aggrObservation = await _aggregator.Run(patientId, code, DateTime.Now.AddDays(-config.AggregationPeriodDays)); //Find Corresponding observation in config foreach (var metaObservation in config.Input.Where(e => e.Code == code)) { //Meta Observations are only numeric values.Add(new DSSValue() { Name = metaObservation.Name, Code = metaObservation.Code, Value = aggrObservation.Select(e => e.Value).DefaultIfEmpty(0).Average().ToString() }); } } catch (Exception ex) { throw ex; } } #endregion Observation Codes #region Clinical Info try { var patient = await _dataProxy.Get <PDPatient>(patientId); var clinicalInfoList = GetClinicalInfoList(patient.ClinicalInfo); foreach (var c in clinicalInfoList) { var clinicalInfo = config.Input.FirstOrDefault(e => e.Code.ToLower() == c.Code.ToLower()); if (clinicalInfo != null) { values.Add(new DSSValue() { Name = clinicalInfo.Name, Code = clinicalInfo.Code, Value = c.Value }); } } } catch (Exception ex) { throw ex; } #endregion Clinical Info return(values); }