55from .trisomy_21_aap import select_reference_data_for_trisomy_21_aap
66from .turner import select_reference_data_for_turner
77from .uk_who import select_reference_data_for_uk_who_chart
8+ from .who import who_reference , select_reference_data_for_who_chart
89from .constants .reference_constants import (
910 CDC_REFERENCES ,
1011 CDC ,
2526 TURNERS ,
2627 UK_WHO ,
2728 UK_WHO_REFERENCES ,
29+ WHO ,
30+ WHO_REFERENCES
2831)
2932
3033"""
@@ -70,6 +73,12 @@ def create_chart(
7073 sex = sex ,
7174 centile_format = centile_format ,
7275 is_sds = is_sds )
76+ elif reference == WHO :
77+ return create_who_chart (
78+ measurement_method = measurement_method ,
79+ sex = sex ,
80+ centile_format = centile_format ,
81+ is_sds = is_sds )
7382 else :
7483 print ("No reference data returned. Is there a spelling mistake in your reference?" )
7584
@@ -109,7 +118,7 @@ def generate_custom_sds_line(
109118 centile = custom_centile
110119 )
111120 except :
112- print ("Could not generate centile data." )
121+ print ("Could not generate centile data for UK-WHO ." )
113122 centile_data = []
114123 # all data can now be tagged by reference_name and added to reference_data
115124 reference_data .append ({reference : centile_data })
@@ -131,7 +140,30 @@ def generate_custom_sds_line(
131140 centile = custom_centile
132141 )
133142 except :
134- print (f"Could not generate SDS centile data." )
143+ print (f"Could not generate SDS centile data for { CDC } ." )
144+ centile_data = []
145+ # all data can now be tagged by reference_name and added to reference_data
146+ reference_data .append ({reference : centile_data })
147+ elif reference == WHO :
148+ for reference_index , reference in enumerate (WHO_REFERENCES ):
149+ # the centile reference data
150+ lms_array_for_measurement = select_reference_data_for_who_chart (
151+ who_reference_name = reference ,
152+ measurement_method = measurement_method ,
153+ sex = sex
154+ )
155+ centile_data = []
156+ try :
157+ centile_data = build_centile_object (
158+ reference = WHO ,
159+ measurement_method = measurement_method ,
160+ sex = sex ,
161+ lms_array_for_measurement = lms_array_for_measurement ,
162+ z = custom_sds ,
163+ centile = custom_centile
164+ )
165+ except :
166+ print (f"Could not generate SDS centile data for WHO." )
135167 centile_data = []
136168 # all data can now be tagged by reference_name and added to reference_data
137169 reference_data .append ({reference : centile_data })
@@ -219,6 +251,8 @@ def select_reference_lms_data(reference: str, measurement_method: str, sex: str)
219251 lms_array_for_measurement = select_reference_data_for_trisomy_21 (measurement_method = measurement_method , sex = sex )
220252 elif reference == CDC :
221253 lms_array_for_measurement = select_reference_data_for_cdc_chart (measurement_method = measurement_method , sex = sex )
254+ elif reference == WHO :
255+ lms_array_for_measurement = select_reference_data_for_who_chart (measurement_method = measurement_method , sex = sex )
222256 else :
223257 raise Exception ("No data has been selected!" )
224258
@@ -907,7 +941,163 @@ def create_trisomy_21_aap_chart(measurement_method: str, sex: str, centile_forma
907941 ]
908942 """
909943
910- # Private functions
944+ def create_who_chart (
945+ measurement_method : str ,
946+ sex : str ,
947+ centile_format : Union [str , list ] = COLE_TWO_THIRDS_SDS_NINE_CENTILES ,
948+ is_sds = False
949+ ):
950+
951+ # user selects which centile collection they want, for sex and measurement_method
952+ # If the Cole method is selected, conversion between centile and SDS
953+ # is different as SDS is rounded to the nearest 2/3
954+ # Cole method selection is stored in the cole_method flag.
955+ # If no parameter is passed, default is the Cole method
956+ # Alternatively it is possible to pass a custom list of values - if the is_sds flag is False (default) these are centiles
957+
958+ centile_sds_collection = []
959+ cole_method = False
960+
961+ if (type (centile_format ) is list ):
962+ # a custom list of centiles was provided
963+ centile_sds_collection = centile_format
964+ else :
965+ # a standard centile collection was selected
966+ centile_sds_collection = select_centile_format (centile_format )
967+ is_sds = False
968+
969+ ##
970+ # iterate through the 3 references that make up CDC (Fenton, WHO, CDC itself)
971+ # There will be a list for each one
972+ ##
973+
974+ # all data for a given reference are stored here: this is returned to the user
975+ reference_data = []
976+
977+ for reference_index , reference_name in enumerate (WHO_REFERENCES ):
978+ sex_list : dict = {} # all the data for a given sex are stored here
979+ # For each reference we have 2 sexes
980+ # for sex_index, sex in enumerate(SEXES):
981+ # For each sex we have 4 measurement_methods
982+
983+ measurements : dict = {} # all the data for a given measurement_method are stored here
984+
985+ # for measurement_index, measurement_method in enumerate(MEASUREMENT_METHODS):
986+ # for every measurement method we have as many centiles
987+ # as have been requested
988+
989+ centiles = [] # all generated centiles for a selected centile collection are stored here
990+
991+ default_youngest_reference = False
992+ if reference_index == 1 : # WHO children
993+ default_youngest_reference = True
994+
995+ # the centile reference data
996+ try :
997+ lms_array_for_measurement = select_reference_data_for_who_chart (
998+ who_reference_name = reference_name ,
999+ measurement_method = measurement_method ,
1000+ sex = sex ,
1001+ default_youngest_reference = default_youngest_reference )
1002+ except :
1003+ lms_array_for_measurement = []
1004+
1005+ for centile_index , centile_sds in enumerate (centile_sds_collection ):
1006+ # we must create a z for each requested centile
1007+ # if the Cole 9 centiles were selected, these are rounded,
1008+ # so conversion to SDS is different
1009+ # Otherwise standard conversation of centile to z is used
1010+
1011+ z = 0.0 #initialise
1012+ centile_value = 0.0 #initialise
1013+
1014+ if cole_method :
1015+ z = rounded_sds_for_centile (centile_sds ) # a centile was provided, so convert to z
1016+ centile_value = centile_sds # store the original centile value
1017+ else :
1018+ if (is_sds ):
1019+ z = centile_sds # an sds was supplied
1020+ centile_value = centile (centile_sds ) # convert the z to a centile and store
1021+ else :
1022+ z = sds_for_centile (centile_sds ) # a centile was provided, so convert to z
1023+ centile_value = centile_sds # store the original centile value
1024+ centile_data = []
1025+
1026+ try :
1027+ # Generate a centile. there will be nine of these if Cole method selected.
1028+ # Some data does not exist at all ages, so any error reflects missing data.
1029+ # If this happens, an empty list is returned.
1030+ centile_data = generate_centile (
1031+ z = z ,
1032+ centile = centile_value ,
1033+ measurement_method = measurement_method ,
1034+ sex = sex ,
1035+ lms_array_for_measurement = lms_array_for_measurement ,
1036+ reference = WHO ,
1037+ is_sds = is_sds ,
1038+ default_youngest_reference = default_youngest_reference
1039+ )
1040+ except LookupError as e :
1041+ print (f"Not possible to generate centile data for WHO { measurement_method } in { sex } s. { e } " )
1042+ centile_data = None
1043+ # Store this centile for a given measurement
1044+
1045+ centiles .append ({"sds" : round (z * 100 ) / 100 ,
1046+ "centile" : centile_value , "data" : centile_data })
1047+
1048+ # this is the end of the centile_collection for loop
1049+ # All the centiles for this measurement, sex and reference are added to the measurements list
1050+ measurements .update ({measurement_method : centiles })
1051+
1052+ # this is the end of the measurement_methods loop
1053+ # All data for all measurement_methods for this sex are added to the sex_list list
1054+
1055+ sex_list .update ({sex : measurements })
1056+
1057+ # all data can now be tagged by reference_name and added to reference_data
1058+ reference_data .append ({reference_name : sex_list })
1059+
1060+ # returns a list of 4 references, each containing 2 lists for each sex,
1061+ # each sex in turn containing 4 datasets for each measurement_method
1062+ return reference_data
1063+
1064+ """
1065+ # return object structure
1066+ [ cdc_infant: {
1067+ male: {
1068+ height: [
1069+ {
1070+ sds: -2.667,
1071+ centile: 0.4
1072+ data: [{l: , x: , y: }, ....]
1073+ }
1074+ ],
1075+ weight: [...],
1076+ bmi: [...],
1077+ ofc: [...]
1078+ },
1079+ female {...}
1080+ },
1081+ cdc_child: {
1082+ male: {
1083+ height: [
1084+ {
1085+ sds: -2.667,
1086+ centile: 0.4
1087+ data: [{l: , x: , y: }, ....]
1088+ }
1089+ ],
1090+ weight: [...],
1091+ bmi: [...],
1092+ ofc: [...]
1093+ },
1094+ female {...}
1095+ }
1096+ ]
1097+ """
1098+
1099+
1100+
9111101def select_centile_format (centile_format : str ):
9121102 """
9131103 Select the centile format
0 commit comments