diff --git a/rcpchgrowth/__init__.py b/rcpchgrowth/__init__.py index 1b177f1..55a483f 100644 --- a/rcpchgrowth/__init__.py +++ b/rcpchgrowth/__init__.py @@ -1,5 +1,5 @@ from .date_calculations import chronological_decimal_age, corrected_decimal_age, chronological_calendar_age, estimated_date_delivery, corrected_gestational_age -from .global_functions import centile, sds_for_measurement, measurement_from_sds, percentage_median_bmi, mid_parental_height +from .global_functions import centile, sds_for_measurement, measurement_from_sds, percentage_median_bmi, mid_parental_height, measurement_for_z from .centile_bands import centile_band_for_centile from .bmi_functions import bmi_from_height_weight, weight_for_bmi_height from .age_advice_strings import comment_prematurity_correction diff --git a/rcpchgrowth/chart_functions.py b/rcpchgrowth/chart_functions.py index 315e83a..185a99b 100644 --- a/rcpchgrowth/chart_functions.py +++ b/rcpchgrowth/chart_functions.py @@ -407,16 +407,20 @@ def create_uk_who_chart(measurement_method: str, sex: str, centile_format: Union # if the Cole 9 centiles were selected, these are rounded, # so conversion to SDS is different # Otherwise standard conversation of centile to z is used + + z=0.0 #initialise + centile_value=0.0 #initialise + if cole_method: - z = rounded_sds_for_centile(centile_sds) - centile_value=centile_sds + z = rounded_sds_for_centile(centile_sds) # a centile was provided, so convert to z + centile_value=centile_sds # store the original centile value else: if (is_sds): - z=centile_sds - centile_value=centile(centile_sds) + z=centile_sds # an sds was supplied + centile_value=centile(centile_sds) # convert the z to a centile and store else: - z = sds_for_centile(centile_sds) - centile_value=centile_sds + z = sds_for_centile(centile_sds) # a centile was provided, so convert to z + centile_value=centile_sds # store the original centile value centile_data = [] try: @@ -433,6 +437,7 @@ def create_uk_who_chart(measurement_method: str, sex: str, centile_format: Union is_sds=is_sds ) except: + print(f"Not possible to generate centile data for UK-WHO {measurement_method} in {sex}s.") centile_data=None # Store this centile for a given measurement diff --git a/rcpchgrowth/data_tables/trisomy_21.json b/rcpchgrowth/data_tables/trisomy_21.json index 4acf0ca..bc3a3be 100644 --- a/rcpchgrowth/data_tables/trisomy_21.json +++ b/rcpchgrowth/data_tables/trisomy_21.json @@ -982,7 +982,7 @@ }, "bmi": { "male":[ - {"decimal_age": 0, "L": 0.7975301, "M": 12.18163, "S": 0.1195348}, + {"decimal_age": 0.0, "L": 0.7975301, "M": 12.18163, "S": 0.1195348}, {"decimal_age": 0.08, "L": 0.7580755, "M": 13.4406, "S": 0.1114926}, {"decimal_age": 0.17, "L": 0.7335379, "M": 14.3038, "S": 0.1068001}, {"decimal_age": 0.25, "L": 0.7154457, "M": 14.9775, "S": 0.1037158}, @@ -994,7 +994,7 @@ {"decimal_age": 0.75, "L": 0.6475536, "M": 16.8791, "S": 0.0960959}, {"decimal_age": 0.83, "L": 0.6382132, "M": 16.9882, "S": 0.0955683}, {"decimal_age": 0.92, "L": 0.628519, "M": 17.0694, "S": 0.0951506}, - {"decimal_age": 1, "L": 0.6182923, "M": 17.1296, "S": 0.0948244}, + {"decimal_age": 1.0, "L": 0.6182923, "M": 17.1296, "S": 0.0948244}, {"decimal_age": 1.08, "L": 0.6074216, "M": 17.1739, "S": 0.0945748}, {"decimal_age": 1.17, "L": 0.5958693, "M": 17.2059, "S": 0.0943864}, {"decimal_age": 1.25, "L": 0.5836943, "M": 17.2284, "S": 0.0942544}, @@ -1006,7 +1006,7 @@ {"decimal_age": 1.75, "L": 0.499399, "M": 17.26, "S": 0.0943826}, {"decimal_age": 1.83, "L": 0.4838544, "M": 17.256, "S": 0.0945339}, {"decimal_age": 1.92, "L": 0.4679904, "M": 17.2505, "S": 0.0947134}, - {"decimal_age": 2, "L": 0.4518357, "M": 17.2439, "S": 0.0949221}, + {"decimal_age": 2.0, "L": 0.4518357, "M": 17.2439, "S": 0.0949221}, {"decimal_age": 2.08, "L": 0.4354165, "M": 17.2361, "S": 0.0951559}, {"decimal_age": 2.17, "L": 0.4187565, "M": 17.2271, "S": 0.0954131}, {"decimal_age": 2.25, "L": 0.4018769, "M": 17.217, "S": 0.0956899}, @@ -1018,7 +1018,7 @@ {"decimal_age": 2.75, "L": 0.296824, "M": 17.1412, "S": 0.0976967}, {"decimal_age": 2.83, "L": 0.2787896, "M": 17.1284, "S": 0.0980714}, {"decimal_age": 2.92, "L": 0.2606286, "M": 17.1161, "S": 0.0984535}, - {"decimal_age": 3, "L": 0.2423511, "M": 17.1044, "S": 0.0988418}, + {"decimal_age": 3.0, "L": 0.2423511, "M": 17.1044, "S": 0.0988418}, {"decimal_age": 3.08, "L": 0.2239744, "M": 17.0934, "S": 0.0992357}, {"decimal_age": 3.17, "L": 0.2055171, "M": 17.083, "S": 0.0996345}, {"decimal_age": 3.25, "L": 0.186997, "M": 17.0734, "S": 0.1000371}, @@ -1030,7 +1030,7 @@ {"decimal_age": 3.75, "L": 0.0753428, "M": 17.0285, "S": 0.1025485}, {"decimal_age": 3.83, "L": 0.0567556, "M": 17.0232, "S": 0.1029832}, {"decimal_age": 3.92, "L": 0.038204, "M": 17.0185, "S": 0.1034228}, - {"decimal_age": 4, "L": 0.0196991, "M": 17.0145, "S": 0.1038675}, + {"decimal_age": 4.0, "L": 0.0196991, "M": 17.0145, "S": 0.1038675}, {"decimal_age": 4.08, "L": 0.0012517, "M": 17.0111, "S": 0.1043176}, {"decimal_age": 4.17, "L": -0.017128, "M": 17.0084, "S": 0.1047723}, {"decimal_age": 4.25, "L": -0.0354303, "M": 17.0063, "S": 0.1052328}, @@ -1042,7 +1042,7 @@ {"decimal_age": 4.75, "L": -0.143193, "M": 17.0081, "S": 0.1080977}, {"decimal_age": 4.83, "L": -0.1607589, "M": 17.0111, "S": 0.1085914}, {"decimal_age": 4.92, "L": -0.1782008, "M": 17.0149, "S": 0.1090893}, - {"decimal_age": 5, "L": -0.1955155, "M": 17.0195, "S": 0.1095912}, + {"decimal_age": 5.0, "L": -0.1955155, "M": 17.0195, "S": 0.1095912}, {"decimal_age": 5.08, "L": -0.2127001, "M": 17.0251, "S": 0.1100974}, {"decimal_age": 5.17, "L": -0.2297519, "M": 17.0316, "S": 0.1106068}, {"decimal_age": 5.25, "L": -0.2466678, "M": 17.039, "S": 0.1111201}, @@ -1054,7 +1054,7 @@ {"decimal_age": 5.75, "L": -0.3451413, "M": 17.1029, "S": 0.1142622}, {"decimal_age": 5.83, "L": -0.3610311, "M": 17.1167, "S": 0.1147954}, {"decimal_age": 5.92, "L": -0.3767681, "M": 17.1314, "S": 0.1153319}, - {"decimal_age": 6, "L": -0.3923514, "M": 17.1471, "S": 0.1158704}, + {"decimal_age": 6.0, "L": -0.3923514, "M": 17.1471, "S": 0.1158704}, {"decimal_age": 6.08, "L": -0.4077801, "M": 17.1636, "S": 0.1164113}, {"decimal_age": 6.17, "L": -0.4230534, "M": 17.1811, "S": 0.1169544}, {"decimal_age": 6.25, "L": -0.4381714, "M": 17.1995, "S": 0.1174995}, @@ -1066,7 +1066,7 @@ {"decimal_age": 6.75, "L": -0.5256538, "M": 17.3287, "S": 0.1208067}, {"decimal_age": 6.83, "L": -0.5397037, "M": 17.3531, "S": 0.1213627}, {"decimal_age": 6.92, "L": -0.5536048, "M": 17.3784, "S": 0.1219195}, - {"decimal_age": 7, "L": -0.567358, "M": 17.4044, "S": 0.1224771}, + {"decimal_age": 7.0, "L": -0.567358, "M": 17.4044, "S": 0.1224771}, {"decimal_age": 7.08, "L": -0.5809644, "M": 17.4311, "S": 0.1230351}, {"decimal_age": 7.17, "L": -0.5944252, "M": 17.4585, "S": 0.1235938}, {"decimal_age": 7.25, "L": -0.6077414, "M": 17.4866, "S": 0.1241526}, @@ -1078,7 +1078,7 @@ {"decimal_age": 7.75, "L": -0.6846683, "M": 17.6684, "S": 0.1274992}, {"decimal_age": 7.83, "L": -0.6970069, "M": 17.7008, "S": 0.1280544}, {"decimal_age": 7.92, "L": -0.7092117, "M": 17.7337, "S": 0.1286085}, - {"decimal_age": 8, "L": -0.7212843, "M": 17.7671, "S": 0.1291613}, + {"decimal_age": 8.0, "L": -0.7212843, "M": 17.7671, "S": 0.1291613}, {"decimal_age": 8.08, "L": -0.7332264, "M": 17.801, "S": 0.1297126}, {"decimal_age": 8.17, "L": -0.7450395, "M": 17.8354, "S": 0.1302625}, {"decimal_age": 8.25, "L": -0.7567253, "M": 17.8703, "S": 0.1308106}, @@ -1090,7 +1090,7 @@ {"decimal_age": 8.75, "L": -0.8242714, "M": 18.0889, "S": 0.1340562}, {"decimal_age": 8.83, "L": -0.8351192, "M": 18.1268, "S": 0.134589}, {"decimal_age": 8.92, "L": -0.8458554, "M": 18.165, "S": 0.1351193}, - {"decimal_age": 9, "L": -0.8564819, "M": 18.2036, "S": 0.1356467}, + {"decimal_age": 9.0, "L": -0.8564819, "M": 18.2036, "S": 0.1356467}, {"decimal_age": 9.08, "L": -0.8670007, "M": 18.2426, "S": 0.1361716}, {"decimal_age": 9.17, "L": -0.8774138, "M": 18.2819, "S": 0.1366939}, {"decimal_age": 9.25, "L": -0.8877229, "M": 18.3215, "S": 0.1372131}, @@ -1102,7 +1102,7 @@ {"decimal_age": 9.75, "L": -0.9474747, "M": 18.5658, "S": 0.1402682}, {"decimal_age": 9.83, "L": -0.9570971, "M": 18.6075, "S": 0.1407681}, {"decimal_age": 9.92, "L": -0.9666279, "M": 18.6494, "S": 0.1412629}, - {"decimal_age": 10, "L": -0.9760686, "M": 18.6916, "S": 0.1417557}, + {"decimal_age": 10.0, "L": -0.9760686, "M": 18.6916, "S": 0.1417557}, {"decimal_age": 10.08, "L": -0.9854209, "M": 18.734, "S": 0.1422454}, {"decimal_age": 10.17, "L": -0.9946866, "M": 18.7767, "S": 0.1427322}, {"decimal_age": 10.25, "L": -1.003867, "M": 18.8196, "S": 0.1432159}, @@ -1114,7 +1114,7 @@ {"decimal_age": 10.75, "L": -1.057258, "M": 19.0819, "S": 0.1460552}, {"decimal_age": 10.83, "L": -1.065889, "M": 19.1264, "S": 0.1465182}, {"decimal_age": 10.92, "L": -1.074447, "M": 19.1711, "S": 0.1469781}, - {"decimal_age": 11, "L": -1.082934, "M": 19.2159, "S": 0.1474352}, + {"decimal_age": 11.0, "L": -1.082934, "M": 19.2159, "S": 0.1474352}, {"decimal_age": 11.08, "L": -1.091351, "M": 19.261, "S": 0.1478893}, {"decimal_age": 11.17, "L": -1.0997, "M": 19.3062, "S": 0.1483408}, {"decimal_age": 11.25, "L": -1.107981, "M": 19.3516, "S": 0.1487894}, @@ -1126,7 +1126,7 @@ {"decimal_age": 11.75, "L": -1.156312, "M": 19.6269, "S": 0.1514243}, {"decimal_age": 11.83, "L": -1.164152, "M": 19.6732, "S": 0.1518542}, {"decimal_age": 11.92, "L": -1.171933, "M": 19.7196, "S": 0.1522817}, - {"decimal_age": 12, "L": -1.179656, "M": 19.7661, "S": 0.1527067}, + {"decimal_age": 12.0, "L": -1.179656, "M": 19.7661, "S": 0.1527067}, {"decimal_age": 12.08, "L": -1.187322, "M": 19.8128, "S": 0.1531295}, {"decimal_age": 12.17, "L": -1.194933, "M": 19.8595, "S": 0.1535494}, {"decimal_age": 12.25, "L": -1.20249, "M": 19.9062, "S": 0.1539673}, @@ -1138,7 +1138,7 @@ {"decimal_age": 12.75, "L": -1.24676, "M": 20.1882, "S": 0.1564283}, {"decimal_age": 12.83, "L": -1.253968, "M": 20.2353, "S": 0.1568306}, {"decimal_age": 12.92, "L": -1.261131, "M": 20.2824, "S": 0.1572314}, - {"decimal_age": 13, "L": -1.268249, "M": 20.3295, "S": 0.1576303}, + {"decimal_age": 13.0, "L": -1.268249, "M": 20.3295, "S": 0.1576303}, {"decimal_age": 13.08, "L": -1.275322, "M": 20.3767, "S": 0.1580272}, {"decimal_age": 13.17, "L": -1.282351, "M": 20.4238, "S": 0.1584224}, {"decimal_age": 13.25, "L": -1.289338, "M": 20.4709, "S": 0.1588158}, @@ -1150,7 +1150,7 @@ {"decimal_age": 13.75, "L": -1.330389, "M": 20.7528, "S": 0.1611403}, {"decimal_age": 13.83, "L": -1.337092, "M": 20.7996, "S": 0.1615224}, {"decimal_age": 13.92, "L": -1.343757, "M": 20.8463, "S": 0.1619024}, - {"decimal_age": 14, "L": -1.350385, "M": 20.893, "S": 0.1622812}, + {"decimal_age": 14.0, "L": -1.350385, "M": 20.893, "S": 0.1622812}, {"decimal_age": 14.08, "L": -1.356975, "M": 20.9395, "S": 0.1626586}, {"decimal_age": 14.17, "L": -1.363529, "M": 20.9859, "S": 0.1630346}, {"decimal_age": 14.25, "L": -1.370047, "M": 21.0323, "S": 0.1634091}, @@ -1162,7 +1162,7 @@ {"decimal_age": 14.75, "L": -1.408424, "M": 21.308, "S": 0.1656287}, {"decimal_age": 14.83, "L": -1.414703, "M": 21.3536, "S": 0.1659941}, {"decimal_age": 14.92, "L": -1.420949, "M": 21.399, "S": 0.1663585}, - {"decimal_age": 15, "L": -1.427164, "M": 21.4442, "S": 0.166722}, + {"decimal_age": 15.0, "L": -1.427164, "M": 21.4442, "S": 0.166722}, {"decimal_age": 15.08, "L": -1.433347, "M": 21.4894, "S": 0.1670836}, {"decimal_age": 15.17, "L": -1.439499, "M": 21.5344, "S": 0.1674444}, {"decimal_age": 15.25, "L": -1.44562, "M": 21.5792, "S": 0.1678042}, @@ -1174,7 +1174,7 @@ {"decimal_age": 15.75, "L": -1.481732, "M": 21.8454, "S": 0.1699412}, {"decimal_age": 15.83, "L": -1.487652, "M": 21.8892, "S": 0.1702935}, {"decimal_age": 15.92, "L": -1.493545, "M": 21.9329, "S": 0.1706453}, - {"decimal_age": 16, "L": -1.499411, "M": 21.9765, "S": 0.170996}, + {"decimal_age": 16.0, "L": -1.499411, "M": 21.9765, "S": 0.170996}, {"decimal_age": 16.08, "L": -1.505251, "M": 22.0199, "S": 0.1713459}, {"decimal_age": 16.17, "L": -1.511065, "M": 22.0631, "S": 0.171695}, {"decimal_age": 16.25, "L": -1.516854, "M": 22.1062, "S": 0.1720431}, @@ -1186,7 +1186,7 @@ {"decimal_age": 16.75, "L": -1.551072, "M": 22.3614, "S": 0.1741151}, {"decimal_age": 16.83, "L": -1.556692, "M": 22.4034, "S": 0.1744578}, {"decimal_age": 16.92, "L": -1.562289, "M": 22.4453, "S": 0.1747996}, - {"decimal_age": 17, "L": -1.567864, "M": 22.487, "S": 0.1751407}, + {"decimal_age": 17.0, "L": -1.567864, "M": 22.487, "S": 0.1751407}, {"decimal_age": 17.08, "L": -1.573416, "M": 22.5285, "S": 0.1754814}, {"decimal_age": 17.17, "L": -1.578946, "M": 22.5699, "S": 0.1758212}, {"decimal_age": 17.25, "L": -1.584454, "M": 22.6112, "S": 0.17616}, @@ -1198,7 +1198,7 @@ {"decimal_age": 17.75, "L": -1.617057, "M": 22.8555, "S": 0.17818}, {"decimal_age": 17.83, "L": -1.622419, "M": 22.8957, "S": 0.1785144}, {"decimal_age": 17.92, "L": -1.62776, "M": 22.9357, "S": 0.1788482}, - {"decimal_age": 18, "L": -1.633082, "M": 22.9756, "S": 0.1791814}, + {"decimal_age": 18.0, "L": -1.633082, "M": 22.9756, "S": 0.1791814}, {"decimal_age": 18.08, "L": -1.638384, "M": 23.0154, "S": 0.1795139}, {"decimal_age": 18.17, "L": -1.643667, "M": 23.055, "S": 0.179846}, {"decimal_age": 18.25, "L": -1.64893, "M": 23.0945, "S": 0.1801772}, diff --git a/rcpchgrowth/global_functions.py b/rcpchgrowth/global_functions.py index 0fe2aa3..32ef822 100644 --- a/rcpchgrowth/global_functions.py +++ b/rcpchgrowth/global_functions.py @@ -36,10 +36,10 @@ def measurement_from_sds( observation_value = None try: observation_value = measurement_for_z(z=requested_sds, l=l, m=m, s=s) - return observation_value except Exception as e: print(e) return None + return observation_value def sds_for_measurement( reference: str, @@ -98,32 +98,34 @@ def generate_centile(z: float, centile: float, measurement_method: str, sex: str Takes the z-score equivalent of the centile, the centile to be used as a label, the sex and measurement method. """ + if (len(lms_array_for_measurement)==0): + raise Exception(f"No reference data available for {measurement_method} in {sex} in {reference}") + min_age = lms_array_for_measurement[0]["decimal_age"] max_age = lms_array_for_measurement[-1]["decimal_age"] # if this is an sds line, the label reflects the sds value. The default is to reflect the centile label_value = centile if is_sds: - label_value=round(z, 3) + label_value=round(z, 3) centile_measurements = [] age = min_age while age <= max_age: + measurement=0.0 #initialise # loop through the reference in steps of 0.1y try: measurement = measurement_from_sds( reference=reference, measurement_method=measurement_method, requested_sds=z, sex=sex, age=age) except Exception as err: - print(err) - measurement = None + print(f"Measurement Calculation Error: {err}") # creates a data point if measurement is not None: try: - rounded = round(measurement, 4) - except Exception as err: - # cannot round a complex number: set that as zero - rounded = None + rounded = round(measurement*10000)/10000 + except Exception as e: + print(f"{e} z:{z} age:{age} measurement: {measurement}") else: rounded = None value = { @@ -278,10 +280,22 @@ def linear_interpolation(age: float, age_one_below: float, age_one_above: float, def measurement_for_z(z: float, l: float, m: float, s: float) -> float: """ Returns a measurement for a z score, L, M and S + x = M (1 + L S z)^(1/L) + Note, in some circumstances, 1 + l * s * z will be negative, and + it will not be possible to calculate a power. + In these circumstances, None is returned """ + measurement_value=0.0 if l != 0.0: - # measurement_value = math.pow((1 + l * s * z), 1 / l) * m - measurement_value = ((1 + l * s * z) ** (1 / l)) * m + first_step= (1 + l * s * z) + exponent= 1 / l + if first_step < 0: + return None + try: + measurement_value= (first_step ** (1/exponent)) * m + except Exception as e: + print(e) + return else: measurement_value = math.exp(s * z) * m return measurement_value @@ -292,7 +306,6 @@ def z_score(l: float, m: float, s: float, observation: float): """ sds = 0.0 if l != 0.0: - # sds = (((math.pow((observation / m), l)) - 1) / (l * s)) sds = (((observation / m) ** l) - 1) / (l*s) else: sds = (math.log(observation / m) / s) diff --git a/rcpchgrowth/trisomy_21.py b/rcpchgrowth/trisomy_21.py index 6b7d5ff..6e2c249 100644 --- a/rcpchgrowth/trisomy_21.py +++ b/rcpchgrowth/trisomy_21.py @@ -69,7 +69,7 @@ def trisomy_21_lms_array_for_measurement_and_sex( if data_invalid: raise LookupError(data_error) else: - return TRISOMY_21_DATA["measurement"][measurement_method][sex] + return TRISOMY_21_DATA["measurement"][measurement_method][sex] def select_reference_data_for_trisomy_21(measurement_method:str, sex:str): try: