Skip to content

Commit

Permalink
Add medications rule support
Browse files Browse the repository at this point in the history
  • Loading branch information
samhq committed Feb 27, 2019
1 parent 03b614b commit 9722527
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 50 deletions.
31 changes: 31 additions & 0 deletions contents/guideline_hearts.json
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,37 @@
],
"code": "BP-HTN-DM"
},
{
"category": "hypertension, on medication",
"definition": "high blood pressure, on medication",
"conditions": [{
"medications": {
"anti-hypertensive": true
},
"diabetes": false,
"age": {
"from": 41
},
"sbp": {
"from": 141,
"unit": "mmHg"
},
"target": "120/80"
},
{
"medications": {
"anti-hypertensive": true
},
"diabetes": false,
"dbp": {
"from": 91,
"unit": "mmHg"
},
"target": "120/80"
}
],
"code": "BP-HTN-ON-MEDICATION"
},
{
"category": "hypertension",
"definition": "high blood pressure",
Expand Down
8 changes: 4 additions & 4 deletions pkg/algorithms/hearts/hearts.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ func (d *Data) get(ctx context.Context) error {
}

// Diabetes
diabetes, err := engineGuide.Body.Diabetes.Process(p.Diabetes, bslOrA1c, bslOrA1cType, bslOrA1cUnit)
diabetes, err := engineGuide.Body.Diabetes.Process(p.Diabetes, bslOrA1c, bslOrA1cType, bslOrA1cUnit, p.Medications)
if err != nil {
errs = append(errs, err.Error())
} else {
Expand All @@ -401,7 +401,7 @@ func (d *Data) get(ctx context.Context) error {
if diabetes.Value == "diabetes" {
diab = true
}
bp, err := engineGuide.Body.BloodPressure.Process(diab, p.Sbp, p.Dbp, p.Age)
bp, err := engineGuide.Body.BloodPressure.Process(diab, p.Sbp, p.Dbp, p.Age, p.Medications)
if err != nil {
errs = append(errs, err.Error())
} else {
Expand All @@ -421,7 +421,7 @@ func (d *Data) get(ctx context.Context) error {

// CVD
cvdScore := ""
cvd, err := engineGuide.Body.CVD.Guidelines.Process(ctx, p.AMI, p.Cvd, p.Pvd, p.Ckd, p.Age, *engineGuide.Body.CVD.PreProcessing)
cvd, err := engineGuide.Body.CVD.Guidelines.Process(ctx, p.AMI, p.Cvd, p.Pvd, p.Ckd, p.Age, *engineGuide.Body.CVD.PreProcessing, p.Medications)
if err == nil {
cvdScore = cvd.Value
res, followupActions = GetResults(cvd, *engineContent.Body.Contents, followupActions)
Expand Down Expand Up @@ -456,7 +456,7 @@ func (d *Data) get(ctx context.Context) error {
cvdForChol = 10.0
}
// fmt.Println("CVD for Chol: ", cvdForChol)
chol, err := engineGuide.Body.Cholesterol.TotalCholesterol.Process(cvdForChol, p.Age, p.TChol, p.CholUnit, "total cholesterol")
chol, err := engineGuide.Body.Cholesterol.TotalCholesterol.Process(cvdForChol, p.Age, p.TChol, p.CholUnit, "total cholesterol", p.Medications)
if err != nil {
errs = append(errs, err.Error())
} else {
Expand Down
33 changes: 26 additions & 7 deletions pkg/engine/blood_pressure.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,25 @@ import (
"math"
)

// MedicationConditions object
type MedicationConditions struct {
Antihypertensive *bool `json:"anti-hypertensive"`
OralHypoglycaemic *bool `json:"oral-hypoglycaemic"`
Insulin *bool `json:"insulin"`
LipidLowering *bool `json:"lipid-lowering"`
Antiplatelet *bool `json:"anti-platelet"`
AntiCoagulant *bool `json:"anti-coagulant"`
Bronchodilator *bool `json:"bronchodilator"`
}

// BloodPressureCondition object
type BloodPressureCondition struct {
Diabetes *bool `json:"diabetes"`
SBP *RangeInt `json:"sbp"`
DBP *RangeInt `json:"dbp"`
Age *RangeFloat `json:"age"`
Target *string `json:"target"`
Medications *MedicationConditions `json:"medications"`
Diabetes *bool `json:"diabetes"`
SBP *RangeInt `json:"sbp"`
DBP *RangeInt `json:"dbp"`
Age *RangeFloat `json:"age"`
Target *string `json:"target"`
}

// BloodPressureConditions slice
Expand All @@ -29,7 +41,7 @@ type BloodPressureGuideline struct {
type BloodPressureGuidelines []BloodPressureGuideline

// Process function
func (b *BloodPressureGuidelines) Process(diabetes bool, sbp, dbp int, age float64) (Response, error) {
func (b *BloodPressureGuidelines) Process(diabetes bool, sbp, dbp int, age float64, medications map[string]bool) (Response, error) {
code := ""
value := fmt.Sprintf("%d/%d", sbp, dbp)
target := ""
Expand Down Expand Up @@ -72,12 +84,19 @@ func (b *BloodPressureGuidelines) Process(diabetes bool, sbp, dbp int, age float
}
}

conditionMedication := true
if c.Medications != nil {
if c.Medications.Antihypertensive != nil && *c.Medications.Antihypertensive != medications["anti-hypertensive"] {
conditionMedication = false
}
}

conditionDiabetes := true
if c.Diabetes != nil && *c.Diabetes != diabetes {
conditionDiabetes = false
}

if conditionDiabetes && (age >= ageFrom && age <= ageTo) && sbpFrom <= sbp && sbpTo >= sbp && dbpFrom <= dbp && dbpTo >= dbp {
if conditionDiabetes && conditionMedication && (age >= ageFrom && age <= ageTo) && sbpFrom <= sbp && sbpTo >= sbp && dbpFrom <= dbp && dbpTo >= dbp {
code = *g.Code
target = *c.Target
break
Expand Down
19 changes: 13 additions & 6 deletions pkg/engine/cholesterol.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ type CholesterolGuidelinesFull struct {

// CholesterolCondition object
type CholesterolCondition struct {
Age *RangeFloat `json:"age"`
CVD *RangeFloat `json:"cvd"`
Range *RangeFloat `json:"range"`
Target *string `json:"target"`
Medications *MedicationConditions `json:"medications"`
Age *RangeFloat `json:"age"`
CVD *RangeFloat `json:"cvd"`
Range *RangeFloat `json:"range"`
Target *string `json:"target"`
}

// CholesterolConditions slice
Expand All @@ -38,7 +39,7 @@ type CholesterolGuideline struct {
type CholesterolGuidelines []CholesterolGuideline

// Process function
func (b *CholesterolGuidelines) Process(cvd, age, chol float64, cholUnit, cholType string) (Response, error) {
func (b *CholesterolGuidelines) Process(cvd, age, chol float64, cholUnit, cholType string, medications map[string]bool) (Response, error) {
cholesterol := tools.CalculateMMOLValue(chol, cholUnit)

code := ""
Expand Down Expand Up @@ -87,9 +88,15 @@ func (b *CholesterolGuidelines) Process(cvd, age, chol float64, cholUnit, cholTy
}
}

conditionMedication := true
if c.Medications != nil {
if c.Medications.LipidLowering != nil && *c.Medications.LipidLowering != medications["lipid-lowering"] {
conditionMedication = false
}
}
// fmt.Println("CHOL =>", cholFrom, cholTo, cholUnit)

if (age >= ageFrom && age <= ageTo) && (cvd >= cvdFrom && cvd <= cvdTo) && (cholesterol >= cholFrom && cholesterol <= cholTo) {
if conditionMedication && (age >= ageFrom && age <= ageTo) && (cvd >= cvdFrom && cvd <= cvdTo) && (cholesterol >= cholFrom && cholesterol <= cholTo) {
code = *g.Code
target = *c.Target
break
Expand Down
24 changes: 16 additions & 8 deletions pkg/engine/cvd.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,12 @@ func (p *PreProcessingGuidelines) PreProcess(ami, hxCVD, hxPVD, hxCKD bool, age

// CVDCondition object
type CVDCondition struct {
ExistingCVD *bool `json:"existing_cvd"`
HighRiskCondition *bool `json:"high_risk_conditions"`
AgeCheckForCVD *bool `json:"age_check_for_cvd"`
Range *RangeFloat `json:"range"`
Target *string `json:"target"`
Medications *MedicationConditions `json:"medications"`
ExistingCVD *bool `json:"existing_cvd"`
HighRiskCondition *bool `json:"high_risk_conditions"`
AgeCheckForCVD *bool `json:"age_check_for_cvd"`
Range *RangeFloat `json:"range"`
Target *string `json:"target"`
}

// CVDConditions slice
Expand All @@ -118,7 +119,7 @@ type CVDGuideline struct {
type CVDGuidelines []CVDGuideline

// Process function
func (b *CVDGuidelines) Process(ctx context.Context, ami, hxCVD, hxPVD, hxCKD bool, age float64, preProcessing PreProcessing) (Response, error) {
func (b *CVDGuidelines) Process(ctx context.Context, ami, hxCVD, hxPVD, hxCKD bool, age float64, preProcessing PreProcessing, medications map[string]bool) (Response, error) {
code := ""
value := ""
target := ""
Expand Down Expand Up @@ -178,18 +179,25 @@ func (b *CVDGuidelines) Process(ctx context.Context, ami, hxCVD, hxPVD, hxCKD bo
conditionHighRisk = false
}

conditionMedication := true
if c.Medications != nil {
if (c.Medications.Antiplatelet != nil && *c.Medications.Antiplatelet != medications["anti-platelet"]) || (c.Medications.AntiCoagulant != nil && *c.Medications.AntiCoagulant != medications["anti-coagulant"]) {
conditionMedication = false
}
}

// res2B, _ := json.Marshal(c)
// fmt.Println(string(res2B))
// fmt.Printf("%+v\n", conditionAge)
// fmt.Printf("%+v\n", conditionExistingCVD)
// fmt.Printf("%+v\n", conditionHighRisk)

if conditionAge && conditionExistingCVD && conditionHighRisk && (riskScore >= rangeFrom && riskScore <= rangeTo) {
if conditionMedication && conditionAge && conditionExistingCVD && conditionHighRisk && (riskScore >= rangeFrom && riskScore <= rangeTo) {
code = *g.Code
if code != "CVD-AGE-FALSE" {
value = fmt.Sprintf("%s%%", riskRange)
} else {
value = "1"
value = "0"
}
target = *c.Target
break
Expand Down
18 changes: 13 additions & 5 deletions pkg/engine/diabetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ type BloodSugarCondition struct {

// DiabetesCondition object
type DiabetesCondition struct {
HxDiabetes *bool `json:"hx_diabetes"`
BloodSugar *BloodSugarCondition `json:"blood_sugar"`
Target *string `json:"target"`
Medications *MedicationConditions `json:"medications"`
HxDiabetes *bool `json:"hx_diabetes"`
BloodSugar *BloodSugarCondition `json:"blood_sugar"`
Target *string `json:"target"`
}

// DiabetesConditions slice
Expand All @@ -38,7 +39,7 @@ type DiabetesGuideline struct {
type DiabetesGuidelines []DiabetesGuideline

// Process function
func (b *DiabetesGuidelines) Process(hxDiabetes bool, bsFromInput float64, bsType, unit string) (Response, error) {
func (b *DiabetesGuidelines) Process(hxDiabetes bool, bsFromInput float64, bsType, unit string, medications map[string]bool) (Response, error) {
code := ""
value := ""
target := ""
Expand Down Expand Up @@ -75,12 +76,19 @@ func (b *DiabetesGuidelines) Process(hxDiabetes bool, bsFromInput float64, bsTyp
givenBsType = *c.BloodSugar.Type
}

conditionMedication := true
if c.Medications != nil {
if (c.Medications.OralHypoglycaemic != nil && *c.Medications.OralHypoglycaemic != medications["oral-hypoglycaemic"]) || (c.Medications.Insulin != nil && *c.Medications.Insulin != medications["insulin"]) {
conditionMedication = false
}
}

conditionHxDiabetes := true
if c.HxDiabetes != nil && *c.HxDiabetes != hxDiabetes {
conditionHxDiabetes = false
}

if conditionHxDiabetes && bsFrom <= from && bsTo >= from && strings.ToLower(bsType) == strings.ToLower(givenBsType) {
if conditionHxDiabetes && conditionMedication && bsFrom <= from && bsTo >= from && strings.ToLower(bsType) == strings.ToLower(givenBsType) {
code = *g.Code
target = *c.Target
value = fmt.Sprintf("%.1f%s", bsFromInput, unit)
Expand Down
36 changes: 20 additions & 16 deletions pkg/tools/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,7 @@ type FamilyHistory struct {
}

// Medications object
type Medications struct {
Antihypertensives bool
Statin bool
Antiplatelet bool
Bronchodilator bool
}
type Medications map[string]bool

// Measurements object
type Measurements struct {
Expand Down Expand Up @@ -452,22 +447,31 @@ func getInputs(data []byte) (Params, error) {
}, "params", "components", "family_history")

// Medications
out.Medications = make(map[string]bool)
jp.ArrayEach(data, func(value []byte, dataType jp.ValueType, offset int, err error) {
category := ""
if stringValue, err = jp.GetString(value, "category"); err == nil {
category = stringValue
}

switch category {
case "anti-hypertensive":
out.Antihypertensives = true
case "statin":
out.Statin = true
case "antiplatelet":
out.Antiplatelet = true
case "bronchodilator":
out.Bronchodilator = true
}
out.Medications[category] = true

// switch category {
// case "anti-hypertensive":
// out.Antihypertensives = true
// case "oral-hypoglycaemic":
// out.OralHypoglycaemic = true
// case "insulin":
// out.Insulin = true
// case "lipid-lowering":
// out.LipidLowering = true
// case "anti-platelet":
// out.Antiplatelet = true
// case "anti-coagulant":
// out.AntiCoagulant = true
// case "bronchodilator":
// out.Bronchodilator = true
// }
}, "params", "components", "medications")

// Medical history
Expand Down
9 changes: 5 additions & 4 deletions sample-request.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,23 +68,23 @@
"effectiveDate": "timestamp",
"name": "blood_pressure",
"category": "vital-signs",
"value": "110/85",
"value": "150/95",
"units": "mmHg",
"arm": "right"
},
{
"effectiveDate": "timestamp",
"name": "blood_pressure",
"category": "vital-signs",
"value": "125/80",
"value": "145/90",
"units": "mmHg",
"arm": "right"
},
{
"effectiveDate": "timestamp",
"name": "blood_pressure",
"category": "vital-signs",
"value": "115/78",
"value": "148/88",
"units": "mmHg",
"arm": "right"
},
Expand Down Expand Up @@ -210,7 +210,8 @@
"medications": [
{
"generic": "rampiril",
"category": "anti-hypertensive"
"category": "anti-hypertensive",
"class": ""
}
],
"family_history": [
Expand Down

0 comments on commit 9722527

Please sign in to comment.