diff --git a/tests/__init__.py b/tests/__init__.py index e69de29..8b13789 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/fixtures/tabular/data.csv b/tests/fixtures/tabular/data.csv new file mode 100644 index 0000000..aac51d8 --- /dev/null +++ b/tests/fixtures/tabular/data.csv @@ -0,0 +1,23 @@ +time;s0;s1;id +0.0;0.0;10.0;m0 +1.0;1.0;9.0;m0 +2.0;2.0;8.0;m0 +3.0;3.0;7.0;m0 +4.0;4.0;6.0;m0 +5.0;5.0;5.0;m0 +6.0;6.0;4.0;m0 +7.0;7.0;3.0;m0 +8.0;8.0;2.0;m0 +9.0;9.0;1.0;m0 +10.0;10.0;0.0;m0 +0.0;0.0;10.0;m1 +1.0;1.0;9.0;m1 +2.0;2.0;8.0;m1 +3.0;3.0;7.0;m1 +4.0;4.0;6.0;m1 +5.0;5.0;5.0;m1 +6.0;6.0;4.0;m1 +7.0;7.0;3.0;m1 +8.0;8.0;2.0;m1 +9.0;9.0;1.0;m1 +10.0;10.0;0.0;m1 diff --git a/tests/fixtures/tabular/data.xlsx b/tests/fixtures/tabular/data.xlsx new file mode 100644 index 0000000..bfec157 Binary files /dev/null and b/tests/fixtures/tabular/data.xlsx differ diff --git a/tests/fixtures/tabular/data_invalid.csv b/tests/fixtures/tabular/data_invalid.csv new file mode 100644 index 0000000..2199d4a --- /dev/null +++ b/tests/fixtures/tabular/data_invalid.csv @@ -0,0 +1,23 @@ +s0;s1;id +0.0;10.0;m0 +1.0;9.0;m0 +2.0;8.0;m0 +3.0;7.0;m0 +4.0;6.0;m0 +5.0;5.0;m0 +6.0;4.0;m0 +7.0;3.0;m0 +8.0;2.0;m0 +9.0;1.0;m0 +10.0;0.0;m0 +0.0;10.0;m1 +1.0;9.0;m1 +2.0;8.0;m1 +3.0;7.0;m1 +4.0;6.0;m1 +5.0;5.0;m1 +6.0;4.0;m1 +7.0;3.0;m1 +8.0;2.0;m1 +9.0;1.0;m1 +10.0;0.0;m1 diff --git a/tests/fixtures/tabular/data_invalid.xlsx b/tests/fixtures/tabular/data_invalid.xlsx new file mode 100644 index 0000000..1fb2882 Binary files /dev/null and b/tests/fixtures/tabular/data_invalid.xlsx differ diff --git a/tests/fixtures/tabular/data_invalid_chars.csv b/tests/fixtures/tabular/data_invalid_chars.csv new file mode 100644 index 0000000..2e89614 --- /dev/null +++ b/tests/fixtures/tabular/data_invalid_chars.csv @@ -0,0 +1,23 @@ +s0;s1;id +0.0;10.0;m0 +1.0;m1;m0 +2.0;8.0;m0 +3.0;7.0;m0 +m0;6.0;m0 +5.0;5.0;m0 +6.0;4.0;m0 +7.0;3.0;m0 +8.0;2.0;m0 +9.0;1.0;m0 +10.0;0.0;m0 +0.0;10.0;m1 +1.0;9.0;m1 +2.0;8.0;m1 +3.0;7.0;m1 +4.0;6.0;m1 +5.0;5.0;m1 +6.0;4.0;m1 +7.0;3.0;m1 +8.0;2.0;m1 +9.0;1.0;m1 +10.0;0.0;m1 diff --git a/tests/fixtures/tabular/measurement_export.csv b/tests/fixtures/tabular/measurement_export.csv new file mode 100644 index 0000000..e69de29 diff --git a/tests/fixtures/tabular/measurement_invalid.json b/tests/fixtures/tabular/measurement_invalid.json new file mode 100644 index 0000000..204c460 --- /dev/null +++ b/tests/fixtures/tabular/measurement_invalid.json @@ -0,0 +1,208 @@ +{ + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/", + "name": "schema:title", + "references": { + "@id": "schema:citation", + "@type": "@id" + }, + "created": "schema:dateCreated", + "modified": "schema:dateModified", + "creators": "schema:creator" + }, + "@id": "enzml:EnzymeMLDocument/32912026-6dad-4c20-97c4-d0924c8a60d7", + "@type": ["enzml:EnzymeMLDocument"], + "name": "Test", + "references": [], + "creators": [], + "vessels": [], + "proteins": [], + "complexes": [], + "small_molecules": [], + "reactions": [], + "measurements": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/", + "id": { + "@id": "schema:identifier", + "@type": "@id" + }, + "group_id": { + "@type": "@id" + } + }, + "@id": "enzml:Measurement/83505f32-65c8-44eb-a54e-07540deb6182", + "@type": ["enzml:Measurement"], + "id": "m1", + "name": "Measurement 2", + "species": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/", + "species_id": { + "@type": "@id" + } + }, + "@id": "enzml:MeasurementData/e802b437-075e-4c91-bba6-5c178d7f93a1", + "@type": ["enzml:MeasurementData"], + "species_id": "s1", + "init_conc": 0.0, + "data_type": "conc", + "data_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000063", + "@type": ["OBO:UO_0000000"], + "name": "mmol / l", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/e1ec421c-95c3-4eb0-aa7d-fd8c8f181816", + "@type": ["enzml:BaseUnit"], + "kind": "mole", + "exponent": 1, + "scale": -3.0 + }, + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/f84a3b44-1548-4280-a4ef-6ead5fc9fd48", + "@type": ["enzml:BaseUnit"], + "kind": "litre", + "exponent": -1, + "scale": 1.0 + } + ] + }, + "time_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000010", + "@type": ["OBO:UO_0000000"], + "name": "s", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/7974d9a4-3fa1-4c6f-91f4-d22a0af85655", + "@type": ["enzml:BaseUnit"], + "kind": "second", + "exponent": 1, + "scale": 1.0 + } + ] + }, + "time": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 8.0], + "data": [ + 0.0, 0.2, 0.4, 0.6000000000000001, 0.8, 1.0, 1.2000000000000002, + 1.4000000000000001, 1.6, 1.8 + ], + "is_calculated": false + }, + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/", + "species_id": { + "@type": "@id" + } + }, + "@id": "enzml:MeasurementData/00e58e3d-60ac-4501-813f-b6386398a8c1", + "@type": ["enzml:MeasurementData"], + "species_id": "s2", + "init_conc": 100.0, + "data_type": "conc", + "data_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000063", + "@type": ["OBO:UO_0000000"], + "name": "mmol / l", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/e1ec421c-95c3-4eb0-aa7d-fd8c8f181816", + "@type": ["enzml:BaseUnit"], + "kind": "mole", + "exponent": 1, + "scale": -3.0 + }, + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/f84a3b44-1548-4280-a4ef-6ead5fc9fd48", + "@type": ["enzml:BaseUnit"], + "kind": "litre", + "exponent": -1, + "scale": 1.0 + } + ] + }, + "time_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000010", + "@type": ["OBO:UO_0000000"], + "name": "s", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/7974d9a4-3fa1-4c6f-91f4-d22a0af85655", + "@type": ["enzml:BaseUnit"], + "kind": "second", + "exponent": 1, + "scale": 1.0 + } + ] + }, + "time": [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0], + "data": [100.0, 99.0, 98.0, 97.0, 96.0, 95.0, 94.0, 93.0, 92.0, 91.0], + "is_calculated": false + } + ] + } + ], + "equations": [], + "parameters": [] +} diff --git a/tests/fixtures/tabular/measurement_valid.json b/tests/fixtures/tabular/measurement_valid.json new file mode 100644 index 0000000..ed462a2 --- /dev/null +++ b/tests/fixtures/tabular/measurement_valid.json @@ -0,0 +1,523 @@ +{ + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/", + "name": "schema:title", + "references": { + "@id": "schema:citation", + "@type": "@id" + }, + "created": "schema:dateCreated", + "modified": "schema:dateModified", + "creators": "schema:creator" + }, + "@id": "enzml:EnzymeMLDocument/84fdaf73-0c33-4eb6-adc7-7f17b1523b4a", + "@type": [ + "enzml:EnzymeMLDocument" + ], + "name": "Test", + "references": [], + "creators": [], + "vessels": [], + "proteins": [], + "complexes": [], + "small_molecules": [], + "reactions": [], + "measurements": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/", + "id": { + "@id": "schema:identifier", + "@type": "@id" + }, + "group_id": { + "@type": "@id" + } + }, + "@id": "enzml:Measurement/111038ce-6e37-44da-a715-611c9b869bc9", + "@type": [ + "enzml:Measurement" + ], + "id": "m0", + "name": "Measurement 1", + "species": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/", + "species_id": { + "@type": "@id" + } + }, + "@id": "enzml:MeasurementData/8b78f5b5-25aa-4793-8a57-c0d791303f07", + "@type": [ + "enzml:MeasurementData" + ], + "species_id": "s1", + "init_conc": 0.0, + "data_type": "conc", + "data_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000063", + "@type": [ + "OBO:UO_0000000" + ], + "name": "mmol / l", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/b943545d-894b-445c-a745-c1215180ec8d", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "mole", + "exponent": 1, + "scale": -3.0 + }, + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/c85ac147-42ac-40d6-bc03-172be2f0d7ad", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "litre", + "exponent": -1, + "scale": 1.0 + } + ] + }, + "time_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000010", + "@type": [ + "OBO:UO_0000000" + ], + "name": "s", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/8aec2395-2071-48e9-85ed-120847dfe64a", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "second", + "exponent": 1, + "scale": 1.0 + } + ] + }, + "time": [ + 0.0, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 6.0, + 7.0, + 8.0, + 9.0 + ], + "data": [ + 0.0, + 0.1, + 0.2, + 0.30000000000000004, + 0.4, + 0.5, + 0.6000000000000001, + 0.7000000000000001, + 0.8, + 0.9 + ], + "is_calculated": false + }, + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/", + "species_id": { + "@type": "@id" + } + }, + "@id": "enzml:MeasurementData/e2fd62b6-88d6-4d87-b8df-a3747677c2eb", + "@type": [ + "enzml:MeasurementData" + ], + "species_id": "s2", + "init_conc": 10.0, + "data_type": "conc", + "data_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000063", + "@type": [ + "OBO:UO_0000000" + ], + "name": "mmol / l", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/b943545d-894b-445c-a745-c1215180ec8d", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "mole", + "exponent": 1, + "scale": -3.0 + }, + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/c85ac147-42ac-40d6-bc03-172be2f0d7ad", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "litre", + "exponent": -1, + "scale": 1.0 + } + ] + }, + "time_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000010", + "@type": [ + "OBO:UO_0000000" + ], + "name": "s", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/8aec2395-2071-48e9-85ed-120847dfe64a", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "second", + "exponent": 1, + "scale": 1.0 + } + ] + }, + "time": [ + 0.0, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 6.0, + 7.0, + 8.0, + 9.0 + ], + "data": [ + 10.0, + 9.0, + 8.0, + 7.0, + 6.0, + 5.0, + 4.0, + 3.0, + 2.0, + 1.0 + ], + "is_calculated": false + } + ] + }, + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/", + "id": { + "@id": "schema:identifier", + "@type": "@id" + }, + "group_id": { + "@type": "@id" + } + }, + "@id": "enzml:Measurement/996cb565-edf0-4b4c-871b-d9a288831c88", + "@type": [ + "enzml:Measurement" + ], + "id": "m1", + "name": "Measurement 2", + "species": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/", + "species_id": { + "@type": "@id" + } + }, + "@id": "enzml:MeasurementData/3c413494-54e7-4ba4-aeee-0382d778e0c9", + "@type": [ + "enzml:MeasurementData" + ], + "species_id": "s1", + "init_conc": 0.0, + "data_type": "conc", + "data_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000063", + "@type": [ + "OBO:UO_0000000" + ], + "name": "mmol / l", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/b943545d-894b-445c-a745-c1215180ec8d", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "mole", + "exponent": 1, + "scale": -3.0 + }, + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/c85ac147-42ac-40d6-bc03-172be2f0d7ad", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "litre", + "exponent": -1, + "scale": 1.0 + } + ] + }, + "time_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000010", + "@type": [ + "OBO:UO_0000000" + ], + "name": "s", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/8aec2395-2071-48e9-85ed-120847dfe64a", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "second", + "exponent": 1, + "scale": 1.0 + } + ] + }, + "time": [ + 0.0, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 6.0, + 7.0, + 8.0, + 9.0 + ], + "data": [ + 0.0, + 0.2, + 0.4, + 0.6000000000000001, + 0.8, + 1.0, + 1.2000000000000002, + 1.4000000000000001, + 1.6, + 1.8 + ], + "is_calculated": false + }, + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/", + "species_id": { + "@type": "@id" + } + }, + "@id": "enzml:MeasurementData/7af21a16-9cab-49e2-9250-278a4a57c91f", + "@type": [ + "enzml:MeasurementData" + ], + "species_id": "s2", + "init_conc": 100.0, + "data_type": "conc", + "data_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000063", + "@type": [ + "OBO:UO_0000000" + ], + "name": "mmol / l", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/b943545d-894b-445c-a745-c1215180ec8d", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "mole", + "exponent": 1, + "scale": -3.0 + }, + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/c85ac147-42ac-40d6-bc03-172be2f0d7ad", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "litre", + "exponent": -1, + "scale": 1.0 + } + ] + }, + "time_unit": { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "OBO:UO_0000010", + "@type": [ + "OBO:UO_0000000" + ], + "name": "s", + "base_units": [ + { + "@context": { + "enzml": "http://www.enzymeml.org/v2/", + "OBO": "http://purl.obolibrary.org/obo/", + "schema": "https://schema.org/" + }, + "@id": "enzml:BaseUnit/8aec2395-2071-48e9-85ed-120847dfe64a", + "@type": [ + "enzml:BaseUnit" + ], + "kind": "second", + "exponent": 1, + "scale": 1.0 + } + ] + }, + "time": [ + 0.0, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 6.0, + 7.0, + 8.0, + 9.0 + ], + "data": [ + 100.0, + 99.0, + 98.0, + 97.0, + 96.0, + 95.0, + 94.0, + 93.0, + 92.0, + 91.0 + ], + "is_calculated": false + } + ] + } + ], + "equations": [], + "parameters": [] +} \ No newline at end of file diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/unit/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/unit/test_equations.py b/tests/unit/test_equations.py new file mode 100644 index 0000000..3556555 --- /dev/null +++ b/tests/unit/test_equations.py @@ -0,0 +1,256 @@ +import pytest + +from pyenzyme.equations._math import build_equation, build_equations +from pyenzyme.equations._chem import build_reaction, build_reactions +from pyenzyme.units import M, second +from pyenzyme.model import EquationType + + +class TestMathEquations: + def test_parse_equation(self): + # Arrange + equation = "s1'(t) = kcat * p0(t) * s0(t)" + + # Act + equation = build_equation(equation, unit=M / second) + + # Assert + expected_vars = ["p0", "s0"] + expected_params = ["kcat"] + + assert ( + equation.species_id == "s1" + ), f"Species ID is not correct. Got {equation.species_id}" + assert ( + equation.equation == "kcat*p0*s0" + ), "Equation is not correct. Got {equation.equation.equation}" + assert equation.parameters[0].name == "kcat", "Parameter name is not correct" + assert ( + equation.parameters[0].symbol == "kcat" + ), "Parameter symbol is not correct" + + for var in equation.variables: + assert var.name in expected_vars + assert var.symbol in expected_vars + + for param in equation.parameters: + assert param.name in expected_params + assert param.symbol in expected_params + + def test_invalid_equation_no_left(self): + # Arrange + equation = "kcat * p0(t) * s0(t)" + + # Act + with pytest.raises(ValueError): + equation = build_equation(equation, unit=M / second) + + def test_invalid_equation_no_right(self): + # Arrange + equation = "s1'(t) =" + + # Act + with pytest.raises(ValueError): + equation = build_equation(equation, unit=M / second) + + def test_invalid_equation_no_equals(self): + # Arrange + equation = "s1'(t) kcat * p0(t) * s0(t)" + + # Act + with pytest.raises(ValueError): + equation = build_equation(equation, unit=M / second) + + def test_equation_with_funs(self): + # Arrange + equation = "s1'(t) = kcat * exp(p0(t) * t)" + + # Act + equation = build_equation(equation, unit=M / second) + + # Assert + assert ( + equation.species_id == "s1" + ), f"Species ID is not correct. Got {equation.species_id}" + assert ( + equation.equation == "kcat*exp(p0*t)" + ), f"Equation is not correct. Got {equation.equation}" + + def test_equation_with_fun_only_t(self): + # Arrange + equation = "s1'(t) = kcat * exp(t)" + + # Act + equation = build_equation(equation, unit=M / second) + + # Assert + assert ( + equation.species_id == "s1" + ), f"Species ID is not correct. Got {equation.species_id}" + assert ( + equation.equation == "kcat*exp(t)" + ), f"Equation is not correct. Got {equation.equation}" + + def test_multiple_equations(self): + # Arrange + equations = [ + "s1'(t) = kcat * E_tot * s0(t)", + "E_tot = p0(t) + p1(t)", + ] + + # Act + units = [M / second, M] + equations = build_equations(*equations, units=units) + + # Assert + assert len(equations) == 2, f"Expected 2 equations. Got {len(equations)}" + + def test_init_assigment_equation(self): + # Arrange + equation = "E_tot = p0 + p1" + + # Act + equation = build_equation(equation, unit=M) + + # Assert + assert ( + equation.species_id == "E_tot" + ), f"Species ID is not correct. Got {equation.species_id}" + assert ( + equation.equation == "p0 + p1" + ), f"Equation is not correct. Got {equation.equation}" + assert ( + equation.equation_type == EquationType.INITIAL_ASSIGNMENT + ), f"Equation type is not correct. Got {equation.equation_type}" + + def test_assigment_equation(self): + # Arrange + equation = "E_tot(t) = p0 + p1" + + # Act + equation = build_equation(equation, unit=M) + + # Assert + assert ( + equation.species_id == "E_tot" + ), f"Species ID is not correct. Got {equation.species_id}" + assert ( + equation.equation == "p0 + p1" + ), f"Equation is not correct. Got {equation.equation}" + assert ( + equation.equation_type == EquationType.ASSIGNMENT + ), f"Equation type is not correct. Got {equation.equation_type}" + + +class TestChemEqautions: + def test_build_irrev_reaction(self): + # Arrange + reaction_str = "2 s1 + s2 -> 2 s3 + s4" + + # Act + reac = build_reaction( + id="R1", + name="Reaction 1", + scheme=reaction_str, + ) + + # Assert + expected = [ + (-2.0, "s1"), + (-1.0, "s2"), + (2.0, "s3"), + (1.0, "s4"), + ] + + assert reac.id == "R1", f"Reaction ID is not correct. Got {reac.id}" + assert ( + reac.name == "Reaction 1" + ), f"Reaction name is not correct. Got {reac.name}" + + for stoich, species in expected: + element = next( + filter(lambda x: x.species_id == species, reac.species), None + ) + + if not element: + assert False, f"Species {species} not found in reaction" + + assert ( + element.stoichiometry == stoich + ), f"Stoichiometry for {species} is not correct. Got {element.stoichiometry}" + + assert ( + element.species_id == species + ), f"Species ID for {species} is not correct. Got {element.species_id}" + + def test_build_rev_reaction(self): + # Arrange + reaction_str = "s1 + s2 <=> s3 + s4" + + # Act + reac = build_reaction( + id="R1", + name="Reaction 1", + scheme=reaction_str, + ) + + # Assert + assert reac.reversible is True, "Reaction is not reversible" + + def test_build_w_modifiers(self): + # Arrange + reaction_str = "s1 + s2 -> s3 + s4" + + # Act + reac = build_reaction( + id="R1", + name="Reaction 1", + scheme=reaction_str, + modifiers=["s5", "s6"], + ) + + # Assert + assert ( + len(reac.modifiers) == 2 + ), f"Expected 2 modifiers. Got {len(reac.modifiers)}" + + def test_build_invalid_reaction(self): + # Arrange + reaction_str = "s1 + s2 + s3" + + # Act + with pytest.raises(ValueError): + build_reaction("R1", "Reaction 1", reaction_str) + + def test_build_multiple_reactions(self): + # Arrange + reactions = [ + "s1 + s2 -> s3 + s4", + "s2 -> s5", + ] + + # Act + reacs = build_reactions(*reactions) + + # Assert + assert len(reacs) == 2, f"Expected 2 reactions. Got {len(reacs)}" + + def test_build_multiple_reactions_w_modifiers(self): + # Arrange + reactions = [ + "s1 + s2 -> s3 + s4", + "s2 -> s5", + ] + + # Act + modifiers = {"r1": ["p0"]} + reacs = build_reactions(*reactions, modifiers=modifiers) + + # Assert + assert len(reacs) == 2, f"Expected 2 reactions. Got {len(reacs)}" + + r0 = reacs[0] + assert len(r0.modifiers) == 1, f"Expected 1 modifier. Got {len(r0.modifiers)}" + + r1 = reacs[1] + assert len(r1.modifiers) == 0, f"Expected 0 modifiers. Got {len(r1.modifiers)}" diff --git a/tests/unit/test_tabular.py b/tests/unit/test_tabular.py new file mode 100644 index 0000000..821faa3 --- /dev/null +++ b/tests/unit/test_tabular.py @@ -0,0 +1,147 @@ +import pytest +import pandas as pd +import pyenzyme as pe + +from pyenzyme.units import mM, s +from pyenzyme.tabular import _measurement_to_pandas, to_pandas + + +class TestTabularExport: + def test_single_measurement(self, measurement_valid): + """Test that a single measurement can be converted to a pandas DataFrame""" + + # Act + df = _measurement_to_pandas(measurement_valid.measurements[0]) + + # Assert + assert isinstance(df, pd.DataFrame), f"Expected a DataFrame. Got {type(df)}" + + def test_invalid_measurement(self, measurement_invalid): + """Test that an invalid measurement raises a ValueError""" + + # Act + with pytest.raises(ValueError): + _measurement_to_pandas(measurement_invalid.measurements[0]) + + def test_multiple_measurements(self, measurement_valid): + """Test that multiple measurements can be converted to a pandas DataFrame""" + + # Act + df = to_pandas(measurement_valid) + + # Assert + total_time_len = sum( + [len(m.species[0].time) for m in measurement_valid.measurements] + ) + + assert ( + df.shape[0] == total_time_len + ), f"Expected {total_time_len} rows. Got {df.shape[0]}" + assert df.shape[1] == 4, f"Expected 4 columns. Got {df.shape[1]}" + assert isinstance(df, pd.DataFrame), f"Expected a DataFrame. Got {type(df)}" + assert ( + df["id"].nunique() == 2 + ), f"Expected 2 unique IDs. Got {df['id'].nunique()}" + + for measurement in measurement_valid.measurements: + df_sub = df[df["id"] == measurement.id] + assert df_sub.shape[0] == len( + measurement.species[0].time + ), f"Expected {len(measurement.species[0].time)} rows. Got {df_sub.shape[0]}" + + for species in measurement.species: + assert ( + species.species_id in df.columns + ), f"Expected column for {species}" + + +class TestTabularImport: + def test_csv_import(self): + """Test that a CSV file can be imported to a pandas DataFrame""" + # Act + meas = pe.read_csv("tests/fixtures/tabular/data.csv", data_unit=mM, time_unit=s) + + # Assert + assert len(meas) == 2, f"Expected 2 measurements. Got {len(meas)}" + + for m in meas: + assert len(m.species) == 2, f"Expected 2 species. Got {len(m.species)}" + assert ( + len(m.species[0].time) == 11 + ), f"Expected 10 time points. Got {len(m.species[0].time)}" + assert ( + len(m.species[1].time) == 11 + ), f"Expected 10 time points. Got {len(m.species[1].time)}" + assert ( + m.species[0].data_unit == mM + ), f"Expected mM. Got {m.species[0].data_unit}" + assert ( + m.species[0].time_unit == s + ), f"Expected s. Got {m.species[0].time_unit}" + assert ( + m.species[1].data_unit == mM + ), f"Expected mM. Got {m.species[1].data_unit}" + assert ( + m.species[1].time_unit == s + ), f"Expected s. Got {m.species[1].time_unit}" + + def test_excel_import(self): + """Test that a Excel file can be imported to a pandas DataFrame""" + # Act + meas = pe.read_excel( + "tests/fixtures/tabular/data.xlsx", data_unit=mM, time_unit=s + ) + + # Assert + assert len(meas) == 2, f"Expected 2 measurements. Got {len(meas)}" + + for m in meas: + assert len(m.species) == 2, f"Expected 2 species. Got {len(m.species)}" + assert ( + len(m.species[0].time) == 11 + ), f"Expected 10 time points. Got {len(m.species[0].time)}" + assert ( + len(m.species[1].time) == 11 + ), f"Expected 10 time points. Got {len(m.species[1].time)}" + assert ( + m.species[0].data_unit == mM + ), f"Expected mM. Got {m.species[0].data_unit}" + assert ( + m.species[0].time_unit == s + ), f"Expected s. Got {m.species[0].time_unit}" + assert ( + m.species[1].data_unit == mM + ), f"Expected mM. Got {m.species[1].data_unit}" + assert ( + m.species[1].time_unit == s + ), f"Expected s. Got {m.species[1].time_unit}" + + def test_invalid_types(self): + """Test that an invalid CSV raises a ValueError""" + # Act + with pytest.raises(AssertionError): + pe.read_csv( + "tests/fixtures/tabular/data_invalid_chars.csv", + data_unit=mM, + time_unit=s, + ) + + def test_invalid_csv(self): + """Test that an invalid CSV raises a ValueError""" + # Act + with pytest.raises(AssertionError): + pe.read_csv( + "tests/fixtures/tabular/data_invalid.csv", + data_unit=mM, + time_unit=s, + ) + + def test_invalid_excel(self): + """Test that an invalid Excel raises a ValueError""" + # Act + with pytest.raises(AssertionError): + pe.read_excel( + "tests/fixtures/tabular/data_invalid.xlsx", + data_unit=mM, + time_unit=s, + )