Skip to content

Commit adeb3a4

Browse files
fix: Support EnVision calculated formulas without a name prefix (#1246)
## Summary A PerkinElmer EnVision 384-well absorbance export (`OD450`) failed to parse: ``` AllotropeConversionError: Unable to find expected formula name for calculated results section. ``` The calculated plate's `Formula` is a plain description with no `name =` prefix: ``` Calc 1: OD450 direct absorbance value at 450 nm ``` `CalculatedPlateInfo.create` extracted the name with `^([^=]*)=`, which assumes the standard form `Calc N: <name> = <expression>` and raised when no `=` was present. ## Fix When the formula has no `=`, fall back to using the whole formula string as the calculated data name. Standard formulas are unaffected. ## Changes - `perkin_elmer_envision_structure.py`: make the formula-name regex optional with a whole-string fallback. - Reworked `test_create_calculated_plate_info_with_invalid_formula` → `test_create_calculated_plate_info_with_formula_without_name` to assert the fallback. - Edited the formula in the existing `PE_Envision_fluorescence_example01.csv` to the no-`=` form (and regenerated its expected JSON) to exercise the fallback end-to-end. Other example files retain the standard `name = expression` form, so both branches stay covered. ## Testing - All 24 `perkin_elmer_envision` tests pass; `hatch run lint` (ruff, black, mypy) clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 1b963ec commit adeb3a4

4 files changed

Lines changed: 118 additions & 109 deletions

File tree

src/allotropy/parsers/perkin_elmer_envision/perkin_elmer_envision_structure.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,12 @@ class CalculatedPlateInfo(PlateInfo):
119119
def create(data: SeriesData) -> CalculatedPlateInfo:
120120
formula = data[str, "Formula"]
121121

122-
name = assert_not_none(
123-
search(r"^([^=]*)=", formula),
124-
msg="Unable to find expected formula name for calculated results section.",
125-
).group(1)
122+
# Standard formulas embed the name before an '=' (e.g.
123+
# "Calc 1: General = (X / Y) * Z where ..."). Some formulas are a plain
124+
# description with no '=' (e.g. "Calc 1: OD450 direct absorbance value at
125+
# 450 nm"), in which case the whole formula string is the name.
126+
formula_name_match = search(r"^([^=]*)=", formula)
127+
name = formula_name_match.group(1) if formula_name_match else formula
126128

127129
plate_number, barcode = PlateInfo.get_plate_number_and_barcode(data)
128130

tests/parsers/perkin_elmer_envision/perkin_elmer_envision_structure_test.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -345,20 +345,27 @@ def test_create_calculated_plate_info_with_no_formula() -> None:
345345
CalculatedPlateInfo.create(data)
346346

347347

348-
def test_create_calculated_plate_info_with_invalid_formula() -> None:
348+
def test_create_calculated_plate_info_with_formula_without_name() -> None:
349+
# Some formulas are a plain description with no "name =" prefix; the whole
350+
# formula string is used as the name.
349351
data = SeriesData(
350352
pd.Series(
351353
{
352354
"Plate": "dummy",
353355
"Measured height": "0",
354-
"Formula": "invalid formula",
356+
"Formula": "Calc 1: OD450 direct absorbance value at 450 nm",
355357
"Measurement date": "10/13/2022 3:08:06 PM",
356358
}
357359
)
358360
)
359-
msg = "Unable to find expected formula name for calculated results section."
360-
with pytest.raises(AllotropeConversionError, match=msg):
361-
CalculatedPlateInfo.create(data)
361+
calculated_plate_info = CalculatedPlateInfo.create(data)
362+
assert (
363+
calculated_plate_info.name == "Calc 1: OD450 direct absorbance value at 450 nm"
364+
)
365+
assert (
366+
calculated_plate_info.formula
367+
== "Calc 1: OD450 direct absorbance value at 450 nm"
368+
)
362369

363370

364371
def test_create_basic_assay_info() -> None:

tests/parsers/perkin_elmer_envision/testdata/PE_Envision_fluorescence_example01.csv

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
Plate information
22
Plate,Repeat,Barcode,Measured height,Chamber temperature at start,Chamber temperature at end,Humidity at start,Humidity at end,Ambient temperature at start,Ambient temperature at end,Formula,Measurement date,
3-
1,1,"=""""",N/A,N/A,N/A,N/A,N/A,N/A,N/A,Calc 1: General = (X / Y) * Z where X = AC HTRF Laser [Eu](1) channel 1 window 1 Y = AC HTRF Laser [Eu](1) channel 2 window 1 Z = 10000,10/13/2022 3:08:06 PM,
3+
1,1,"=""""",N/A,N/A,N/A,N/A,N/A,N/A,N/A,Calc 1: HTRF ratio value for AC HTRF Laser [Eu],10/13/2022 3:08:06 PM,
44

55
Background information
66
Plate,Label,Result,Signal,Flashes/Time,Meastime,MeasInfo,
77
1,AC HTRF Laser [Eu],0,162,50,00:00:00.000,De=1st Ex=Top Em=Top Wdw=1 (14),
88
1,AC HTRF Laser [Eu],0,260,50,00:00:00.000,De=2nd Ex=Top Em=Top Wdw=1 (142),
99

10-
Calculated results: Calc 1: General = (X / Y) * Z where X = AC HTRF Laser [Eu](1) channel 1 window 1 Y = AC HTRF Laser [Eu](1) channel 2 window 1 Z = 10000
10+
Calculated results: Calc 1: HTRF ratio value for AC HTRF Laser [Eu]
1111
,01,02,03,04,05,06,07,08,09,10,11,12,
1212
A,3912.12920565,3923.92517971,3948.45245355,,3933.03506298,4061.92827247,3996.61746992,,,,,,
1313
B,2385.72193555,2384.42487617,2396.10683014,,2390.61028269,2396.68321027,2424.70697585,,,,,,
@@ -119,8 +119,8 @@ H,- ,- ,- , ,- ,- ,- , , , , ,
119119
Calculations:
120120
Plate,,,,1
121121
Formula index,,,,Calc 1
122-
Formula name,,,,General
123-
Formula,,,,(X / Y) * Z where X = AC HTRF Laser [Eu](1) channel 1 window 1 Y = AC HTRF Laser [Eu](1) channel 2 window 1 Z = 10000
122+
Formula name,,,,HTRF ratio value for AC HTRF Laser [Eu]
123+
Formula,,,,HTRF ratio value for AC HTRF Laser [Eu]
124124

125125
Auto export parameters:
126126
Export format,,,,Plate2

0 commit comments

Comments
 (0)