Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/allotropy/parsers/thermo_skanit/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@
"Ctrl": SampleRoleType.control_sample_role,
}
DEVICE_TYPE = "plate reader"

PLATE_IDENTIFIER_PATTERN = r"\b(?:\w+\s+)?plate(?:\s+\d+)?\b"
13 changes: 10 additions & 3 deletions src/allotropy/parsers/thermo_skanit/thermo_skanit_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
)
from allotropy.exceptions import AllotropyParserError
from allotropy.parsers.constants import NEGATIVE_ZERO, NOT_APPLICABLE
from allotropy.parsers.thermo_skanit.constants import DEVICE_TYPE, SAMPLE_ROLE_MAPPINGS
from allotropy.parsers.thermo_skanit.constants import (
DEVICE_TYPE,
PLATE_IDENTIFIER_PATTERN,
SAMPLE_ROLE_MAPPINGS,
)
from allotropy.parsers.utils.pandas import df_to_series_data, parse_header_row
from allotropy.parsers.utils.uuids import random_uuid_str
from allotropy.parsers.utils.values import try_float_or_none
Expand Down Expand Up @@ -443,8 +447,11 @@ def identify_data_and_sample_dfs(
reading_samples = False
continue

if "Plate" in row_str:
plate_match = re.search(r"Plate\s*(\d+)", row_str)
if "plate" in row_str.lower():
# Match "Plate 1", "Blank plate", "gch - Plate", etc.
Comment thread
joshua-benchling marked this conversation as resolved.
plate_match = re.search(
PLATE_IDENTIFIER_PATTERN, row_str, re.IGNORECASE
)
if plate_match:
current_plate_id = plate_match.group(0)
if current_plate_id not in plates_dict:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"$asm.manifest": "http://purl.allotrope.org/manifests/plate-reader/REC/2025/03/plate-reader.manifest",
"plate reader aggregate document": {
"plate reader document": [
{
"measurement aggregate document": {
"measurement document": [
{
"device control aggregate document": {
"device control document": [
{
"device type": "plate reader",
"detection type": "Absorbance",
"detector wavelength setting": {
"value": 260.0,
"unit": "nm"
},
"custom information document": {
"Plate adapter name": "96-well adapter for plate without lid",
"Optical response compensation": "Yes",
"Plate adapter number": 2.0
}
}
]
},
"measurement identifier": "THERMO_SKANIT_TEST_ID_0",
"sample document": {
"location identifier": "A2",
"sample identifier": "Blank1",
"sample role type": "blank role",
"well plate identifier": "Blank plate"
},
"absorbance": {
"value": 0.0499,
"unit": "mAU"
},
"experimental data identifier": "4-8-24 BD final"
}
],
"measurement time": "2024-05-08T15:54:50+00:00",
"plate well count": {
"value": 96,
"unit": "#"
},
"container type": "well plate"
}
},
{
"measurement aggregate document": {
"measurement document": [
{
"device control aggregate document": {
"device control document": [
{
"device type": "plate reader",
"detection type": "Absorbance",
"detector wavelength setting": {
"value": 260.0,
"unit": "nm"
},
"custom information document": {
"Plate adapter name": "96-well adapter for plate without lid",
"Optical response compensation": "Yes",
"Plate adapter number": 2.0
}
}
]
},
"measurement identifier": "THERMO_SKANIT_TEST_ID_1",
"sample document": {
"location identifier": "A2",
"sample identifier": "Un0001",
"sample role type": "unknown sample role",
"well plate identifier": "Sample Plate"
},
"absorbance": {
"value": 0.058,
"unit": "mAU"
},
"experimental data identifier": "4-8-24 BD final"
}
],
"measurement time": "2024-05-08T15:54:50+00:00",
"plate well count": {
"value": 96,
"unit": "#"
},
"container type": "well plate"
}
}
],
"data system document": {
"ASM file identifier": "skanit_different_plate_pattern.json",
"data system instance identifier": "N/A",
"UNC path": "tests/parsers/thermo_skanit/testdata/skanit_different_plate_pattern.xlsx",
"file name": "skanit_different_plate_pattern.xlsx",
"ASM converter name": "allotropy_thermo_fisher_scientific_skanit",
"ASM converter version": "0.1.109",
"software name": "SkanIt Software 7.0.2 RE for Microplate Readers RE",
"software version": "7.0.2.5",
"custom information document": {
"Dispenser": "No",
"ESW version": "1.00.38"
}
},
"device system document": {
"device identifier": "Varioskan LUX",
"model number": "Varioskan LUX",
"equipment serial number": "3020-83152"
}
}
}
Binary file not shown.
36 changes: 36 additions & 0 deletions tests/parsers/thermo_skanit/thermo_skanit_structure_test.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import re

import pandas as pd
import pytest

from allotropy.allotrope.models.shared.components.plate_reader import SampleRoleType
from allotropy.allotrope.schema_mappers.adm.plate_reader.rec._2025._03.plate_reader import (
MeasurementType,
)
from allotropy.parsers.thermo_skanit.constants import PLATE_IDENTIFIER_PATTERN
from allotropy.parsers.thermo_skanit.thermo_skanit_structure import (
DataThermoSkanIt,
DataWell,
Expand Down Expand Up @@ -201,3 +205,35 @@ def test_create_skanit_data() -> None:
skanit_data = DataThermoSkanIt.create(sheet_data=sheet_data, file_path="abc")
assert len(skanit_data.measurement_groups) == 96
assert skanit_data.metadata.equipment_serial_number == "3020-81776"


@pytest.mark.parametrize(
"input_string,expected_match",
[
("Plate 1", "Plate 1"),
("Plate 2", "Plate 2"),
("Plate 123", "Plate 123"),
("Blank plate", "Blank plate"),
("Sample Plate", "Sample Plate"),
("blank plate", "blank plate"),
("SAMPLE PLATE", "SAMPLE PLATE"),
("plate", "plate"),
],
)
def test_plate_identifier_regex_matching(
input_string: str, expected_match: str | None
) -> None:
"""Test that the plate identifier regex correctly matches valid plate names."""
match = re.search(PLATE_IDENTIFIER_PATTERN, input_string, re.IGNORECASE)

if expected_match is None:
assert (
match is None
), f"Expected no match for '{input_string}', but got '{match.group(0) if match else None}'"
else:
assert (
match is not None
), f"Expected to match '{expected_match}' in '{input_string}', but got no match"
assert (
match.group(0) == expected_match
), f"Expected '{expected_match}', but got '{match.group(0)}'"
Loading