Has anyone re-coded Pediatric percentile functions for WHO percentiles (24 months and under)? Particularly the functions that either GE or Lee Cooper has done? Providers have noticed that percentiles on forms we have don't match the new Growth Charts (we went from Patch 1 to Service Pack 4 so we didn't get the new growth charts as soon as other did).
Thanks,
Hi David,
Did you ever get the percentiles re-coded. If yes , would you be willing to share?
Dan Rosato
570-650-6006
Physicians Health Alliance
Nothing yet, and I'm not sure I understand the code well enough to do it on my own.
Our former Pediatric/IS docs built the code for this to use on EMR SP3. You need to check it against the Growth Charts themselves, since we felt there was some discrepency about how the GE Growth Charts vs. the WHO rounded up/down on patient month-ages.
Rather than calling a text-file that the original Growth Charts used, everything should be below. I can't answer questions on the code logic but here it is:
/*********************************************************
/ GetPercentile
/ Returns the percentile of a given z-score
/
/ Paramaters
/ z: a z-score
/
/ Return
/ a percentile (double)
*********************************************************/
{! fn GetPercentile(zScore){
local part1
local part2
local part3
local part4
local zAbsSq
local doublePi
local percentile
if zScore == "" then
return ""
endif
part1 = 1 / (1 + (0.33267 * AbsValue(zScore)))
part2 = (0.4361836 * part1) - (0.1201676 * (part1^2)) + (0.937298 * (part1^3))
doublePi= 2 * 3.14159265
zAbsSq = (AbsValue(zScore)^2)
part3 = -1 * zAbsSq / 2
part4 = 1 / (doublePi^0.5) * (2.71828182845905^part3) * part2
percentile = 1 - part4
if zScore > 0 then
percentile = percentile * 100
else
percentile = 100 - (percentile * 100)
endif
return percentile
}}
/*********************************************************
/ AbsValue
/ Returns the absolute value of a number
/
/ Paramaters
/ val: the number to evaluate
/
/ Return
/ a positive number (double)
*********************************************************/
{! fn AbsValue(val){
if val<0 then
return -1 * val
endif
return val
}}
?
/* CALCULATE_GROWTH_PERCENTILES*/
{fn CALCULATE_GROWTH_PERCENTILES(){
local htPercent
local wtPercent
local bmiPercent
local hcPercent
local wtForLgthPercent
local htZScore
local wtZScore
local hcZScore
local bmiZScore
local wtForLgthZScore
local htCm
local wtKg
local hcCm
local bmi
htCm = OBSNOW("HEIGHT (CM)")
wtKg = OBSNOW("WEIGHT (KG)")
hcCm = OBSNOW("HEADCIRC(CM)")
bmi = OBSNOW("BMI")
htZScore = GetZScore("HEIGHT", htCm, gAgeInMonths)
wtZScore = GetZScore("WEIGHT", wtKg, gAgeInMonths)
hcZScore = GetZScore("HEAD CIRC", hcCm, gAgeInMonths)
bmiZScore = GetZScore("BMI", bmi, gAgeInMonths)
wtForLgthZScore = GetWtForLgthZScore(htCm, wtKg, gAgeInMonths)
htPercent = GetPercentile(htZScore)
wtPercent = GetPercentile(wtZScore)
hcPercent = GetPercentile(hcZScore)
bmiPercent = GetPercentile(bmiZScore)
wtForLgthPercent = GetPercentile(wtForLgthZScore)
?
htPercent = str(htPercent)
wtPercent = str(wtPercent)
hcPercent = str(hcPercent)
bmiPercent = str(bmiPercent)
wtForLgthPercent = str(wtForLgthPercent)
OBSNOW("HEIGHT %TILE", (if htPercent <> "" AND htPercent <> "n/a" THEN htPercent ELSE "" ENDIF))
OBSNOW("WEIGHT %TILE", (if wtPercent <> "" AND wtPercent <> "n/a" THEN wtPercent ELSE "" ENDIF))
OBSNOW("HC %tile", (if hcPercent <> "" AND hcPercent <> "n/a" THEN hcPercent ELSE "" ENDIF))
OBSNOW("bmi%ile", (if bmiPercent <> "" AND bmiPercent <> "n/a" THEN bmiPercent ELSE "" ENDIF))
OBSNOW("wt lgth-ht%", (if wtForLgthPercent <> "" AND wtForLgthPercent <>"n/a" THEN wtForLgthPercent ELSE "" ENDIF))
local display
display=""
if size(wtPercent) > 0 and NOT (wtPercent == "n/a") then display = display + "Weight: ..." + wtPercent + "% \n" endif
if size(htPercent) > 0 and NOT (htPercent == "n/a") then display = display + "Height: ...." + htPercent + "% \n" endif
if size(bmiPercent) > 0 and NOT (bmiPercent == "n/a") then display = display + "BMI: ......." + bmiPercent + "% \n" endif
if size(wtForLgthPercent) > 0 and NOT (wtForLgthPercent == "n/a") then display = display + "Wt. for Ht: " + wtForLgthPercent + "% \n" endif
if size(hcPercent) > 0 and NOT (hcPercent == "n/a") then display = display + "Head circ.: " + hcPercent + "% \n" endif
USEROK( display )
}}
?
/*********************************************************
/ GetZScore(growthParameter, valueMetric, ageInMonths)
/
/ Paramaters
/ growthParameter: the growth parameter category ("HEIGHT", "WEIGHT", "HEAD CIRC", or "BMI")
/ valueMetric: growth parameter measurement in metric (double)
/ ageInMonths: age of patient in months (integer)
/
/ Return
/ the z-score (double)
*********************************************************/
{! fn GetZScore(growthParameter, valueMetric, ageInMonths){
local lmsDataArr
local zScore
local adjAgeInMonths
local fileName, fileNameAge
local path, file, text
local GC_DIR, backslashes, backslash
local L, M, S
//Check if valid value
if valueMetric == 0 then
return ""
endif
//age limitations
//if older than 240 months = 20 years exit function
if ageInMonths >= 240 then
return ""
endif
if growthParameter == "HEAD CIRC" and ageInMonths > 36 then
return ""
endif
if growthParameter == "BMI" and ageInMonths < 24 then
return ""
endif
//Calculation
cond
case growthParameter == "HEIGHT"
if ageInMonths <= 24 then
fileName = "length_who"
else
if ageInMonths < 60 then
fileName = "height_age_60"
else
if ageInMonths < 120 then
fileName = "height_age_120"
else
if ageInMonths < 180 then
fileName = "height_age_180"
else
if ageInMonths < 240 then
fileName = "height_age_240"
endif
endif
endif
endif
endif
case growthParameter == "WEIGHT"
if ageInMonths <= 24 then
fileName = "weight_who"
else
if ageInMonths < 60 then
fileName = "weight_age_60"
else
if ageInMonths < 120 then
fileName = "weight_age_120"
else
if ageInMonths < 180 then
fileName = "weight_age_180"
else
if ageInMonths < 240 then
fileName = "weight_age_240"
endif
endif
endif
endif
endif
case growthParameter == "BMI"
if ageInMonths < 60 then
fileName = "bmi_age_60"
else
if ageInMonths < 120 then
fileName = "bmi_age_120"
else
if ageInMonths < 180 then
fileName = "bmi_age_180"
else
if ageInMonths < 240 then
fileName = "bmi_age_240"
endif
endif
endif
endif
case growthParameter == "HEAD CIRC"
if ageInMonths <= 24 then
fileName = "head_circ_who"
else
fileName = "head_circ_36"
endif
endcond
//GetRawLMSArray
text=""
//GetGrowthChartLmsDataPath
backslashes="\\\\"
backslash = get(backslashes, 2)
GC_DIR = backslash + "clinical content" + backslash + "peds_growth_data" + backslash + PATIENT.SEX + backslash
path = DIR_EMR() + GC_DIR + fileName
//Open file and copy data in to variable text
file = FILEOPEN(path, "r")
if file <> NULL then
text = FILEREAD(file)
FILECLOSE(file)
else
USEROK("Unable to open file '" + path + "'")
endif
if size(text) == 0 then
return ""
endif
//Put data into a 2-dimentional array
lmsDataArr = getfield(text, ",")
for i = 1, i<= size(lmsDataArr), i = i + 1
do
lmsDataArr[i] = getField(lmsDataArr[i], "|", "")
endfor
if size(lmsDataArr) == 0 then
return ""
endif
//Find LMS data by patient adjusted age
if ageInMonths <= 24 then
adjAgeInMonths = ageInMonths
else
adjAgeInMonths = ageInMonths + 0.5
endif
for j = 1, j <= size(lmsDataArr), j = j + 1
do
if adjAgeInMonths == lmsDataArr[j][4] then
L = lmsDataArr[j][1]
M = lmsDataArr[j][2]
S = lmsDataArr[j][3]
break
endif
endfor
if L == "" or M == "" or S == "" then
return ""
endif
//GetZScore
zScore = (((valueMetric / val(M))^val(L)) - 1) / (val(L) * val(S))
return zScore
}}
/*********************************************************
/ GetWtForLgthZScore(htCm, wtKg, ageInMonths)
/
/ Paramaters
/ htCm: the height in cm (double)
/ wtKg: the weight in kg (double)
/ ageInMonths: age of patient in months (integer)
/
/ Return
/ the z-score (double)
*********************************************************/
{! fn GetWtForLgthZScore(htCm, wtKg, ageInMonths){
local lmsDataArr
local zScore
local adjLength
local fileName
local path, file, text
local GC_DIR, backslashes, backslash
local L, M, S
if ageInMonths > 60 or wtKg == 0 or htCm == 0 then
return ""
endif
if ageInMonths <= 24 then
fileName = "weight_length_who"
else
fileName = "weight_length_child"
endif
//Get LMS constants
text=""
backslashes="\\\\"
backslash = get(backslashes, 2)
GC_DIR = backslash + "clinical content" + backslash + "peds_growth_data" + backslash + PATIENT.SEX + backslash
path = DIR_EMR() + GC_DIR + fileName
//Open file and copy data in to variable text
file = FILEOPEN(path, "r")
if file <> NULL then
text = FILEREAD(file)
FILECLOSE(file)
else
USEROK("Unable to open file '" + path + "'")
endif
if size(text) == 0 then
return ""
endif
//Put data into a 2-dimentional array
lmsDataArr = getfield(text, ",")
for i = 1, i<= size(lmsDataArr), i = i + 1
do
lmsDataArr[i] = getField(lmsDataArr[i], "|", "")
endfor
if size(lmsDataArr) == 0 then
return ""
endif
//Get adjusted length
if ageInMonths <= 24 then
//Find length rounded to nearest 0.5
adjLength = mod(round(val(htCm), 1), 1)
if adjLength < 0.3 then
adjlength = div(val(htCm), 1)
else
if adjLength < 0.8 then
adjlength = div(val(htCm), 1) + 0.5
else
adjlength = div(val(htCm), 1) + 1
endif
endif
else
adjlength = div(val(htCm), 1) + 0.5
endif
//Find LMS constants
for j = 1, j <= size(lmsDataArr), j = j + 1
do
if adjLength == lmsDataArr[j][4] then
L = lmsDataArr[j][1]
M = lmsDataArr[j][2]
S = lmsDataArr[j][3]
break
endif
endfor
if L == "" or M == "" or S == "" then
return ""
endif
//GetZScore
zScore = (((wtKg / val(M))^val(L)) - 1) / (val(L) * val(S))
return zScore
}}
/*********************************************************
/ DateDeltaInMonths
/ Returns the difference between two dates in months.
/ The dates may be entered in any order.
/ This function uses the date of the first date as the
/ defining point of a "month". For example, if the
/ date1 is May 16th
/ if date2 is June 16 or 17th, there is 1 month difference
/ if date 2 is June 15th, there are 0 months difference
/
/ Paramaters
/ date1: a date in MM/DD/YYYY format
/ date2: a date in MM/DD/YYYY format
/
/ Return
/ the difference between the dates (integer)
*********************************************************/
{! fn DateDeltaInMonths(date1, date2){
//local variables
local deltaInMonths
local monthiversaryMonth
local startDate
local endDate
local startDay
local endDay
local startMonth
local endMonth
local startYear
local endYear
//Determine startDate
if (DURATIONDAYS(str(date1), str(date2)) > 1) then
startDate=str(date1)
endDate=str(date2)
else
startDate=str(date2)
endDate=str(date1)
endif
//Parse startDate
startDay = sub(startDate, 4, 2)
startMonth = sub(startDate, 1, 2)
startYear = sub(startDate, 7, 4)
//Parse endDate
endDay = sub(endDate, 4, 2)
endMonth = sub(endDate, 1, 2)
endYear = sub(endDate, 7, 4)
//Calculate month of last monthiversary
if endDay >= startDay then
monthiversaryMonth = endMonth
else
if endDay < startDay then
If endMonth = 1 then //January
monthiversaryMonth = 12 //December
endYear = str(endYear - 1)
else
monthiversaryMonth = str(endMonth - 1)
endif
endif
endif
//Calculate months between dates
if monthiversaryMonth = startMonth then
deltaInMonths = (val(endYear) - val(startYear)) * 12
else
if monthiversaryMonth > startMonth then
deltaInMonths = (monthiversaryMonth - val(startMonth)) + (12 * (val(endYear) - val(startYear)))
else
if monthiversaryMonth < startMonth then
deltaInMonths = (12 + monthiversaryMonth - val(startMonth)) + (12 * ((val(endYear) - 1) - val(startYear)))
endif
endif
endif
return deltaInMonths
}}
/***************************
Variable Declarations
***************************/
{! gDocDate}
{! gAgeInMonths}
{global gWEIGHTlbs = DOCUMENT.WEIGHT_}
{global gWEIGHTozs = DOCUMENT.OZ}
{global gWEIGHTkg = OBSNOW("Weight (Kg)")}
{global gHeightCm = OBSNOW("Height (cm)")}
{global gHeight = OBSNOW("height")}
{global gHCIRCIN = OBSNOW("Head circumf")}
{global gHCIRCCM = OBSNOW("Headcirc(cm)")}
Thanks so very much James! I will give it a try.
Thanks James
James, in your code it refers to the files below:
head_circ_who
weight_length_who
weight_who
length_who
Anyway I could get a copy of these files. These might fix our issue with incorrect growth percentiles.
Daniel Robinson
OU Tulsa School of Community Medicine
These store into C:\Program Files\Centricity Physician Office\Clinical Content\peds_growth_data\ then to female or male with the other growth-chart files.
I don't recall if we created these or if they came with SP3. Our Peds doc who updated the form is gone now.
4-files in each.
jamesedward said:
These store into C:Program FilesCentricity Physician OfficeClinical Contentpeds_growth_data then to female or male with the other growth-chart files.
I don't recall if we created these or if they came with SP3. Our Peds doc who updated the form is gone now.
4-files in each.
The links are bad. Could you send these files to my email and thank you for these files.
Daniel Robinson
OU Tulsa School of Community Medicine