-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat: luminex xponent adapter (#255)
Add Luminex Xponent support.
- Loading branch information
Showing
14 changed files
with
32,766 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
160 changes: 160 additions & 0 deletions
160
src/allotropy/parsers/luminex_xponent/luminex_xponent_parser.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
from allotropy.allotrope.models.multi_analyte_profiling_benchling_2024_01_multi_analyte_profiling import ( | ||
AnalyteAggregateDocument, | ||
AnalyteDocumentItem, | ||
CalibrationAggregateDocument, | ||
CalibrationDocumentItem, | ||
DataSystemDocument, | ||
DeviceControlAggregateDocument, | ||
DeviceControlDocumentItem, | ||
DeviceSystemDocument, | ||
ErrorAggregateDocument, | ||
ErrorDocumentItem, | ||
MeasurementAggregateDocument, | ||
MeasurementDocumentItem, | ||
Model, | ||
MultiAnalyteProfilingAggregateDocument, | ||
MultiAnalyteProfilingDocumentItem, | ||
SampleDocument, | ||
) | ||
from allotropy.allotrope.models.shared.definitions.custom import ( | ||
TQuantityValueMicroliter, | ||
TQuantityValueNumber, | ||
TQuantityValueRelativeFluorescenceUnit, | ||
TQuantityValueUnitless, | ||
) | ||
from allotropy.allotrope.models.shared.definitions.definitions import ( | ||
TStatisticDatumRole, | ||
) | ||
from allotropy.constants import ASM_CONVERTER_NAME, ASM_CONVERTER_VERSION | ||
from allotropy.named_file_contents import NamedFileContents | ||
from allotropy.parsers.lines_reader import CsvReader, read_to_lines | ||
from allotropy.parsers.luminex_xponent.luminex_xponent_structure import ( | ||
Data, | ||
Header, | ||
Measurement, | ||
) | ||
from allotropy.parsers.utils.uuids import random_uuid_str | ||
from allotropy.parsers.vendor_parser import VendorParser | ||
|
||
DEFAULT_SOFTWARE_NAME = "xPONENT" | ||
DEFAULT_CONTAINER_TYPE = "well plate" | ||
DEFAULT_DEVICE_TYPE = "multi analyte profiling analyzer" | ||
|
||
|
||
class LuminexXponentParser(VendorParser): | ||
def to_allotrope(self, named_file_contents: NamedFileContents) -> Model: | ||
lines = read_to_lines(named_file_contents.contents) | ||
reader = CsvReader(lines) | ||
data = Data.create(reader, self.timestamp_parser) | ||
return self._get_model(named_file_contents.original_file_name, data) | ||
|
||
def _get_model(self, file_name: str, data: Data) -> Model: | ||
header = data.header | ||
return Model( | ||
field_asm_manifest="http://purl.allotrope.org/manifests/multi-analyte-profiling/BENCHLING/2024/01/multi-analyte-profiling.manifest", | ||
multi_analyte_profiling_aggregate_document=MultiAnalyteProfilingAggregateDocument( | ||
device_system_document=DeviceSystemDocument( | ||
model_number=header.model_number, | ||
equipment_serial_number=header.equipment_serial_number, | ||
calibration_aggregate_document=CalibrationAggregateDocument( | ||
calibration_document=[ | ||
CalibrationDocumentItem( | ||
calibration_name=calibration_item.name, | ||
calibration_report=calibration_item.report, | ||
calibration_time=calibration_item.time, | ||
) | ||
for calibration_item in data.calibration_data | ||
] | ||
), | ||
), | ||
data_system_document=DataSystemDocument( | ||
data_system_instance_identifier=header.data_system_instance_identifier, | ||
file_name=file_name, | ||
software_name=DEFAULT_SOFTWARE_NAME, | ||
software_version=header.software_version, | ||
ASM_converter_name=ASM_CONVERTER_NAME, | ||
ASM_converter_version=ASM_CONVERTER_VERSION, | ||
), | ||
multi_analyte_profiling_document=[ | ||
MultiAnalyteProfilingDocumentItem( | ||
analyst=header.analyst, | ||
measurement_aggregate_document=MeasurementAggregateDocument( | ||
analytical_method_identifier=header.analytical_method_identifier, | ||
method_version=header.method_version, | ||
experimental_data_identifier=header.experimental_data_identifier, | ||
container_type=DEFAULT_CONTAINER_TYPE, | ||
plate_well_count=TQuantityValueNumber( | ||
value=header.plate_well_count | ||
), | ||
measurement_document=[ | ||
self._get_measurement_document_item( | ||
measurement, | ||
header, | ||
data.minimum_bead_count_setting, | ||
) | ||
for measurement in data.measurement_list.measurements | ||
], | ||
), | ||
) | ||
], | ||
), | ||
) | ||
|
||
def _get_measurement_document_item( | ||
self, | ||
measurement: Measurement, | ||
header_data: Header, | ||
minimum_bead_count_setting: float, | ||
) -> MeasurementDocumentItem: | ||
error_aggregate_document = None | ||
if measurement.errors: | ||
error_aggregate_document = ErrorAggregateDocument( | ||
error_document=[ | ||
ErrorDocumentItem(error=error) for error in measurement.errors | ||
] | ||
) | ||
|
||
return MeasurementDocumentItem( | ||
measurement_identifier=random_uuid_str(), | ||
measurement_time=header_data.measurement_time, | ||
sample_document=SampleDocument( | ||
sample_identifier=measurement.sample_identifier, | ||
location_identifier=measurement.location_identifier, | ||
), | ||
device_control_aggregate_document=DeviceControlAggregateDocument( | ||
device_control_document=[ | ||
DeviceControlDocumentItem( | ||
device_type=DEFAULT_DEVICE_TYPE, | ||
sample_volume_setting=TQuantityValueMicroliter( | ||
value=header_data.sample_volume_setting | ||
), | ||
dilution_factor_setting=TQuantityValueUnitless( | ||
value=measurement.dilution_factor_setting | ||
), | ||
detector_gain_setting=header_data.detector_gain_setting, | ||
minimum_assay_bead_count_setting=TQuantityValueUnitless( | ||
value=minimum_bead_count_setting | ||
), | ||
) | ||
] | ||
), | ||
assay_bead_count=TQuantityValueNumber(value=measurement.assay_bead_count), | ||
analyte_aggregate_document=AnalyteAggregateDocument( | ||
analyte_document=[ | ||
AnalyteDocumentItem( | ||
analyte_identifier=random_uuid_str(), | ||
analyte_name=analyte.analyte_name, | ||
assay_bead_identifier=analyte.assay_bead_identifier, | ||
assay_bead_count=TQuantityValueNumber( | ||
value=analyte.assay_bead_count | ||
), | ||
fluorescence=TQuantityValueRelativeFluorescenceUnit( | ||
value=analyte.fluorescence, | ||
has_statistic_datum_role=TStatisticDatumRole.median_role, | ||
), | ||
) | ||
for analyte in measurement.analytes | ||
] | ||
), | ||
error_aggregate_document=error_aggregate_document, | ||
) |
Oops, something went wrong.