@@ -68,65 +68,45 @@ class Header:
6868
6969 @classmethod
7070 def create (
71- cls , header_data : pd .DataFrame , minimum_assay_bead_count_setting : float | None
71+ cls ,
72+ header_data : pd .DataFrame ,
73+ header_row : SeriesData ,
74+ minimum_assay_bead_count_setting : float | None ,
7275 ) -> Header :
73- info_row = SeriesData (header_data .iloc [0 ])
74- raw_datetime = info_row [str , "BatchStartTime" ]
75- sample_volume = info_row .get (str , ["SampleVolume" , "MaxSampleUptakeVolume" ])
76-
77- # Read all the keys first
78- software_version = info_row .get (str , "Build" )
79- equipment_serial_number = info_row .get (str , "SN" )
80- analytical_method_identifier = info_row .get (str , "ProtocolName" )
81- method_version = info_row .get (str , "ProtocolVersion" )
82- experimental_data_identifier = info_row .get (str , "Batch" )
83- detector_gain_setting = info_row .get (
84- str , ["ProtocolReporterGain" , "ProtocolOperatingMode" ]
85- )
86- data_system_instance_identifier = info_row [str , "ComputerName" ]
87- analyst = info_row .get (str , "Operator" )
88-
89- # Mark keys that are accessed directly in helper methods
90- if "Program" in header_data :
91- info_row .mark_read ("Program" )
92- if "ProtocolPlate" in header_data :
93- info_row .mark_read ("ProtocolPlate" )
94-
95- custom_info = {
96- "Country Code" : info_row .get (str , "Country Code" ),
97- "ProtocolDevelopingCompany" : info_row .get (str , "ProtocolDevelopingCompany" ),
98- "Version" : info_row .get (str , "Version" ),
99- # These properties will be used by the measurement groups down below.
100- "BatchStopTime" : info_row .get (str , "BatchStopTime" ),
101- "ProtocolDescription" : info_row .get (str , "ProtocolDescription" ),
102- }
76+ sample_volume = header_row .get (str , ["SampleVolume" , "MaxSampleUptakeVolume" ])
10377
104- info_row .get_unread (
105- skip = {
106- "Date" ,
107- },
108- )
78+ header_row .mark_read ({"Program" , "ProtocolPlate" , "Date" })
10979
110- # Build parameters dictionary
11180 return Header (
11281 model_number = cls ._get_model_number (header_data ),
113- software_version = software_version ,
114- equipment_serial_number = equipment_serial_number ,
115- analytical_method_identifier = analytical_method_identifier ,
116- method_version = method_version ,
117- experimental_data_identifier = experimental_data_identifier ,
82+ software_version = header_row . get ( str , "Build" ) ,
83+ equipment_serial_number = header_row . get ( str , "SN" ) ,
84+ analytical_method_identifier = header_row . get ( str , "ProtocolName" ) ,
85+ method_version = header_row . get ( str , "ProtocolVersion" ) ,
86+ experimental_data_identifier = header_row . get ( str , "Batch" ) ,
11887 sample_volume_setting = (
11988 try_float (sample_volume .split ()[0 ], "sample volume setting" )
12089 if sample_volume
12190 else None
12291 ),
12392 plate_well_count = cls ._get_plate_well_count (header_data ),
124- measurement_time = raw_datetime ,
125- detector_gain_setting = detector_gain_setting ,
126- data_system_instance_identifier = data_system_instance_identifier ,
93+ measurement_time = header_row [str , "BatchStartTime" ],
94+ detector_gain_setting = header_row .get (
95+ str , ["ProtocolReporterGain" , "ProtocolOperatingMode" ]
96+ ),
97+ data_system_instance_identifier = header_row [str , "ComputerName" ],
12798 minimum_assay_bead_count_setting = minimum_assay_bead_count_setting ,
128- analyst = analyst ,
129- custom_info = custom_info ,
99+ analyst = header_row .get (str , "Operator" ),
100+ custom_info = {
101+ "Country Code" : header_row .get (str , "Country Code" ),
102+ "ProtocolDevelopingCompany" : header_row .get (
103+ str , "ProtocolDevelopingCompany"
104+ ),
105+ "Version" : header_row .get (str , "Version" ),
106+ # Used for the measurement groups
107+ "BatchStopTime" : header_row .get (str , "BatchStopTime" ),
108+ "ProtocolDescription" : header_row .get (str , "ProtocolDescription" ),
109+ },
130110 )
131111
132112 @classmethod
@@ -227,13 +207,12 @@ def create(
227207 results_data : dict [str , pd .DataFrame ],
228208 count_data : SeriesData ,
229209 bead_ids_data : SeriesData ,
230- header_data : pd . DataFrame ,
210+ header_row : SeriesData ,
231211 ) -> Measurement :
232212 location = str (count_data .series .name )
233213 dilution_factor_data = results_data ["Dilution Factor" ]
234214 errors_data = results_data .get ("Warnings/Errors" )
235215 measurement_identifier = random_uuid_str ()
236- header_row = SeriesData (header_data .iloc [0 ])
237216
238217 if location not in dilution_factor_data .index :
239218 msg = f"Could not find 'Dilution Factor' data for: '{ location } '."
@@ -334,10 +313,6 @@ def get_statistic_dimensions(analyte: str) -> list[StatisticDimension]:
334313 )
335314 )
336315
337- # Read the remaining keys from count_data
338- sample_identifier = count_data [str , "Sample" ]
339- assay_bead_count = count_data [float , "Total Events" ]
340-
341316 device_control_custom_info = {
342317 "ProtocolHeater" : header_row .get (str , "ProtocolHeater" ),
343318 "DDGate" : header_row .get (str , "DDGate" ),
@@ -352,26 +327,18 @@ def get_statistic_dimensions(analyte: str) -> list[StatisticDimension]:
352327 "BeadType" : header_row .get (str , "BeadType" ),
353328 }
354329
355- # Get unread keys after all keys have been read
356- count_data .get_unread ()
357- header_row .get_unread (
358- skip = {
359- "Date" ,
360- },
361- )
362-
363330 return Measurement (
364331 identifier = measurement_identifier ,
365- sample_identifier = sample_identifier ,
332+ sample_identifier = count_data [ str , "Sample" ] ,
366333 location_identifier = location_id ,
367334 dilution_factor_setting = dilution_factor_setting ,
368- assay_bead_count = assay_bead_count ,
335+ assay_bead_count = count_data [ float , "Total Events" ] ,
369336 analytes = analytes ,
370337 errors = errors ,
371338 calculated_data = calculated_data ,
372339 device_control_custom_info = device_control_custom_info ,
373340 sample_custom_info = sample_custom_info ,
374- measurement_custom_info = count_data .get_unread (),
341+ measurement_custom_info = count_data .get_unread () | header_row . get_unread () ,
375342 )
376343
377344 @classmethod
@@ -406,7 +373,7 @@ class MeasurementList:
406373
407374 @classmethod
408375 def create (
409- cls , results_data : dict [str , pd .DataFrame ], header_data : pd . DataFrame
376+ cls , results_data : dict [str , pd .DataFrame ], header_row : SeriesData
410377 ) -> MeasurementList :
411378 if missing_sections := [
412379 section for section in REQUIRED_SECTIONS if section not in results_data
@@ -433,12 +400,9 @@ def create_measurement(count_data: SeriesData) -> Measurement:
433400 results_data = results_data ,
434401 count_data = count_data ,
435402 bead_ids_data = bead_ids_data ,
436- header_data = header_data ,
403+ header_row = header_row ,
437404 )
438405
439- # Capture unread bead IDs data to prevent warnings
440- bead_ids_data .get_unread ()
441-
442406 return MeasurementList (map_rows (results_data ["Count" ], create_measurement ))
443407
444408
@@ -450,14 +414,14 @@ class Data:
450414
451415 @classmethod
452416 def create (cls , reader : LuminexXponentReader ) -> Data :
417+ header_row = SeriesData (reader .header_data .iloc [0 ])
418+
453419 return Data (
454420 header = Header .create (
455- reader .header_data , reader .minimum_assay_bead_count_setting
421+ reader .header_data , header_row , reader .minimum_assay_bead_count_setting
456422 ),
457423 calibrations = map_rows (reader .calibration_data , create_calibration ),
458- measurement_list = MeasurementList .create (
459- reader .results_data , reader .header_data
460- ),
424+ measurement_list = MeasurementList .create (reader .results_data , header_row ),
461425 )
462426
463427
@@ -518,7 +482,7 @@ def create_measurement_groups(
518482 )
519483 for measurement in measurements
520484 ]
521- # Remove the custom info that was used to create the measurement groups.
485+ # Remove the header custom info that was used to create the measurement groups.
522486 header .custom_info .pop ("BatchStopTime" , None )
523487 header .custom_info .pop ("ProtocolDescription" , None )
524488
0 commit comments