From 9191d382159c25df0706408fbfe22d2273a5af29 Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:39:27 -0500 Subject: [PATCH 01/12] Move examples into subdirs --- .../multicolor-particle-calibration-small.md | 0 examples/multicolor-particle-calibration.md | 69 ------------ examples/mutlicolor-particle-calibration.pdf | Bin 74693 -> 0 bytes .../multicolor-particle-calibration/README.md | 0 .../DefaultBehaviorSpecialization.json | 0 .../artifacts/multicolor-particle-calibration | 0 ...lor-particle-calibration-autoprotocol.json | 0 ...color-particle-calibration-emeraldcloud.nb | 0 ...lticolor-particle-calibration-execution.nt | 0 ...ulticolor-particle-calibration-protocol.nt | 0 ...ibration-strateos-launch-confirmation.json | 0 .../multicolor-particle-calibration.json | 0 .../multicolor-particle-calibration.md | 0 .../multicolor-particle-calibration.md.pdf | Bin .../multicolor-particle-calibration.nt | 0 .../multicolor-particle-calibration.pdf | Bin ...ticolor-particle-calibration_template.xlsx | Bin .../figures/serial_dilution.png | Bin .../metadata/sample_metadata.xlsx | Bin .../multicolor-particle-calibration.py | 0 .../multicolor-particle-calibration-small.md | 0 .../multicolor-particle-calibration-small.py | 0 .../DefaultBehaviorSpecialization.json | 0 .../artifacts/ecl-data.xlsx | Bin .../single-particle-calibration-execution.nt | 0 .../single-particle-calibration-protocol.nt | 0 .../artifacts/single-particle-calibration.md | 0 .../single-particle-calibration.md.pdf | Bin .../artifacts/single-particle-calibration.pdf | Bin .../single-particle-calibration_template.xlsx | Bin .../figures/serial_dilution.png | Bin .../single-particle-calibration.py | 0 .../DefaultBehaviorSpecialization.json | 0 .../singlecolor-particle-calibration | 0 ...alibration-emeraldcloud-stock-solutions.nb | 0 ...color-particle-calibration-emeraldcloud.nb | 0 ...glecolor-particle-calibration-execution.nt | 0 ...nglecolor-particle-calibration-protocol.nt | 0 .../singlecolor-particle-calibration.md | 0 .../singlecolor-particle-calibration.md.pdf | Bin .../singlecolor-particle-calibration.pdf | Bin ...lecolor-particle-calibration_template.xlsx | Bin .../figures/serial_dilution.png | Bin .../singlecolor-particle-calibration.py | 0 .../artifacts}/golden_gate_assembly.nt | 0 .../golden_gate_assembly.py | 0 .../growth-curve}/growth_curve.py | 0 .../InterLab 2022 - Calibration Protocol.pdf | Bin ...rLab 2022 - Calibration Protocol_v1.1.docx | Bin .../iGEM/artifacts}/InterLab 2022_Exp1.pdf | Bin .../artifacts}/InterLab 2022_Exp1_v1.1.docx | Bin .../artifacts}/InterLab 2022_Exp1_v1.1.pdf | Bin .../iGEM/artifacts}/InterLab 2022_Exp2.pdf | Bin .../artifacts}/InterLab 2022_Exp2_v1.1.docx | Bin .../artifacts}/InterLab 2022_Exp2_v1.1.pdf | Bin .../InterLab 2022_Exp3 Challenge.docx | Bin .../InterLab 2022_Exp3 Challenge.pdf | Bin .../InterLab 2022_Exp3 Standard.pdf | Bin ...terLab 2022_Exp3 Standard_prev_distro.docx | Bin ...nterLab 2022_Exp3 Standard_prev_distro.pdf | Bin .../InterLab 2022_Exp3 Standard_v1.2.2.docx | Bin .../InterLab 2022_Exp3 Standard_v1.2.2.pdf | Bin .../iGEM/artifacts}/interlab-endpoint.md | 0 .../iGEM/artifacts}/interlab-endpoint.pdf | Bin .../iGEM/artifacts}/interlab-exp1.md | 0 .../iGEM/artifacts}/interlab-exp1_MI.md | 0 .../iGEM/artifacts}/interlab-exp1_MI.pdf | Bin .../iGEM/artifacts}/interlab-exp2_MI.md | 0 .../iGEM/artifacts}/interlab-exp2_MI.pdf | Bin .../iGEM/artifacts}/interlab-exp2_from1.md | 0 .../artifacts}/interlab-exp3_challenge.docx | Bin .../artifacts}/interlab-exp3_challenge.md | 0 .../iGEM/artifacts}/interlab-timepoint-B.md | 0 .../iGEM/artifacts}/interlab-timepoint-B.pdf | Bin .../artifacts}/interlab-timepoint-B_AV.md | 0 .../figures}/Exp1_2_protocol_published.png | Bin .../iGEM/figures}/Layout_Exp2.png | Bin .../iGEM/figures}/fig1_cell_calibration.png | Bin .../iGEM/figures}/fig1_standard_protocol.png | Bin .../iGEM/figures}/fig3_cell_calibration.png | Bin .../iGEM/figures}/plate_map_exp1.png | Bin .../{ => protocols/iGEM}/interlab-endpoint.py | 0 .../{ => protocols/iGEM}/interlab-exp1.py | 0 .../{ => protocols/iGEM}/interlab-exp1_MI.py | 0 .../{ => protocols/iGEM}/interlab-exp2.py | 0 .../{ => protocols/iGEM}/interlab-exp2_MI.py | 0 .../iGEM}/interlab-exp2_from1.py | 0 .../iGEM}/interlab-exp3_challenge.py | 0 .../iGEM}/interlab-timepoint-B.py | 0 .../iGEM}/interlab-timepoint-B_AV.py | 0 .../{ => protocols/iGEM}/kit_coordinates.py | 0 .../{ => protocols/ludox}/LUDOX_protocol.py | 0 .../ludox/artifacts}/harmony22.md | 0 .../figures}/fig1_challenge_protocol.png | Bin .../ludox/figures}/fig2_cell_calibration.png | Bin .../opentrons_ludox_example.py | 0 .../opentrons-pcr}/opentrons_pcr_example.py | 0 .../opentrons-toy}/opentrons_toy_protocol.py | 0 .../{ => protocols}/pH_calibration/README.md | 0 .../pH_calibration/__init__.py | 0 .../pH_calibration/pH_calibration.py | 0 .../pH_calibration/ph_calibration_utils.py | 0 examples/serial_dilution copy.png | Bin 364969 -> 0 bytes examples/serial_dilution.png | Bin 364969 -> 0 bytes examples/test_LUDOX_markdown.md | 102 ------------------ 105 files changed, 171 deletions(-) delete mode 100644 examples/multicolor-particle-calibration-small.md delete mode 100644 examples/multicolor-particle-calibration.md delete mode 100644 examples/mutlicolor-particle-calibration.pdf rename examples/protocols/{ => calibration}/multicolor-particle-calibration/README.md (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/DefaultBehaviorSpecialization.json (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-autoprotocol.json (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-emeraldcloud.nb (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-execution.nt (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-protocol.nt (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-strateos-launch-confirmation.json (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.json (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.md (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.md.pdf (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.nt (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.pdf (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/artifacts/multicolor-particle-calibration_template.xlsx (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/figures/serial_dilution.png (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/metadata/sample_metadata.xlsx (100%) rename examples/protocols/{ => calibration}/multicolor-particle-calibration/multicolor-particle-calibration.py (100%) rename examples/protocols/{ => calibration}/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.md (100%) rename examples/protocols/{ => calibration}/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py (100%) rename examples/protocols/{ => calibration}/single-particle-calibration/artifacts/DefaultBehaviorSpecialization.json (100%) rename examples/protocols/{ => calibration}/single-particle-calibration/artifacts/ecl-data.xlsx (100%) rename examples/protocols/{ => calibration}/single-particle-calibration/artifacts/single-particle-calibration-execution.nt (100%) rename examples/protocols/{ => calibration}/single-particle-calibration/artifacts/single-particle-calibration-protocol.nt (100%) rename examples/protocols/{ => calibration}/single-particle-calibration/artifacts/single-particle-calibration.md (100%) rename examples/protocols/{ => calibration}/single-particle-calibration/artifacts/single-particle-calibration.md.pdf (100%) rename examples/protocols/{ => calibration}/single-particle-calibration/artifacts/single-particle-calibration.pdf (100%) rename examples/protocols/{ => calibration}/single-particle-calibration/artifacts/single-particle-calibration_template.xlsx (100%) rename examples/protocols/{ => calibration}/single-particle-calibration/figures/serial_dilution.png (100%) rename examples/protocols/{ => calibration}/single-particle-calibration/single-particle-calibration.py (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/artifacts/DefaultBehaviorSpecialization.json (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-emeraldcloud-stock-solutions.nb (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-emeraldcloud.nb (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-execution.nt (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-protocol.nt (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.md (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.md.pdf (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.pdf (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration_template.xlsx (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/figures/serial_dilution.png (100%) rename examples/protocols/{ => calibration}/singlecolor-particle-calibration/singlecolor-particle-calibration.py (100%) rename examples/{ => protocols/golden-gate-assembly/artifacts}/golden_gate_assembly.nt (100%) rename examples/{ => protocols/golden-gate-assembly}/golden_gate_assembly.py (100%) rename examples/{ => protocols/growth-curve}/growth_curve.py (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022 - Calibration Protocol.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022 - Calibration Protocol_v1.1.docx (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp1.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp1_v1.1.docx (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp1_v1.1.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp2.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp2_v1.1.docx (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp2_v1.1.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp3 Challenge.docx (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp3 Challenge.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp3 Standard.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp3 Standard_prev_distro.docx (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp3 Standard_prev_distro.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp3 Standard_v1.2.2.docx (100%) rename examples/{ => protocols/iGEM/artifacts}/InterLab 2022_Exp3 Standard_v1.2.2.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-endpoint.md (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-endpoint.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-exp1.md (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-exp1_MI.md (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-exp1_MI.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-exp2_MI.md (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-exp2_MI.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-exp2_from1.md (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-exp3_challenge.docx (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-exp3_challenge.md (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-timepoint-B.md (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-timepoint-B.pdf (100%) rename examples/{ => protocols/iGEM/artifacts}/interlab-timepoint-B_AV.md (100%) rename examples/{ => protocols/iGEM/figures}/Exp1_2_protocol_published.png (100%) rename examples/{ => protocols/iGEM/figures}/Layout_Exp2.png (100%) rename examples/{ => protocols/iGEM/figures}/fig1_cell_calibration.png (100%) rename examples/{ => protocols/iGEM/figures}/fig1_standard_protocol.png (100%) rename examples/{ => protocols/iGEM/figures}/fig3_cell_calibration.png (100%) rename examples/{ => protocols/iGEM/figures}/plate_map_exp1.png (100%) rename examples/{ => protocols/iGEM}/interlab-endpoint.py (100%) rename examples/{ => protocols/iGEM}/interlab-exp1.py (100%) rename examples/{ => protocols/iGEM}/interlab-exp1_MI.py (100%) rename examples/{ => protocols/iGEM}/interlab-exp2.py (100%) rename examples/{ => protocols/iGEM}/interlab-exp2_MI.py (100%) rename examples/{ => protocols/iGEM}/interlab-exp2_from1.py (100%) rename examples/{ => protocols/iGEM}/interlab-exp3_challenge.py (100%) rename examples/{ => protocols/iGEM}/interlab-timepoint-B.py (100%) rename examples/{ => protocols/iGEM}/interlab-timepoint-B_AV.py (100%) rename examples/{ => protocols/iGEM}/kit_coordinates.py (100%) rename examples/{ => protocols/ludox}/LUDOX_protocol.py (100%) rename examples/{ => protocols/ludox/artifacts}/harmony22.md (100%) rename examples/{ => protocols/ludox/figures}/fig1_challenge_protocol.png (100%) rename examples/{ => protocols/ludox/figures}/fig2_cell_calibration.png (100%) rename examples/{ => protocols/opentrons/opentrons-ludox}/opentrons_ludox_example.py (100%) rename examples/{ => protocols/opentrons/opentrons-pcr}/opentrons_pcr_example.py (100%) rename examples/{ => protocols/opentrons/opentrons-toy}/opentrons_toy_protocol.py (100%) rename examples/{ => protocols}/pH_calibration/README.md (100%) rename examples/{ => protocols}/pH_calibration/__init__.py (100%) rename examples/{ => protocols}/pH_calibration/pH_calibration.py (100%) rename examples/{ => protocols}/pH_calibration/ph_calibration_utils.py (100%) delete mode 100644 examples/serial_dilution copy.png delete mode 100644 examples/serial_dilution.png delete mode 100644 examples/test_LUDOX_markdown.md diff --git a/examples/multicolor-particle-calibration-small.md b/examples/multicolor-particle-calibration-small.md deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/multicolor-particle-calibration.md b/examples/multicolor-particle-calibration.md deleted file mode 100644 index 63cdd1d4..00000000 --- a/examples/multicolor-particle-calibration.md +++ /dev/null @@ -1,69 +0,0 @@ -# Multicolor fluorescence per bacterial particle calibration - -Plate readers report fluorescence values in arbitrary units that vary widely from instrument to instrument. Therefore absolute fluorescence values cannot be directly compared from one instrument to another. In order to compare fluorescence output of biological devices, it is necessary to create a standard fluorescence curve. This variant of the protocol uses two replicates of three colors of dye, plus beads. -Adapted from [https://dx.doi.org/10.17504/protocols.io.bht7j6rn](https://dx.doi.org/10.17504/protocols.io.bht7j6r) and [https://dx.doi.org/10.17504/protocols.io.6zrhf56](https://dx.doi.org/10.17504/protocols.io.6zrhf56) - - -## Protocol Outputs: -* `fluorescein and bead fluorescence measurements of calibration plate` -* `sulforhodamine 101 fluorescence measurements of calibration plate` -* `cascade blue fluorescence measurements of calibration plate` -* `absorbance measurements of calibration plate` - - -## Protocol Materials: -* [Water, sterile-filtered, BioReagent, suitable for cell culture](https://identifiers.org/pubchem.substance:24901740) -* [NanoCym 950 nm monodisperse silica nanoparticles](https://nanocym.com/wp-content/uploads/2018/07/NanoCym-All-Datasheets-.pdf) -* [Phosphate Buffered Saline](https://pubchem.ncbi.nlm.nih.gov/substance/329753341) -* [Fluorescein](https://pubchem.ncbi.nlm.nih.gov/substance/329753341) -* [Cascade Blue](https://pubchem.ncbi.nlm.nih.gov/substance/329753341) -* [Sulforhodamine](https://pubchem.ncbi.nlm.nih.gov/substance/329753341) - - -## Protocol Steps: -1. Provision the stock reagent container containing `Fluorescein calibrant` -2. Provision the stock reagent container containing `Sulforhodamine 101 calibrant` -3. Provision the stock reagent container containing `Cascade blue calibrant` -4. Provision the stock reagent container containing `NanoCym 950 nm microspheres` -5. Transfer 1.0 milliliter of `Phosphate Buffered Saline` sample to stock reagent container `Fluorescein calibrant`. The reconstituted `Fluorescein` should have a final concentration of 10 uM in `Phosphate Buffered Saline` -6. Vortex Fluorescein calibrant -7. Transfer 1.0 milliliter of `Phosphate Buffered Saline` sample to stock reagent container `Sulforhodamine 101 calibrant`. The reconstituted `Sulforhodamine` standard will have a final concentration of 2 uM in `Phosphate Buffered Saline` -8. Vortex Sulforhodamine 101 calibrant -9. Transfer 1.0 milliliter of `Water, sterile-filtered, BioReagent, suitable for cell culture` sample to stock reagent container `Cascade blue calibrant`. The reconstituted `Cascade Blue` calibrant will have a final concentration of 10 uM in `Water, sterile-filtered, BioReagent, suitable for cell culture`. -10. Vortex Cascade blue calibrant -11. Transfer 1.0 milliliter of `Water, sterile-filtered, BioReagent, suitable for cell culture` sample to stock reagent container `NanoCym 950 nm microspheres`. The resuspended `NanoCym 950 nm monodisperse silica nanoparticles` will have a final concentration of 3e9 microspheres/mL in `Water, sterile-filtered, BioReagent, suitable for cell culture`. -12. Vortex NanoCym 950 nm microspheres -13. Provision a 96 well microplate to contain `calibration plate` -14. Transfer 100.0 microliter of `Phosphate Buffered Saline` sample to wells A12:D12 of 96 well microplate `calibration plate`. These are blanks. -15. Transfer 100.0 microliter of `Water, sterile-filtered, BioReagent, suitable for cell culture` sample to wells E12:H12 of 96 well microplate `calibration plate`. These are blanks. -16. Transfer 200.0 microliter of `Fluorescein calibrant` sample to wells A1 of 96 well microplate `calibration plate`. -17. Transfer 200.0 microliter of `Fluorescein calibrant` sample to wells B1 of 96 well microplate `calibration plate`. -18. Transfer 200.0 microliter of `Sulforhodamine 101 calibrant` sample to wells C1 of 96 well microplate `calibration plate`. -19. Transfer 200.0 microliter of `Sulforhodamine 101 calibrant` sample to wells D1 of 96 well microplate `calibration plate`. -20. Transfer 200.0 microliter of `Cascade blue calibrant` sample to wells E1 of 96 well microplate `calibration plate`. -21. Transfer 200.0 microliter of `Cascade blue calibrant` sample to wells F1 of 96 well microplate `calibration plate`. -22. Transfer 200.0 microliter of `NanoCym 950 nm microspheres` sample to wells G1 of 96 well microplate `calibration plate`. -23. Transfer 200.0 microliter of `NanoCym 950 nm microspheres` sample to wells H1 of 96 well microplate `calibration plate`. -24. Perform a series of 10 2-fold dilutions on `Fluorescein calibrant` using `Phosphate Buffered Saline` as diluent to a final volume of 200.0 microliter in wells A1:A11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. - -![](/Users/bbartley/Dev/git/sd2/labop/examples/serial_dilution.png) - - -25. Perform a series of 10 2-fold dilutions on `Fluorescein calibrant` using `Phosphate Buffered Saline` as diluent to a final volume of 200.0 microliter in wells B1:B11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. -26. Perform a series of 10 2-fold dilutions on `Sulforhodamine 101 calibrant` using `Phosphate Buffered Saline` as diluent to a final volume of 200.0 microliter in wells C1:C11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. -27. Perform a series of 10 2-fold dilutions on `Sulforhodamine 101 calibrant` using `Phosphate Buffered Saline` as diluent to a final volume of 200.0 microliter in wells D1:D11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. -28. Perform a series of 10 2-fold dilutions on `Cascade blue calibrant` using `Water, sterile-filtered, BioReagent, suitable for cell culture` as diluent to a final volume of 200.0 microliter in wells E1:E11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. -29. Perform a series of 10 2-fold dilutions on `Cascade blue calibrant` using `Water, sterile-filtered, BioReagent, suitable for cell culture` as diluent to a final volume of 200.0 microliter in wells F1:F11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. -30. Perform a series of 10 2-fold dilutions on `NanoCym 950 nm microspheres` using `Water, sterile-filtered, BioReagent, suitable for cell culture` as diluent to a final volume of 200.0 microliter in wells G1:G11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. -31. Perform a series of 10 2-fold dilutions on `NanoCym 950 nm microspheres` using `Water, sterile-filtered, BioReagent, suitable for cell culture` as diluent to a final volume of 200.0 microliter in wells H1:H11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. -32. Discard 100.0 microliter from wells A11:H11 of 96 well microplate `calibration plate`. This step ensures that all wells contain an equivalent volume. Be sure to change pipette tips for every well to avoid cross-contamination -33. Transfer 100.0 microliter of `Phosphate Buffered Saline` sample to wells A1:D12 of 96 well microplate `calibration plate`. This will bring all wells to volume 200 microliter. -34. Transfer 100.0 microliter of `Water, sterile-filtered, BioReagent, suitable for cell culture` sample to wells E1:H12 of 96 well microplate `calibration plate`. This will bring all wells to volume 200 microliter. -35. Measure fluorescein and bead fluorescence of `calibration plate` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass. -36. Measure sulforhodamine 101 fluorescence of `calibration plate` with excitation wavelength of 561.0 nanometer and emission filter of 610.0 nanometer and 20.0 nanometer bandpass. -37. Measure cascade blue fluorescence of `calibration plate` with excitation wavelength of 405.0 nanometer and emission filter of 450.0 nanometer and 50.0 nanometer bandpass. -38. Measure absorbance of `calibration plate` at 600.0 nanometer. -39. Import data for `fluorescein and bead fluorescence measurements of calibration plate`, `sulforhodamine 101 fluorescence measurements of calibration plate`, `cascade blue fluorescence measurements of calibration plate`, `absorbance measurements of calibration plate` into provided Excel file. ---- -Timestamp: 2022-06-25 09:42:24.954472--- -Protocol version: 1.1b diff --git a/examples/mutlicolor-particle-calibration.pdf b/examples/mutlicolor-particle-calibration.pdf deleted file mode 100644 index 5e041eebfda8f120e215001eae2b4cb427a2f7f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 74693 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 SkI%qPqv0exJhxQkNd6B6Xa_I= diff --git a/examples/protocols/multicolor-particle-calibration/README.md b/examples/protocols/calibration/multicolor-particle-calibration/README.md similarity index 100% rename from examples/protocols/multicolor-particle-calibration/README.md rename to examples/protocols/calibration/multicolor-particle-calibration/README.md diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/DefaultBehaviorSpecialization.json b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/DefaultBehaviorSpecialization.json similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/DefaultBehaviorSpecialization.json rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/DefaultBehaviorSpecialization.json diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-autoprotocol.json b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-autoprotocol.json similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-autoprotocol.json rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-autoprotocol.json diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-emeraldcloud.nb b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-emeraldcloud.nb similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-emeraldcloud.nb rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-emeraldcloud.nb diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-execution.nt b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-execution.nt similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-execution.nt rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-execution.nt diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-protocol.nt b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-protocol.nt similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-protocol.nt rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-protocol.nt diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-strateos-launch-confirmation.json b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-strateos-launch-confirmation.json similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-strateos-launch-confirmation.json rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration-strateos-launch-confirmation.json diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.json b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.json similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.json rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.json diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.md b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.md similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.md rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.md diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.md.pdf b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.md.pdf similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.md.pdf rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.md.pdf diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.nt b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.nt similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.nt rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.nt diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.pdf b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.pdf similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.pdf rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration.pdf diff --git a/examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration_template.xlsx b/examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration_template.xlsx similarity index 100% rename from examples/protocols/multicolor-particle-calibration/artifacts/multicolor-particle-calibration_template.xlsx rename to examples/protocols/calibration/multicolor-particle-calibration/artifacts/multicolor-particle-calibration_template.xlsx diff --git a/examples/protocols/multicolor-particle-calibration/figures/serial_dilution.png b/examples/protocols/calibration/multicolor-particle-calibration/figures/serial_dilution.png similarity index 100% rename from examples/protocols/multicolor-particle-calibration/figures/serial_dilution.png rename to examples/protocols/calibration/multicolor-particle-calibration/figures/serial_dilution.png diff --git a/examples/protocols/multicolor-particle-calibration/metadata/sample_metadata.xlsx b/examples/protocols/calibration/multicolor-particle-calibration/metadata/sample_metadata.xlsx similarity index 100% rename from examples/protocols/multicolor-particle-calibration/metadata/sample_metadata.xlsx rename to examples/protocols/calibration/multicolor-particle-calibration/metadata/sample_metadata.xlsx diff --git a/examples/protocols/multicolor-particle-calibration/multicolor-particle-calibration.py b/examples/protocols/calibration/multicolor-particle-calibration/multicolor-particle-calibration.py similarity index 100% rename from examples/protocols/multicolor-particle-calibration/multicolor-particle-calibration.py rename to examples/protocols/calibration/multicolor-particle-calibration/multicolor-particle-calibration.py diff --git a/examples/protocols/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.md b/examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.md similarity index 100% rename from examples/protocols/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.md rename to examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.md diff --git a/examples/protocols/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py b/examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py similarity index 100% rename from examples/protocols/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py rename to examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py diff --git a/examples/protocols/single-particle-calibration/artifacts/DefaultBehaviorSpecialization.json b/examples/protocols/calibration/single-particle-calibration/artifacts/DefaultBehaviorSpecialization.json similarity index 100% rename from examples/protocols/single-particle-calibration/artifacts/DefaultBehaviorSpecialization.json rename to examples/protocols/calibration/single-particle-calibration/artifacts/DefaultBehaviorSpecialization.json diff --git a/examples/protocols/single-particle-calibration/artifacts/ecl-data.xlsx b/examples/protocols/calibration/single-particle-calibration/artifacts/ecl-data.xlsx similarity index 100% rename from examples/protocols/single-particle-calibration/artifacts/ecl-data.xlsx rename to examples/protocols/calibration/single-particle-calibration/artifacts/ecl-data.xlsx diff --git a/examples/protocols/single-particle-calibration/artifacts/single-particle-calibration-execution.nt b/examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration-execution.nt similarity index 100% rename from examples/protocols/single-particle-calibration/artifacts/single-particle-calibration-execution.nt rename to examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration-execution.nt diff --git a/examples/protocols/single-particle-calibration/artifacts/single-particle-calibration-protocol.nt b/examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration-protocol.nt similarity index 100% rename from examples/protocols/single-particle-calibration/artifacts/single-particle-calibration-protocol.nt rename to examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration-protocol.nt diff --git a/examples/protocols/single-particle-calibration/artifacts/single-particle-calibration.md b/examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration.md similarity index 100% rename from examples/protocols/single-particle-calibration/artifacts/single-particle-calibration.md rename to examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration.md diff --git a/examples/protocols/single-particle-calibration/artifacts/single-particle-calibration.md.pdf b/examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration.md.pdf similarity index 100% rename from examples/protocols/single-particle-calibration/artifacts/single-particle-calibration.md.pdf rename to examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration.md.pdf diff --git a/examples/protocols/single-particle-calibration/artifacts/single-particle-calibration.pdf b/examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration.pdf similarity index 100% rename from examples/protocols/single-particle-calibration/artifacts/single-particle-calibration.pdf rename to examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration.pdf diff --git a/examples/protocols/single-particle-calibration/artifacts/single-particle-calibration_template.xlsx b/examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration_template.xlsx similarity index 100% rename from examples/protocols/single-particle-calibration/artifacts/single-particle-calibration_template.xlsx rename to examples/protocols/calibration/single-particle-calibration/artifacts/single-particle-calibration_template.xlsx diff --git a/examples/protocols/single-particle-calibration/figures/serial_dilution.png b/examples/protocols/calibration/single-particle-calibration/figures/serial_dilution.png similarity index 100% rename from examples/protocols/single-particle-calibration/figures/serial_dilution.png rename to examples/protocols/calibration/single-particle-calibration/figures/serial_dilution.png diff --git a/examples/protocols/single-particle-calibration/single-particle-calibration.py b/examples/protocols/calibration/single-particle-calibration/single-particle-calibration.py similarity index 100% rename from examples/protocols/single-particle-calibration/single-particle-calibration.py rename to examples/protocols/calibration/single-particle-calibration/single-particle-calibration.py diff --git a/examples/protocols/singlecolor-particle-calibration/artifacts/DefaultBehaviorSpecialization.json b/examples/protocols/calibration/singlecolor-particle-calibration/artifacts/DefaultBehaviorSpecialization.json similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/artifacts/DefaultBehaviorSpecialization.json rename to examples/protocols/calibration/singlecolor-particle-calibration/artifacts/DefaultBehaviorSpecialization.json diff --git a/examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration b/examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration rename to examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration diff --git a/examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-emeraldcloud-stock-solutions.nb b/examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-emeraldcloud-stock-solutions.nb similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-emeraldcloud-stock-solutions.nb rename to examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-emeraldcloud-stock-solutions.nb diff --git a/examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-emeraldcloud.nb b/examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-emeraldcloud.nb similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-emeraldcloud.nb rename to examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-emeraldcloud.nb diff --git a/examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-execution.nt b/examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-execution.nt similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-execution.nt rename to examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-execution.nt diff --git a/examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-protocol.nt b/examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-protocol.nt similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-protocol.nt rename to examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration-protocol.nt diff --git a/examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.md b/examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.md similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.md rename to examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.md diff --git a/examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.md.pdf b/examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.md.pdf similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.md.pdf rename to examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.md.pdf diff --git a/examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.pdf b/examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.pdf similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.pdf rename to examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration.pdf diff --git a/examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration_template.xlsx b/examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration_template.xlsx similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration_template.xlsx rename to examples/protocols/calibration/singlecolor-particle-calibration/artifacts/singlecolor-particle-calibration_template.xlsx diff --git a/examples/protocols/singlecolor-particle-calibration/figures/serial_dilution.png b/examples/protocols/calibration/singlecolor-particle-calibration/figures/serial_dilution.png similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/figures/serial_dilution.png rename to examples/protocols/calibration/singlecolor-particle-calibration/figures/serial_dilution.png diff --git a/examples/protocols/singlecolor-particle-calibration/singlecolor-particle-calibration.py b/examples/protocols/calibration/singlecolor-particle-calibration/singlecolor-particle-calibration.py similarity index 100% rename from examples/protocols/singlecolor-particle-calibration/singlecolor-particle-calibration.py rename to examples/protocols/calibration/singlecolor-particle-calibration/singlecolor-particle-calibration.py diff --git a/examples/golden_gate_assembly.nt b/examples/protocols/golden-gate-assembly/artifacts/golden_gate_assembly.nt similarity index 100% rename from examples/golden_gate_assembly.nt rename to examples/protocols/golden-gate-assembly/artifacts/golden_gate_assembly.nt diff --git a/examples/golden_gate_assembly.py b/examples/protocols/golden-gate-assembly/golden_gate_assembly.py similarity index 100% rename from examples/golden_gate_assembly.py rename to examples/protocols/golden-gate-assembly/golden_gate_assembly.py diff --git a/examples/growth_curve.py b/examples/protocols/growth-curve/growth_curve.py similarity index 100% rename from examples/growth_curve.py rename to examples/protocols/growth-curve/growth_curve.py diff --git a/examples/InterLab 2022 - Calibration Protocol.pdf b/examples/protocols/iGEM/artifacts/InterLab 2022 - Calibration Protocol.pdf similarity index 100% rename from examples/InterLab 2022 - Calibration Protocol.pdf rename to examples/protocols/iGEM/artifacts/InterLab 2022 - Calibration Protocol.pdf diff --git a/examples/InterLab 2022 - Calibration Protocol_v1.1.docx b/examples/protocols/iGEM/artifacts/InterLab 2022 - Calibration Protocol_v1.1.docx similarity index 100% rename from examples/InterLab 2022 - Calibration Protocol_v1.1.docx rename to examples/protocols/iGEM/artifacts/InterLab 2022 - Calibration Protocol_v1.1.docx diff --git a/examples/InterLab 2022_Exp1.pdf b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp1.pdf similarity index 100% rename from examples/InterLab 2022_Exp1.pdf rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp1.pdf diff --git a/examples/InterLab 2022_Exp1_v1.1.docx b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp1_v1.1.docx similarity index 100% rename from examples/InterLab 2022_Exp1_v1.1.docx rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp1_v1.1.docx diff --git a/examples/InterLab 2022_Exp1_v1.1.pdf b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp1_v1.1.pdf similarity index 100% rename from examples/InterLab 2022_Exp1_v1.1.pdf rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp1_v1.1.pdf diff --git a/examples/InterLab 2022_Exp2.pdf b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp2.pdf similarity index 100% rename from examples/InterLab 2022_Exp2.pdf rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp2.pdf diff --git a/examples/InterLab 2022_Exp2_v1.1.docx b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp2_v1.1.docx similarity index 100% rename from examples/InterLab 2022_Exp2_v1.1.docx rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp2_v1.1.docx diff --git a/examples/InterLab 2022_Exp2_v1.1.pdf b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp2_v1.1.pdf similarity index 100% rename from examples/InterLab 2022_Exp2_v1.1.pdf rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp2_v1.1.pdf diff --git a/examples/InterLab 2022_Exp3 Challenge.docx b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Challenge.docx similarity index 100% rename from examples/InterLab 2022_Exp3 Challenge.docx rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Challenge.docx diff --git a/examples/InterLab 2022_Exp3 Challenge.pdf b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Challenge.pdf similarity index 100% rename from examples/InterLab 2022_Exp3 Challenge.pdf rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Challenge.pdf diff --git a/examples/InterLab 2022_Exp3 Standard.pdf b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Standard.pdf similarity index 100% rename from examples/InterLab 2022_Exp3 Standard.pdf rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Standard.pdf diff --git a/examples/InterLab 2022_Exp3 Standard_prev_distro.docx b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Standard_prev_distro.docx similarity index 100% rename from examples/InterLab 2022_Exp3 Standard_prev_distro.docx rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Standard_prev_distro.docx diff --git a/examples/InterLab 2022_Exp3 Standard_prev_distro.pdf b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Standard_prev_distro.pdf similarity index 100% rename from examples/InterLab 2022_Exp3 Standard_prev_distro.pdf rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Standard_prev_distro.pdf diff --git a/examples/InterLab 2022_Exp3 Standard_v1.2.2.docx b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Standard_v1.2.2.docx similarity index 100% rename from examples/InterLab 2022_Exp3 Standard_v1.2.2.docx rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Standard_v1.2.2.docx diff --git a/examples/InterLab 2022_Exp3 Standard_v1.2.2.pdf b/examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Standard_v1.2.2.pdf similarity index 100% rename from examples/InterLab 2022_Exp3 Standard_v1.2.2.pdf rename to examples/protocols/iGEM/artifacts/InterLab 2022_Exp3 Standard_v1.2.2.pdf diff --git a/examples/interlab-endpoint.md b/examples/protocols/iGEM/artifacts/interlab-endpoint.md similarity index 100% rename from examples/interlab-endpoint.md rename to examples/protocols/iGEM/artifacts/interlab-endpoint.md diff --git a/examples/interlab-endpoint.pdf b/examples/protocols/iGEM/artifacts/interlab-endpoint.pdf similarity index 100% rename from examples/interlab-endpoint.pdf rename to examples/protocols/iGEM/artifacts/interlab-endpoint.pdf diff --git a/examples/interlab-exp1.md b/examples/protocols/iGEM/artifacts/interlab-exp1.md similarity index 100% rename from examples/interlab-exp1.md rename to examples/protocols/iGEM/artifacts/interlab-exp1.md diff --git a/examples/interlab-exp1_MI.md b/examples/protocols/iGEM/artifacts/interlab-exp1_MI.md similarity index 100% rename from examples/interlab-exp1_MI.md rename to examples/protocols/iGEM/artifacts/interlab-exp1_MI.md diff --git a/examples/interlab-exp1_MI.pdf b/examples/protocols/iGEM/artifacts/interlab-exp1_MI.pdf similarity index 100% rename from examples/interlab-exp1_MI.pdf rename to examples/protocols/iGEM/artifacts/interlab-exp1_MI.pdf diff --git a/examples/interlab-exp2_MI.md b/examples/protocols/iGEM/artifacts/interlab-exp2_MI.md similarity index 100% rename from examples/interlab-exp2_MI.md rename to examples/protocols/iGEM/artifacts/interlab-exp2_MI.md diff --git a/examples/interlab-exp2_MI.pdf b/examples/protocols/iGEM/artifacts/interlab-exp2_MI.pdf similarity index 100% rename from examples/interlab-exp2_MI.pdf rename to examples/protocols/iGEM/artifacts/interlab-exp2_MI.pdf diff --git a/examples/interlab-exp2_from1.md b/examples/protocols/iGEM/artifacts/interlab-exp2_from1.md similarity index 100% rename from examples/interlab-exp2_from1.md rename to examples/protocols/iGEM/artifacts/interlab-exp2_from1.md diff --git a/examples/interlab-exp3_challenge.docx b/examples/protocols/iGEM/artifacts/interlab-exp3_challenge.docx similarity index 100% rename from examples/interlab-exp3_challenge.docx rename to examples/protocols/iGEM/artifacts/interlab-exp3_challenge.docx diff --git a/examples/interlab-exp3_challenge.md b/examples/protocols/iGEM/artifacts/interlab-exp3_challenge.md similarity index 100% rename from examples/interlab-exp3_challenge.md rename to examples/protocols/iGEM/artifacts/interlab-exp3_challenge.md diff --git a/examples/interlab-timepoint-B.md b/examples/protocols/iGEM/artifacts/interlab-timepoint-B.md similarity index 100% rename from examples/interlab-timepoint-B.md rename to examples/protocols/iGEM/artifacts/interlab-timepoint-B.md diff --git a/examples/interlab-timepoint-B.pdf b/examples/protocols/iGEM/artifacts/interlab-timepoint-B.pdf similarity index 100% rename from examples/interlab-timepoint-B.pdf rename to examples/protocols/iGEM/artifacts/interlab-timepoint-B.pdf diff --git a/examples/interlab-timepoint-B_AV.md b/examples/protocols/iGEM/artifacts/interlab-timepoint-B_AV.md similarity index 100% rename from examples/interlab-timepoint-B_AV.md rename to examples/protocols/iGEM/artifacts/interlab-timepoint-B_AV.md diff --git a/examples/Exp1_2_protocol_published.png b/examples/protocols/iGEM/figures/Exp1_2_protocol_published.png similarity index 100% rename from examples/Exp1_2_protocol_published.png rename to examples/protocols/iGEM/figures/Exp1_2_protocol_published.png diff --git a/examples/Layout_Exp2.png b/examples/protocols/iGEM/figures/Layout_Exp2.png similarity index 100% rename from examples/Layout_Exp2.png rename to examples/protocols/iGEM/figures/Layout_Exp2.png diff --git a/examples/fig1_cell_calibration.png b/examples/protocols/iGEM/figures/fig1_cell_calibration.png similarity index 100% rename from examples/fig1_cell_calibration.png rename to examples/protocols/iGEM/figures/fig1_cell_calibration.png diff --git a/examples/fig1_standard_protocol.png b/examples/protocols/iGEM/figures/fig1_standard_protocol.png similarity index 100% rename from examples/fig1_standard_protocol.png rename to examples/protocols/iGEM/figures/fig1_standard_protocol.png diff --git a/examples/fig3_cell_calibration.png b/examples/protocols/iGEM/figures/fig3_cell_calibration.png similarity index 100% rename from examples/fig3_cell_calibration.png rename to examples/protocols/iGEM/figures/fig3_cell_calibration.png diff --git a/examples/plate_map_exp1.png b/examples/protocols/iGEM/figures/plate_map_exp1.png similarity index 100% rename from examples/plate_map_exp1.png rename to examples/protocols/iGEM/figures/plate_map_exp1.png diff --git a/examples/interlab-endpoint.py b/examples/protocols/iGEM/interlab-endpoint.py similarity index 100% rename from examples/interlab-endpoint.py rename to examples/protocols/iGEM/interlab-endpoint.py diff --git a/examples/interlab-exp1.py b/examples/protocols/iGEM/interlab-exp1.py similarity index 100% rename from examples/interlab-exp1.py rename to examples/protocols/iGEM/interlab-exp1.py diff --git a/examples/interlab-exp1_MI.py b/examples/protocols/iGEM/interlab-exp1_MI.py similarity index 100% rename from examples/interlab-exp1_MI.py rename to examples/protocols/iGEM/interlab-exp1_MI.py diff --git a/examples/interlab-exp2.py b/examples/protocols/iGEM/interlab-exp2.py similarity index 100% rename from examples/interlab-exp2.py rename to examples/protocols/iGEM/interlab-exp2.py diff --git a/examples/interlab-exp2_MI.py b/examples/protocols/iGEM/interlab-exp2_MI.py similarity index 100% rename from examples/interlab-exp2_MI.py rename to examples/protocols/iGEM/interlab-exp2_MI.py diff --git a/examples/interlab-exp2_from1.py b/examples/protocols/iGEM/interlab-exp2_from1.py similarity index 100% rename from examples/interlab-exp2_from1.py rename to examples/protocols/iGEM/interlab-exp2_from1.py diff --git a/examples/interlab-exp3_challenge.py b/examples/protocols/iGEM/interlab-exp3_challenge.py similarity index 100% rename from examples/interlab-exp3_challenge.py rename to examples/protocols/iGEM/interlab-exp3_challenge.py diff --git a/examples/interlab-timepoint-B.py b/examples/protocols/iGEM/interlab-timepoint-B.py similarity index 100% rename from examples/interlab-timepoint-B.py rename to examples/protocols/iGEM/interlab-timepoint-B.py diff --git a/examples/interlab-timepoint-B_AV.py b/examples/protocols/iGEM/interlab-timepoint-B_AV.py similarity index 100% rename from examples/interlab-timepoint-B_AV.py rename to examples/protocols/iGEM/interlab-timepoint-B_AV.py diff --git a/examples/kit_coordinates.py b/examples/protocols/iGEM/kit_coordinates.py similarity index 100% rename from examples/kit_coordinates.py rename to examples/protocols/iGEM/kit_coordinates.py diff --git a/examples/LUDOX_protocol.py b/examples/protocols/ludox/LUDOX_protocol.py similarity index 100% rename from examples/LUDOX_protocol.py rename to examples/protocols/ludox/LUDOX_protocol.py diff --git a/examples/harmony22.md b/examples/protocols/ludox/artifacts/harmony22.md similarity index 100% rename from examples/harmony22.md rename to examples/protocols/ludox/artifacts/harmony22.md diff --git a/examples/fig1_challenge_protocol.png b/examples/protocols/ludox/figures/fig1_challenge_protocol.png similarity index 100% rename from examples/fig1_challenge_protocol.png rename to examples/protocols/ludox/figures/fig1_challenge_protocol.png diff --git a/examples/fig2_cell_calibration.png b/examples/protocols/ludox/figures/fig2_cell_calibration.png similarity index 100% rename from examples/fig2_cell_calibration.png rename to examples/protocols/ludox/figures/fig2_cell_calibration.png diff --git a/examples/opentrons_ludox_example.py b/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py similarity index 100% rename from examples/opentrons_ludox_example.py rename to examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py diff --git a/examples/opentrons_pcr_example.py b/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py similarity index 100% rename from examples/opentrons_pcr_example.py rename to examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py diff --git a/examples/opentrons_toy_protocol.py b/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py similarity index 100% rename from examples/opentrons_toy_protocol.py rename to examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py diff --git a/examples/pH_calibration/README.md b/examples/protocols/pH_calibration/README.md similarity index 100% rename from examples/pH_calibration/README.md rename to examples/protocols/pH_calibration/README.md diff --git a/examples/pH_calibration/__init__.py b/examples/protocols/pH_calibration/__init__.py similarity index 100% rename from examples/pH_calibration/__init__.py rename to examples/protocols/pH_calibration/__init__.py diff --git a/examples/pH_calibration/pH_calibration.py b/examples/protocols/pH_calibration/pH_calibration.py similarity index 100% rename from examples/pH_calibration/pH_calibration.py rename to examples/protocols/pH_calibration/pH_calibration.py diff --git a/examples/pH_calibration/ph_calibration_utils.py b/examples/protocols/pH_calibration/ph_calibration_utils.py similarity index 100% rename from examples/pH_calibration/ph_calibration_utils.py rename to examples/protocols/pH_calibration/ph_calibration_utils.py diff --git a/examples/serial_dilution copy.png b/examples/serial_dilution copy.png deleted file mode 100644 index f865a673134bfcea550948405c9cff289a227c69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 364969 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⪼#YUom~sg>9in<64~VRaRah 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 dtDTH$?EuQ1|+asLMOO)Oud} zG455Yc{EOK=oVQ&=G@pr{!Z_LNSgh)SM07SC!QY8^e0g_miHum%y=@gKxP@1mss1C zp2B&_d&`;Y#*uG}G|fsIJ$_$2c{uurc2yvw%ejP!aN`d@o;i)Cx{f?c?YcIeyp_qN zbv%Jo5_ayT=l9};WU}UzFLjZ=q0Ki|PHFZzI$hN5LOWd91&e13e-fOYG$3{3#18%_s> zG-z*dizM??-3$98LYtp1oCLL*ChEoeF?@!W94RMj(~|dgDZN&~hkt+GsLxxVx}Ub7 zJOw3IxK{3iwhOVzSvI zl1?jx)BlJ!pAbKlE7=dGNO$wR*lZ2N?;v zJPsot4kce$tm>-`q?Rk$mljH)pd?t=oEhLDdtQ0@5$ofz52ou(4wma2n%e83cGND0 zUw@p-85h)Pb+oTIGti_*WwGPE@A}#CkUqCsg_Z$Q!oYlwCi$Ws8H*b^WoY+CtwOcq z!cua;yj#MQUrtSvBPH3hjJ7L>mzWYQo&RhO)e=l(y}HgMbEL#f zPIFkpM{RkzR>Pe~=#vY#hS*xMBj-n63kB}B^NU6+yI1p)1-YdQFb+-#E(z=@dRqI6 ziyR#mb)Ejo%nB8Br_LQOQ$kr6MSOxr1Ytv0pzaDS+d#A5Hb%1-{p0eYJ8rKIobFK{>(Hy(q@>uB6@O{s7cl{nRq0B#$5Eq zoG$n?pCikiw;`=N>VkREDOb|bPn2Ej6`G%7*V$~JaJ($t2;_UM>*j3kuVJ1La9g)> zy7v0PKI)pon^@P3b*BwF*7s@a^hJxchy0k|Q~7D-^IQgbhaSsdg4GknqP#URic;N$ zwLOidoONEb{r#$bj)~(O-V)PuUYF}e9=AjqM?H2f?~N(wZV)bOSRc<<4~@`VX1_G3 z8F@in=&fRU!eK`ER5-6#J6E89u5T<;6>M*(EmfKj`p<_XT$cP>he#c{}wi{ZKCn>Ag3&# z`cTESxV|y;zDAezW*qsZ6Qp08_rCQU9iLLKw7jjt#J95TORK^1MSs3ZP^mF)hrtJ^ zx}kl7gb4~ioyZd&q*>j-{QIGDr;UOlQNI9Wy}4Nc{htX4qk$gYd|-S3oCn(AO?J{v z>Eo8Kc9T?mwX*MMrTFRat8241*#+AK3mipdla^_aCPaAf`ZI<{Qq$+suzLCKJ(KotJjy-MQ9!E08m|-YSP|h+@sM ztBR-YpqQ0o7degHhj(P`^hx$NU|?bH#g!B$^)A%T(e14Ad@@BvN~K>|+UBmw*|*V3 z+CKAd3^yWuKQxbAk3i#t?_1E=-}1)EH-;xOsh|AyR zkj3gsbU9YIwXXPV>L0aC3@YVyH@?2~#%m>c>n?R^`xWE!6W2DBoH-X#$2n7zb(Km9NcR9!iGNFo3}$#FHLpd? z`9zGsdjf1AO9krJM zU0l9N2ddA$c>0Ypsa5&X-fD;T>ZAyt>#ruYIn`aBoD`2nvkyr$#?{ob3mKoW^natP zIrPiP{gS15{7H#TUy~;*s192KxVjw?HKb@2Xp&V zlwYam$p!*^f?uzFxklc&OvN0==xfH|_nL;G)-NA(GRc>Dh>_&gE=aQXdexcJFP&$qc@qUfLRcY)pdz3bv|IVVA2zBUBD;y0y%ta;0eQ z+i}_XgM2fVetSg3tf%Hzc+VIurK+?WBz>+e4^46Q4?7dd8*JO9IsfA_S$5;tu2OCN zwZZ@z=TP);a$GFJyy_@B44Mxb-c+$}6S;vZ1nWBcYaWrzmt!)r>O%5ihk48A#RDBj zn!CUGrg$)Fbo>gm=yhwEQ`Gu7qADe?7-ZgL8^SH*)Vy14Msa+?DZ44sPGdF%ULISa z4aR0f^Wm`KrxX_1DZ7qTjK_z;z!tp}kgo^wlJ z`4UG>+}Htj-i3EBSKr8eFyDX5(>NSLgCxUD*yAaFUDMF&r>eYIq>=?U_NGdQ0>U2x zW9(fP2CPlwU)ioD*?(6%<1m$XFIVr&<=~a`xuUcy`¬2G;DUte%o`d;CQsTCVcZ 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 R&Q*K&_>mJ|R~!zy_B%n$#5@21 diff --git a/examples/serial_dilution.png b/examples/serial_dilution.png deleted file mode 100644 index f865a673134bfcea550948405c9cff289a227c69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 364969 zcma&Oc|4SD8#g{}NVXy*TO}kRNeB~)k|mNYOOh>QDcQG#N>NEdNNywv*^)J5Nn(<0 zjZ9-`EHN0&FlOd=T;0!m*ZcnU`#jIRM2+h@&*MCf?{?m|&zKl+bBb`HP$=$GCy$$> zP@C?eQ0uKZ*x)Pg3!ZzyKQ{ZGw7H5xZM%m2wQj^!A_#@zH1*KaJ9Ea}=bFz|cOPHL zQ+j%mzWzS09$qdeRM5A~vu+k=Ck3^rBa6DHZ$&*i?PI>3L(*I~AxhwZwA`-Ee1^An ziH$oyJiE0aF)`}yb~AadJDh{;W4oRw#^m0*^N~&n&GqcBqyFq-Rt{*B zUQsg3vFuG8T#rv4GCLf_Rj4bz^+!y5OB-QK;aD`MlrM^pqx{mYtBgJCP_zh5&HcNZ z*c(vmf_k@bpqh*`nv_K2S-exaX?E+PZmw&(_CW14N0b2SSV*F7KI)kMx~R-2(q~c6 zHli+cI$tEB&Ky8pkcs@+i;BvmrG>6Toqx1z`?_ZjP?G#Ew~nLSkD^{-E$^H_Su3Fg zTu-;CqXrM4lulW>o~~jG%6w*WKN!iB&v~2c{a?Si3J?Br?abMZU*SD8jXf9;Uovxk%JewkU7r^S!eh z-5s_(3!o;rzTrJqiF!8q&5GiStj&p>`!z#D<6~okhAq11ojzKHGu@gUo2(dKD-oJ& z)TJK{qf*hz_R$6#X+N4jEgI#CVjph4d2#q>lEGT_7S@_r@9vgU7i+BL1c+wa{1T6+ z-=!$$?Y^!1a9``*FRV+WczOB;ZTw+W>1FM8p$`tcuy@|Dd|HOj`dZT{6@^-;^?CnQ zmSaPddkg^^$ReW|2G91QqFhfs^h2Q>j!P+6d@M(|bD&VipGC`+>g-&6FD&20Ci;HU z@cS)m7gTTRO0_iW^67G3iW2p|u#4%_a`@QOOTT6xFuk=`}BjuCl8w6 zv5-7>QfxuXf4zFVo&LKAM?avHZ>+`D8612R{l-k|D_5mn&5I)7PT<4^J^kB~_!ap=Z|Suhk=k}!Pg$ns{`ym8|5$w4_C^2874tol@`V{H zCq?!ocYM3#`G#Hnk-X&o53ysJW0`!oEu81fym-v-AKKYbS@VyV4R?(5jjN2a zxja$UIhUJm{{2Oc#n!_~wz|bRRpupT@h|vQ0@BsHVgyf}&MSVN(ktRF-Q9Klhn^vUpglZCQ>IhECzCM$8C>kzvU*oBSV;7*lkCkaLE&+{2jdsJK8OjjvSnR zLQ3OJ^EqcNS0xv={lQ1h6vGthl$~;l7KJbKUyi)oa*lGY(;}(R;cWP8{d0%T5(_tf zeOz?zW#*abvpdha6&`&N|I+P+j|KXl2ph(2HXDo)##HYgvu9w~L?3REF6$Z!yDnGzgdtX&p!KpaM_uob;UTMXbIK!EG&}K$AMNQilg%XAf>cVx zoe=@@zR`U<^Hq#$4!YQRzI>ee*t+Osky(+!biL~9nS#vx`V+M_^k^QPc0(CE83VVZ z?oFAbvqNXU7jPB`8f$4Ry;gYXnYS~i_IP09m4ewPSq%qdf3lLQ%tcPH*cnAk2$87=ak}DN)t`1aL+jvxGAVaEMEH)FQ>HnUZAS7L3|ZSt(o+1i)u7iSjl?XNAaE!bL6W0GuAl-2Ks zDV?wCs4A@9Q93@zhI?J*T@~)+c2UT!y7e_?Hn~1I{9X7xh88<_{18u(n5|gE)e3(B z4NHxY^zNs#=uC5;2~laf9JjykIb_fy#{VVZZ%h9D7O-BpT5zlkgBba zv9s;_hx#$YYfFCigpe;wnHl97%`-1>C9|rt9<%Yo*`HLh_hs1}y80ROLGOpzcn^9@ zc8ZcG{#Asjo@umOC25bMv*H7*;(^lYyug=KC$f9UgRFuB~}Ql2UQTYcb(gY+tE7F=hxF|Az`~36VVztm*qD@Gdg#l)#z;3 zNxD&dWBh&bF82?=?icT(lAd%w==R`=Jrgm}|C!zCr&9tZf=ebgKGrG@o#=bZTBPS- z>fykiVZE#PtI4Nfw^6=M#y2HUzt%vgD$7^oN6yC2h;x_u8 zp^+t+eqGXASxck-V9dh@_x*HV?lMlUa+`Ad>3Y5Ml}qd!X6u!NYDMuB_72bT`>!_H z9N?_d&7ZKal^u{{f8*w2<=WVF`=k2fqOAR0GoQ*o;_e@LO3r4@Y-`>|cvzJeciQTJ znDx*4SC`e_X!-@?IEmXg?T@o$d!_mIPL-T@pJ~yIRqE@Adg%~j&uEADA8)*`T<1Bx zz>K}AwW1Ba(rGm=bEo$9+jm|I;Dl1QM-Ivk2aWHH_xaeEHvFifu&AZx z64v#L>*UXo16k*J9=}ZenaXp8d+1vQH{P;hW@-5ZPBFDh7FQcnrB{>NsQI?erJ$p` z>nPgdAB#ncRSVVGFW)Pj2547$W_O0xEvx+M!=10AGPFAyaOc*YGwyTkbD^K2ms8QN zZ@-+RJ*Iox7n^wd&9ra$vVpERVc~18-JPChy0H38sWA%of*~);TU7o6#B4`ySti zKF=H;Bo9YkZVG%x=@~Ylvc<+=nGcqdc=a|Vr6qO7amP((scEaLkD~naKM(?mZ##GbvjuKp3bDMZWN6?{z4vUubnfHOi zfnwxbJg@0km}I0Z%YCJ6>FnnMdh(9sWY)$FPbh27hYsKXZ%R6!G&e?}LiVCiQ86gg z3Jd-@i9!V^p-@v7P$-QjD3p-TL&sKq)TX$vr;h7b1bzF(7)q8Rh2vQb*~6DhrotWb z3kuvMK5@lKqP9ut+5HxBO+H-o0Pa7nbR5?Nr703k}-d;iUjUD-$wUhGeaj~{fe0wU7I`s9lqmea^rWUyY8WJ zPRHpkHvP`+{CFzOGY)qft-!Q(dMkD%l2!B9GK@-Y6Hd@O;dze~{B=6OFmGFmp^NFn z<#g#Zqc|_s1Q#3k;`#7w+v2w2VNo0oC#vp$^Yv>5xfIT#qN1;t53{kcP0Y;fO))%C zQi=X_58r^UZi;X(RiY=XkgVWAeU-6?a&&VF<#*B`PI3$XyH-GrR5v#i{YJA+K zfyE$GerEVA9Brf=eTt6ET3HE3zE)mW_i3P!8PKqpr$|uic8)G0)0;+6LljMTw=P%y zcE1mol%M3EDz+q+uvSabva?BJ9m#7`B}_RPlc&e_#ZJFVG8SpqBhaWZ5zFDMvdN!H zDkEt71AjKYMF;94USIf;YKHOS$B%>PGu12cku>&4=2FQWFRtv)G`YGsVU`ui49*Jv zxq~xy{ZdHg(o%q+py1%pP>yZ!o3gU^i;F6U4jn?CTR%5?`kfid8+ToRC;n`M)5)C; z%!LKz+}vDE#$qoQ7Z=~gbqNUxpSruh^!D=iU7$52k%D`KqCC=jREcNXUr*~-x69o2 z#w9wShubANmc7`QE$#nQImcF+=rT2n<}0I_nPRT4u5YiBc$}S`xwyF>m=x?wF?{vv zRq5NeC-cmAWn-_dE_yudkgBh*H!?B#^8LG*@k(64w%60oAKl51^TtVMW1VrTDTc8# zGu~nNf-|!B4fEcHQWYYpfsySDI#oSjO2BZRNw&6eVBirgEiDxh?o~SdR6(!Vg<&t% zT#_4)I;)zw0HYN2J(+t;TxGV`meQ;noIKn>(t z%bP2tPX7A!PkA})+wxPH|BeU8uI1z=Yf+K;*&n4PM^X&uTNNW7;OX^v=b)e`P#q(| zB(Vm@j1T2KyToT?*(?^RRD)BlZkIMpie^0#k4eEG7i(Be*E;l7a2(4pbs zv3T^_uA@hfYA$^}`&7;EM#d2zWi73)j~_X8_Pj2pp&Ns{Q!!m!W?)cMfBN+4j9ki-^z`RvWapM~J`|bA1sS`>h;UQm)|#s%+Uh`K zcR5!3botO2h8I1i$XZYgUh1>*P!W05Iqp8XlIE60;APG6B877L^y#%9?C2kvfg|fK zgoQozQr)?!bw2CTUt6sEP~^5AMx|?l6y)ob?z&h`R9jqHI;gCytB{&&r%+yBZ(M1c z2j{7(N*{Jn@XeMRQLg1XmN<`yaKm9Qw2-rX)=km89vC<@H1s~e9!_Gag8jvah^*Gu z6LInJHNJ%PGNxHl+1RskDTBkq|3JMJS_IMNcBLvhx;i;U=j80lidgknU0r6zNIVnY{&cwVwC&&`BqXzKdnJx zQzzl7aj#U0q2FlB=C<~BKl{{V8Pf&N#%0f^M+15ARI0osDOlXo(-XD_dIhOFlUN-| zuihadauGHX&7zne{lNnF7mw7XHiS57P4tUuT=6WFC3hf6X%5CM>UPi)mRplm6ykm>5GetzGEM@ zhJ=Ka$|rPpn^;;|6%I`IOhX-7SqW{}umO6MS;;^LiQ-=Dp_<`dJUKD(qvbaL-Fx>Q zbdEz8@0sp+RQ6|-1#R1Ww>3wAt-(p`gxc0$?-VjJGN8MC_EOy;D*8`JiQ>!0bKw%j z0gG#MB-$gtw+Gx~Ki$*cFc6U2-m3SLfxYdspX*9EKB@VK?}Pfe;Q5)Bf_!gW+Z%cL z&SpPR`OXk8Tq5yVWuo95|DTyPYVZL1kR07}PxI%)9P6i+G~lP&HH4+@w|ad+m<=|= z+28-6BnSLtEJZxSgePW@cGIWWau3J)mwj?@2m}&ZW%;VSkG_mVJ-_|)a;1ot^zfCz zn5Tw$N?bAiHPH5Xpthl4p`sIs$HiI*4YA2zbAqgY1&hOvf;}&-sA!odwyXP(aX`s) zmh3(D7ieLB5SgLCb5H3QH|Cp?ltOB!nd#hlpZZo7g|&vRqjVpIMV=o`Q1l;dxvjP9 zwMY73m6$PSd+j~3cAb5#{r!Slwrm-G>lYI^5*(kBlHzWz#&xfEQpIo|bceT*Eba30 z@~_iN?v5DWcV}dkR8(%d*nH~h@*DrS9lByLDKiimc?AXW4Gr4ng#ry^XW_Oi58~Wm zOw_v`cVFtPJ#&Dy>bQpdZKXS~0kgUqVqvw*>Hpf+G?=z=9_dMa243FY^FopHLUn5k zolscvox9VF7N#4S({;4b1ejU+_Lz=K53gy6#bV~%{RgVNMcbWV`Pq5J=N38@DR>q= zvY@*9$hRxIA2hv@zajaou`wGC6Vl`RimYmaDbjA;PYHNNZDc%|ZvA+B{m+(`jgHKP zR4B~hy5M9qlZZ}ysiI)_wkdXt(8T0qj)fe|5*Y1=Fcd;rIts`y`#IfZHuP}6bb;S;hL-Qq10I?Xl~n0n9Ee^Aq@>fA0Nd;VrgY% zYs!8rYg^mV!h)=eFx4)WeSjGYos96c@T}<3>vvttJJ!}TVJ1DZmVaoNce0?@LT5Jn9E2D|zYr1im=@9N1lfZjgb z5S|gwE8)K|b}CTog!1!NjwM1iE(L zpOiW&ot&hl@aitSWREIlvvaSCpZ$?l zPNA`u*@*-2tlnUw=X}`mg%t)4iqo8|pVN?MyN6AsgO%2 zGuyY+LLbF(+_-=x5=$ys0X!iQVU43y#*6UptPoR;eu=$I+j&xpV<3y!mQ69MUI)O? zNtj(ca&1^_@f&+)Eh7mRX);Q-qSeJLYcYk34+A5pMo+G3PYP#Olt=`Gt_5T*HlQa( zXfI|WzaIYY4LRnMbO49DZ`7Hy=Ho0rb2U=QD_z=fA8gB&qq1KY!?Pthl#CCBB=)Dn zzi{mdaiCpYqtY6}EG~#dn(%E*(qc)@&mC&$VwCW+~!RAg5&8?c)__RL3QM(--wD#%Ejd=3f}% z9d;^#Im0`QVT7CWNz4YWX}0R&<{IYe)Dz1|YM2>`#dSJw9V>0`4Gr0hM9{sj48MKf z$fB~cqNCTD7kvE-`YK9B+2!J~J1_m&80h-MHc)tN!x{ae_L67@= zBk3JGb~s(We22-5fS(>s7vQy~T8ZCmBm>|jk7&V%?Gxavn`_>3NjXg>?xqf3X>DyM z;Aoh5@&^v|xT^?@iH$E#_Hyy?=sS%qFRMZqLS`92x!j(nD(|+oHnq@Y`Iwj(=<`up z$@LQFuz=F=d6I zjiRE2%atFSo7el)&9g~_&8=%7=RUgV<`xgj4wHj6D%1$v;gX-<19BMYsAkYy)a6P} zgz~^Z5^@ZCfS@n}!Rd!tz%jMHRkQal?ty`+)gvJZ$X@`@6ddZHC9ZsMt_QSV9BUl`O)+Oar0>Lk1^4VSG`H!+8FMovJMY6)VFh7ub=H)#EXdKhy! zytShugAJM$96xs)$Lel@!X+=sKx_dGLnvQu>orFU813}$~)Oe8aO&g zBDp=cx~+t_#nat|*?_wOyGR77=gpAUHO9H3z88Cr{>Hbqp4)D3gb%S(hUDD z<{wDuii!{(y>Jq~q`U(fho5MCUtgcQ?Gf#z+J=U1fHS}+ov&ScR1&dN1bqB#$$-uI z^Uko?pxq$q4srxxHL%)r`E157x5?>g=YW8e+CVY_&;W~;R@(yL@*{O4LI%7!(qG0X z!SLb(ukD>ZJZ|S2B>7K$Ep!(dq}0h+?*4`D2i*u@UXMFy90+`(%EyuD+T;FdbSk+V zI#S;0RN6vn<0n8e2rb4lm#b_1$2r5p!$FIvv19vjD0_wLu?vD{VXJmP&l+t_fJY~% z-MyzM6$tdDVJ=otNnL%1@lgNe$_cH_1%X9o`46ikegqfF3GL@ zNt-9$y?YnHAqY=yAtC8d=y1Ahrzh$&fmVa`0Wk00&LeLDio!$mj9z0f7(kTH6!krU z<_u>*KUYUCW%R>?J%~mDPg4HoO>^eaz$aN*uJBz8xmM`vAY?s*j|!>p2AS!I&&b{N z1mIUd={|n_DgXc(YWoVlp=)aD@}f@D+?-N-l0;JeP<2%mLV}09zIdr3P#D@uQ-D2C z+$<78*rwls7Uj!a3kKr&!L@v${Xa$QR?@xShqvHFa)%UXOMoBG$P2EFP#fZ*yBv5? zRaMmnj|g1&Zc@^rg9oF%aZfb@?tr-B4_nzkFkoY2HbEW4RPVm3<=LpfN3scOpmoT3{feQ^9k=Fs#N$WFRe3F><97))f_6B(SWgz#cj+ z0!6A=H@CjaHF(?b9%g|u9 zZd?Z|b}2M8!!S=5cxWVJAhPSzCoZJ3=Vtw6oa1Fbr`Mu)6-#;UFzIVfjp5b)0qt_M z$dMt3NII}sP*>FrO9#U6q$3f;BNG!77sA6c$r04r-;D_P-kFlV%dkjuOC^z+r&ATm zV0{7`C}PY}Mdpp(0@L2_-;GU8d5J_KoTGomC5H<1W0!-fs)Bt!2>xzl(HlvtOVetJ zdJ3sm>5YTo3S$zw;9ymkXGwh@ufI4kt;2Ot~7x|KR8aih!xuKKA#IrJhe$r@aHFk;c$(ELuAbTagu1=bI^M_y3 z+ND8Vv=gduIr051!RoEB?OG8Ww)%Q8V>Xh1jqIb-Qro1qZGL19$nWF0GAIDRQJ`DN z@k3j&km&(gut|;UA87iOwg=vsdWxOny=nihDJ!1I^f3^u zp1!_TIOgIqP)|8I+KoQKAvj`iV}^8)$tE9N$+yCz`)+a>=|&3%tVNutC!c^ zNV*T}09K1CihL%PwSo=?u@@H9jQeDeI52Y1o*OX(4aahglUJEHrw8tTZxR}gO*)aYW< zQ{l(Aaj*(b?49NzP_>C_J*XF*SHAPzXm65trFoQq~NDxx=U!3TXb=RIyLp99b z^O@^E@AIJJQmJn+Ciq00M^l2Q}26ZNY-^`ZH9 zF}UWaem~KN9hX$nM6|WJNTW_5zWmec5#=tY%5@a;OpQyA8`DH(Y$y_0CVRd`6Q*zK zkeN|x+V6KpUU^G)Le+xPB2)zD3kJDybz9Pbur8SV05f8BqoH*HiUH986im)o-D`I2 znV!Xm_4M=*!vRJ?ML&YO34UQLOyStv5+-&Ij$7<3tYM1brYJxRsu}lmr(rXEVeow% zU&t!m@eD*x&}a`x3YpA}fFJ~llu_>`K(tFsOD{ObKBXPnsMEwQ5%&8p==N_xT*abU zn)x1YYHLr||L!?<3I-aPZB^c|aj;APLSdf>e`oQPPLb_o{W~1 zMP62~`|cHvsQ~lMi~2s0D0dSR^$Fep z+H}DXd_IX+dJ9M!lw`RSP{p7h3QI^76cz0cDZ%gx@~ocO^Ymm=W8*yU!9NSA&4YM< zGEZ%bEsGEzsH{wJe*da7NvWgF&o^^AAIl_)Y=7jYySlS;29DTNhTst|e00pTKc=@L(%|9}(l-M?~&v zF*>1=4hsVxMno%O8#e%VfEIAV52~mLEa}Df_8__{7TY^C1Z6P>-+T4?HKKnhr*So9 zO}gN!fak-L!!H2_Bajm?9u$hZY6c89kifd31B0g3?x%MBmoNYj06IwdfYSmi3e5p5 zHjw6k?H(`TM-+rRUaF^IHUQE?T0ShU-GEDQu=>j?@WyagN0uW?w`OGrktob7?wjxZ z!P~#dy$C_d9fUf-zMZLxl(wBdh#EXKC1>mD5XlHoJ#u6PfwwTl5oc-t{{0AhUhBwS z+YFBmz#9AxH7HhiuK$5MWT5y@_a6XI3P2H8?E{PfRvOHr*)$byy)UJQg1{K@iJ)ZE z&A07@qER|@NDsW!r2)rw6=UF?VB@(LgOETlWi6V*;RT3#_2;J@-A~o|4@CT=YiE(> zq1(>`B0C769-yvlYA2!~`h*b?BjW1vFB_n8Y9MAq5slYVN1Oqm%+6kcR{`>B_wL$l zaO;2pT3cI7rgqMcD@LY4D@H~vVr^ZY5&2ir_%UBdD$Uv>9?>SjpT!;poe`*)dEp$O za6rsAym4l{zQ2Xm&)>gy!SVpu227zZ)&XAa^gxMoy0k%}Xbw~#kc$}uS_m9`Xp6w` z!8vRS4HA135N08)zlO6W+P&Q$*AUknAk@h^0a2WJ1fG9OJ>a!#D zo$yvrF+Ddf50p5zzmbQJ*dZZ-h{Y0M>7k5_jR|TzfL?nlg*JllaTQelh`AUEsLY$- z`cSF8?kYhn1{FM=YuB&)1BU`N;{%)yaNT}(XC6Ja|7|@oJTxg>a3r90JnV7>wTa;A zNEZQ{5-e3ji>j)wF6_IUlu3dq4`jh0Njwjr#qr%`1=E8n#&9;lK$6Y-FzydV9H1t6 zKoX2^1cAdiLB1d+<^s?kHWiK@;+Y`;o?K5A2S;PLF%q4g-Viju8~j29s{u=cl}vl` z1ROFS(-|(|SbFGPs5-)o281#Brk48Zv+srv-~2XJcL zvcn(4en2C;-JcFe9MJ??AM7!peR9*rP#am{h=dS^mq{}M-@R+7-0dLO9!^$!TN^Zb zGq*)38R!#cc1o3smMEW>Un z{JhTc*2r{)S0!afW_hX72cP>T5`o99$lj-S;n$48r9_Mz!+p@w)j}3!;rzhNd0-?B z^qYuYi)ZomZAT%#tGapza7!^Uu_SvTLd#X%}Iz!=&jEuZk-KDAB`DS8j zYBW~J;R47E%)I0Pqk? zQV(BM$@hSH|K#b@yVB{H!f^n7u+q659))@T*%B@7I+HSaFXE30559lT`sb)!m>gG4 z^JLc<%}ZP|{Fu)sVg4%(rvGLxw#RD3~WpA!5Jv zDp(f)LaUE4`+nLf2raF|4fyhH^z!lo&A`t-kStMY4jl}<`WichkYe+~MKMC4}j_xv@vV%+<(Dl!i7^y)U&>C8G;;D&Uev($SVy3$wEdKm_5r{cG%0 z(ss^b;A3GhNOJg!f`V%b=vYn<*x$JS4lu5yli_io;XHOZv1Mdtb{0{ldG{`?Xii=e z=~c-kzOs-5h@ROFs+*H=&tc1AOR(mf-^jy|06VQ`=?M~#$}TQG08+=Icq{%d%8*^H zCn4Ofho5-noO3=X+odwDn3$YSAQN^wKXy5FVeRyof&DkSOh@)Lyn#0*_eLG!bQb%B zCs;X#rvO7@;()+H>RfBUHtZ$i6rE1|`p=pgmTpFGh`bRHX*F+9&on(d{w9)+HgWls zq*0YU9!@uFrxRx}rf-taQ^P0E{3X%ia*F@CHDGYeb4q1Iu@?OzA-=_rz?gq#&Geut z#%GUdt@=sOlf8QVM3KY<$XTF*>*tmgBwvr*^wIRHF~eD$$fQR;^=8Q@t(<~LeJ8JQlG#a^-M;Efxh(B_y*m*V=@JLY>_OwYe2 zoFH-9I>D^a0(J#jDi>z(P)@{|b9eqL`kQ=>vhk`)BY5f$1}tr-Ss=a#m#*py3G6zOil!ljf6}e_(>x5*d}+m zg6c&$?YO$l4V$$$8yk7)vy9V%;w*z{Ms80Ixg7bB#C$=TDbc#^m@pqZAN4|dynV8g z;g?8n5AN1UO2P}`O(i*Nv#&*DUBfe{9%ok-{AD$Vh4BQ$`&pj=cNMXj-vuN}K z1FUt%H_TtIrZ?yLm>wEEw_1TGab#&b#Gj=Ct;8y&I#9?mH zD;O$6OQ(cP@0o5%8lr}StW+U+X{|1f;2V|=%O281Bpqj}{zbvmdAu)(^5%kX4{{Tv zB*2;QX=Gd%U~4Nd3_`xi8>~PiJ_PXR z$VgBO0;I#n_d60msW$r{h?kh3uO~xhCp(c_#(_vSpb0}MHxPWM)=owHY99M85fPWP znd%hTr>FVj-WKW}CM9|OH0^5hOgvp8?$i8K0)x&s>$6sO6UPaOrMdZMGdJ7CwPiG| z<|%x(4X9F*RzW@S8O3L;}=7?$msikeVTcZ0oMoILnczie> zOnp#mfb)UU0zr`Ejx(|X%V8Jzv_UatkGiH|ES-FNM6vVD^Ar60Q{d`K?C6)C3yzZa{xwE<=I@obV0xn8$Q-T9f|Mh~%V5^kJIEw= z0962B8TLyfDKd$D8paF^C!n-LUZ4Pgjbc*puT}xd^HNB-Y07EgCoO4y~=XH9s*_S@1|F&avtCfy>s)(2+6%*CK zppi?t2(V_0kOGh{OuR&du(7-;$jHN2u{}6kt<1)Rz#2pMH448;t?lDjG96sf1;lzr zxzuQkM*0(^lA^z}V7tp_e zIfPMb@#EvEj;=t)plMR}H!kc)3<$tP7jes39}|>Bc?!J5AY|c%L7HJjKTyNplL!e8 zK__KWBAHmk3l{eTiQxhWJ-phqsNa#rFr~9u zYa}pa?^fB%3kI)@ry{OI`>$UJ`3jpn?Kqm?xVF1JQEU&=fKAK)uL7RhObk-=QacfL zMreOUzUZMet}1VIf2BxV=x5G#{I@qEDOzwu{w2%s8N@A)wDrI`{xL7q>dlcjyibm~ zRnfI`H^+K7tw?J{)86w25$_!VNCXxxNLmnuWF4!q`x1e*G7eQ?A(bv zq$PSMkU2|M<|%>5Z3jerfYU&Re2#ueZcPl#9RO<*(bAxsLL%xTq{@NTAks+P!pHrf z(7-7G)Ae@9D>`r@z}K+Vp|8u}2VvrQZ5$lh{6ryTa2n*P9(SZdS64MaSqCz2(6@~c zAQbV|@63G>6YS17q%A{Cy5rJwCSgv*OGV^Waj_rJVH6P1NirF1YXAd~oaKSo8JK%Q z7$u-Dhzp3&MIfEX$$V{BqpOkm6AIc4HKT@Pw|{f4D(~M@ZltaQG;VdjQKTH<(-E5y zxH>{;!D@tY?S;z+#SVBe$>;1}w-s)g#vu#tBwP({6>MLg`M#;@??XdQU{yhI3gpH! zvZZx(pWvtj&JOR&=z3FE$8`)`DbV`>7Qkcg6HI^}e!{-e>a`sKvatZ#-wgfA@;JNs zZX~mLuFRnXl4soz`2hFg(;=)cMB)Jx1A(`z@s9-u5)eMZogol{n1LlQvdkprp^AZS zXok`5L-quTxQvb>$CFq?$^uFm1GzJBe!+}ST1_GjIF?!8T|Ws<9%Kt(v>WC%)5(ok zkdzQotq0Evw;>qs=TD3;J05W=y^K=@)b}s7fLC$?3k7?voD>X&O+mUOcnICuXo*dY zC3Op&P|V>z8&y}Kst~ZES3b-`15C11^_f9_kjYT76WD_^7wF1 z0y6XRzxGDJZXD!T59mW0W86E;f4BelJr6kapm>>=3_yDXt3bHj4+!KxP%97<0;C95 z@FmcYK#qr&3tAXl4?x0+aEL)$w=EW&F%TZ?zkC=$y;)fxy~(^x^R++1nIR)B{k-r; zP^{tG%u<#{!_3?h1Tc>KLySQ+Biw73R_7aF&F;lW)gxk=;a>U9(ONu1p~~CY#l?+LL_OygdP<)=)6{uOIDK*8-ddW1Irh}B?!8L znVm?S`&EuzSnNfFW%L?>7v2&{R+fa%c$%rf?S?L#Ph(fwAvf?8oBW=-e+-T^j-{>C zkv^wK8Rwb9Bf`xP8k$97eI6KShrURi{hn)EtY2Rb4hyad7Q~GExN;iAxh8u6*#|)^mkOYXIH#gwrY_aX|Ily^FM^ zGj*0laL2~`a;5E}laa7>yciy;R+Bn>HH?yhAFCX2KrZ5d;)>`sa6GVpq=&q&V@L1* zDdkZi@)^Ytp|}djw-ogud0#t)v$6t^5imPrB`*jvAIk2n?>hHbZx9$UD#l3iXaTXl z0TyV}er$lMN2I2!*>t-_8WbO#@aKg;V|3A*+as8d%rBMOK(|DkdT33JD;bTq^IfNx zGytCu1OP7s;<5QWWVrcMhb`3tb}Fa{HTtlc?>POS|3kIe7YkQq*tZh`I5n&IoYzQ7 zmv|)jBd=&i@lbbZmwDOVcw_z4FNo zL?&?HAY26ni98#O2sljn9uWF~*=i;{O^;C7F3Q&C6t1WFft$=L(}6j2gew`79zRzV zG>&0jnWpUyBzVsk66P@RXX;+=Zn#B^`0aoq(;?0YVo_%dPh_@&$ZUZojx$QU0$!fLutr zbZH|@6u36SpyI)XOn?Id*b7ARG0KV-IlN9|x82w*cx#CA3)2qSV}K$5yXXe7kVz^e zp}ASB)7M`eBFZmV!AX~{$NHK zY~dD6I00?oE5i%7Y`~n^{70p7ybID?JUaethH3gph5Y`h+Jd-zq)fn#2jQe$ZZ^*Z-fpf}kQIgr(5p zBYYQv5o_B!Ebi0>&O%;Ho%J<1(bz;;P3Z#!NRgx}q92Wu8;w*`oqxXH@UHfqdiaz; zy_VKZx8wZNLd%*{GXu=FBg{L5oL#EbzoT8Y#R#x~-I|aPz9ona1vrCW`*{Rt>;F`C z1l4L}Ua>NZBC`XYNk+o|pj^4SkqQS8OOygM?94tZwZK_w{x;atnRKd)L5{2x`s1Iw|2Syx{_63{-8V$f4 zX!5i8Mr?H>!@Hs%76keea25b-$UP(jgZAj{68~@YZU~i*!dy7ARJT>K@&B$n zp^%%Jn%MCas|M_OpGL63F9o^ZbOUd|ajjVhX;osGnVOU|x4{)qtYWMjiJT_vWEo%HY*0Wi=&ObJ-Cit~O zV|Q<&-qB2#|5>SnRjn;OxlyiOVUHRb#3h?l4#)*0Wd!E0(8={}Yr|YeaX6I>?W>n}Rs2Ki;b_HZa`Rn-@xLZkL|Z zdh|tD4khsMOfeou4z+eGgN~-0hFn?0Ml6?WveqbwJ)xV!*H?+?E}+B1bqk0NkPuQz z$!2K+9_ZQlH!~hn`x@=1iQ*PIghO+SvUSi|L*Z)&3D_Ko?fwkqO|69aShU1qsIWjg znJy&(7d??HM!*2zb0GqVSboso5wm4(&ewvBpj(nQOI<@_i;;=(7x%ZKJ0wV-CJ%{b zXzE+lroMwVDCD@NY;XVlQ}?IQP{j8DmptylgI(JSkMEbVyrZPlKZ8ywrwIz)e7-5{?6VjEkpAy0joa|9R}5 z%Ko*FC2O4j^EXWj)WLXzN$CO_;5ChUplUb%Tr9t3%9h9LaoasCr*sZUdYmAS>bT2} zoEEK)OsAFJJWo*P#Ga^2P=DIYqqh|FMBKzK@=Ld#8id?Y10XpecPv0S{2dH|ix%~n zby=s29dgaRm&9;Yddd%^2x`{(_spLi283R04*Blf7{o4@OK!XF#dS8P*_<=)bJNVx zKw4uYJu-Nva$sV5dYr|8|FsBOsJN?S038%~**BTccGcbvYmj3Wak0X z2dic^-MkDu9KC6jUZr@Fxo})_l^5Kk6I`#t6>~{B+5<;xFs-!AGxK@a<)Xy30ZaKD z-R8ILAM;a>lu_KATz#C^i;(%{xaPC}*IpAa=kSkz-x5Nm+FM76Hj4|9*R+iy&;Dr; zjlV$so@e5DS7qkd19;-A+c$iTk-o=^QNLrlO~T^T*0?FBV|8dXrqpKqo?aEOkRZ6x zx94X2HpdrAnrt|~(rr9LVcJ#2{j5#Jp9Ff9zz`p-I?>j7oWCi~_FcQ~d{mG#Hrc3h`L?B-Qbk-ykKE5e^*4;I+Xe|>AU^Mzs+!%B@i z-24?i4Ok9a{B*~SWvYSIdTclV;WW$EoLas;aY&Y>u^eY^Xe`WQ7u&ZKDzL14*lp0YNS$Wq^?GY zN$7%QHQG+;o~1A6OsS>kdWlCvobKnR8L=9lceABYBbXE35>I=?8fut zNb(j4aa7uO}l*JjW%jqU`$nUor#NHABL9vd_mY% zrAA_TPki#kya!XpSP(r~zxA&}9u$AQS?$+IpDp}{CVt-?WicVMJTo(+_1;oCnE+Yl zHG%|l7jOz7aS&gIH8U#}&TiorvPcLloh7$?R}_C1OAk1sxS+$bKs#*DsZ3l?rd`Km z6O$`_eV^@g+~~_{Xq7lyYzeB2S|a~axA@|_`GJv0qsEECo}iK|VU5k3hbH_uA9+0E z;P@86MVN`>42?eT^okRkbJ>)6nK6Mq8T-Bc<_uqyes$K@^sfP2>-%gau~yFxe*T79 z|48|B;^t^+cPstlmHa(5Ua^>s+Rv1}DZa#23dXH-Z>-N2*-jIVj^BN3(h^r@$rk6~ zl;LFHckGdWHTCGLPLzZg4Gv#F=c7szT!rl4(%5V=7W10HNX9qHpOg8sQrXh+?;h^v zdZCGR1_}+Suk~}FYaCKnhyQ8>U@f?LaRa&h0~drKTdkS_p$xb!J_NZ;h}nW^O$r8) z27nW2%|K0nEZTZPKn)USU@3x#ok&D3ivst9IEEyLwWFh(rzZ%tfbd{2z*Sh_Dv874IqFoI2@>_o1U2$BKKT>{*(rD9aKlaf*|j}tR&Ns$R%KX&;x-|_Vt~B z&xiCuo&b;z@VL(uT7Ux9!$>n?Yxfft6&-_%v~a`K$wm-nEzEexmBY_R^&I5k;zC>- zaQd5nIa*lPp%+IYam@B9>vu)h24!C5df=|NtWBJ*%n!ocb}ByHpgNbL>&&Cb%iZObPQEcqFx<-aXktbVdB}*V6e-7{~_LE=iztUZP&O% zWkq~O+Xa1zm)j=zN4Ek=;9Ha0nj4uQ<)@Yd@lk}oV^SLy_rl^E?t|-tUkN)GG?S1# z5nST{iT3~F>MWqT%D%TxcS(1NvLX1wm3;q*OwMp}RpElnzCak`_q? zL<9s$fp_1T-};a9t~G0%H8X1|_ug~PKF@xh&jwZt9NG0|4q)Fxx(6T#fP9Dsy)>{g zWr5g_KVLL#DxYzd=u!D@Ee073H>7^5djq&v2s0 zp|Ot)#Pso;l^csk!DSb(x4be7^%_1?Xr%slmGXICUhk^wSVw~<|5%5?=J1pVY)$VA@AdX8U z-VP|jO{v! zSn`hJ+%$LiDmIY3ArMSPR=2^CrunRJW9hzp*$1|Tk)D^%zFc|cR#0M~7mj>WYnaKY zcBA9?KH>XL=Xq4uOAY?9E*%-O@T%F#``P#++y;CWM%FJl)%rOzyx(vzjpC;pboF`h zGxlFvd_EP`C1O4+Mm%$pT^(nns!8eA*x*(doy?NauKg9`;lJDEQqkRF%;nQ_jn4-` za1R9=DhOEMj(~(Z!c3W*q`@v;RJsF=%4aZ$WMmk)fPU6hxGjM!26|~;RTb$2kVt-QOd`oOuoxouIjDKST@21$(7D~`T6&Qc zhin|+N<%_cprRw&1H>_pc2_}JL3$5p&_Ab-$AK>d`j5~n>x3*E67GeUj%1dQ)&$@L zyuhY;r}@*BX-X$PZW6)Vff%&Ns!qb}MQnp_0$=>YoiApax#(3+OkbWX9;bIr{>J~~ zW3i~k?*-kANEWQaHg{h}S>6CNxoG`Pbb6KwOiJ{7;>51z;;Cu_H8n_)??y3eV6wU0 z^p(zF?t$4{(dWIH&W5frM;Ch9NGB9I2?u{x{v5|TR{nQR{F`y4#3`uo4Ds35BX?6MHUfO8AUan+iFe;E?P)(~Mqu5i8ZRe<))C>#9O z-!3yos8>O|BAY)zY=wsi4r2^l|NroUkY?@au@9^%T41_ZTcbUICMwb#10ODECveQx zP0&Wwtnwwj6-4f_fVJ91nis%6^4$HZ2`|^&+#I~AYk{Yu7JPDYCZai>^?k(IpZ9o- zHz;pXiN!ih_zt)}vltlXZ2dwHe^t(>eRn&SNi+J=ljrnh!gof#t_y`dw#j3C<3Wj8 z#@j;d1cxLo@fBg7moF$^BrA%o>%1v^bDKP$kz&^Qvh!^ecfcdP!6JiS+~XDlKF{vV z6&XZ3S}(aomQf9M?WD_ z6na%ndi{(_z#IAy$c`sS^iS^@WOM+RfyrF8uET;G4+HL_rQBVS-@wxczOCQuS!Ygl ztXUf^(1u0>*~0HzNfF{$Mp|$n*!^|=Zq&0|{xQ&luc@!U(QE-=tgE7;H^kB}WoRY6 zwTIOW-o!hQl4mS8TdW3@t}Hb;UcBtr-N zOpMXGg~t~TdI%{oI>v{II>uy(hl&hHr>07)n_hkBE-;)B^DSx7sXRG+j&fMUrFPF2 z3X{;%ak-pYM7gFCJ6*5-WHz>^-pa})(!qR+lcW4W1aV2k4S}S>vd0BgMX{Y{?k$pc zIW&?Y@DoY|N4P8SF|t^d(h%ExWRJiUX?kxj#Nju zpI{pU4>gj+2j3XDYoUG61Z%RPKSBs9DF>NnWD!ORSWkA3Yl z_eXd)$P4zCIGytLp~c%GecJtFwfe_JqP1?4)vSci2kHJ@(zw4XW2j{7!Zn!ccv*-d zjVe0Ch8Os5Jm?xrQ@?6mHfnFz`un}8Yy0e; zQSO>mF5az0P4y_t!1fWDs2tC7BNi{2^z7Eh1+5nqjRn+HWNxsfvuC_iy97BgEVbDl z103~6n(A2f%NimTAM7eLTx-Yg{&n;Eo{uA4Rg-ISnrq58R~kN7s&^mL(A&iDsy#jBNZtia^NULy5UHe6{4Sz`GY3O#KZ)6Md4sZ{tL+H;?OLKvO$^(5I=xRp2Szb z3Kglq`SUL)!IbL#eA2-Z68q8?mYO%(d$*>~iBN`^4D`wFkIhKWh4xs+JwECa=wy<(sR+`q_svjs$PHN>`x%jYWQr<8Ms3U^%Vpzvs8}^X=HV{Q&@E>Wb6wD zRc@QQU}$vocxYQ1r*Y0!D)VIhn!|Z#&TRRDckX`l=L8PSx%(}8*2QSaECNgqNkl^R zxG#P;nAoHkn+bWn6%-$K=7(aug>gbX^9S`xRu;KY{ti>of4xXq?KTUjB$3 zb!|_1F(S$iGqWQ&E#S4m{{VLe#B`tyW~9D&252)8b;IouXg_sX(Dw!}gcl^akiZ#| zfCe{Q>;(O61E2#}fXRS_!oVB?Um*~1sxD|rMO*EZ##H0_pMSh#aTq{`CEK06BY(Fi zv6MrGH^FGf#1wZpQ$U#qqk}ZN1k>3)$#&48!o(riA^j-jveC8JC9x&5!y|`+SfETlcE(Q_K^yFnB)GmscuizB<%IYnv)e(WP0U1xblK5y{Yt8lEj>D zJ`tfz&6!#CJ>MB7FefFrnS#EVMu1IAz)!)izi2`|oqt1H9-6U{sfEH^?#es53|Y?8EE?hqEhr=js1`1nW3eU7>nBk z4mnU}p=%7$C%8|-Dx+m$ikAp)ZD~Q$Szy?N$^|Z@aE(OTu~7IU9UO?6N9lpx5mw~a z@6)x2$r>`4Ky_?wWhkHoOFuzP01#V%kO&4bxadGmAl@kr4nxSzF<-v73a;e9ZTY%4 z7VsPYkC2EY4vVsa)8M*`EL$Wg4}CJQq#zDgfPR6w25Ac;u^Z^K!}b7v5U8i^Ao2ny z3iNa#s{}S0B~fbV6zZ}%Y z!c{`uC2x$I9CD}88qhOKexY}fY~`<{x!+`D?^C8!V^K8W>C{4BVV2YrDwb=k6XiT< zxi;~p3MVqd@{!~)iHfC*C^ufJe>!P4neQ2Wm zaAwDZ#9!_cv}P(4vr+qO+fIivnOl05*G#5)$MjVNhf}hvu4)>~D9R+Uy3J1U$~iFw zY{gZ7ZxW3uX9>At$Y+=!fKDgyM~dH%=d{)bFVMD^#=}J{9l_DSr4)MDNY?uAMsDue z9O$Y@P6-qrSggonfA=FllhXDrltCoqWB`Tw1@I&w5VUjLMHV^ zWtg%Zcx6;!6MH}NJS95B%<3tQTp#^Nkg~&Mirf3TzNwmYQ!?L`qF;~WGQ~SQ7aFsm z{yyys)wqXs3QG?>_a)w&hA)ilxHv31YtD^*w9InsF4DcrL%s3I+`=xnReAcVS3HO2 zm*IR-O*d3L6_&}2%UmvIT!*3)OPtYpt-CL!c>{a8fw#S@KcQ1p0AbwTmo;@9@tJNk zgOfDWkZmK^<20zqNO_iQD{@JKL)v zpE+*1dN&4$0403()4sAj)#VqUg$nR$I`po!p$(w!hBb4Kwlb;_b420JVq5eHz0vK6 zA!4iZ?9Ypb?A|-KzIujOOwL`!XPgHj-AHcmqJlp#BZd}t49dn)X%bSYS(gNZUrmZV zoGU%Rj@ya+LMgux=B)YKAH69w_iMLubKj^@#(K2NdnpTtyG0t~<066Ef$=$%g*I~8 zBWc`t@gFkuP)ydP`^jDljnpqOHT0i&@)JyRyw13O+`3D&PffeYH=M5hxFLRmww*-K z`+*xBtqo0$u+Ap^!>q%ZKHRXNP%jtzYr|w~f*(b_Fg?R3+)^=a@<~lDpZ(-Km>4Ke z4Z27FC_}V&AV`DBI$H>X1`jVerb?sECPyRIalsDtEMhU~X4;-lA>G!H zke=YW`m8;S5p^rxz0QihV?B|BsHx_4+b zfB5Mb^CHFVtC6qioItI4rM`=wpVR9>o(Jz7L3+KrsBpxpG9CA?vECdTYYo?3G20NX+@#}#}2*T+g?Ql1h;d7 z5`xA{tMG{Oq;odyoM{*mlMB{W8HlJ{qgreCd{@`raH(B#bM5XJMW;r`VMd*gM5F0i zyVgr4o2xjm{lVGm>F<^Jj!R4GvYfMic5=7v2b^5to_T<3j+}r2(M$wi)@KP(y z33D(ut`vJ*DsdXR0lmz|tb-%1r=bt@Dl#qS z%=R^J^v{=Oqp{q0;K2K|;RbJtb#+y25=D629@W}Fk*cJan#vR54g#q-RyiKnKuTX% z@wze?$ttQ;No>F1EgwY9-^Pe?Hk6O3XI7T{{(-~o*ezOVlr!n2mn)%5#e1z1`LSqL z!C_h~-dh|a1aX*VHg&7(M(qt@Xz^vDGrM>L0`9N-+?zk#E9mqL32m$7pU&4D)v4fd z*}uX*^~2t%BCEcq=Z{*y6)6@rXqIf8f1e#L??)E`=C9o5p$8X{TK&X`cg5BTTB4zF z#8?yVX17XYH;a!2E_Mr~)gTKa8|=DMvVM4XA9rrCMr!?)Q$-E`Moo|e%J!J6#&JD1$UPi~rjN;h{1_KF|0jfo>@j>IY(5Mtu zDKjW@?-Y_EXcoDs_*#RB$nDE`TgN$v+ENrMN$$E| z)SMZacKvFskKBT2jlqMGFw~CBT<|K!xPKP^9EaV<^+DdglUfZTAK}rYOId<7_+~-F zrA*6ZDzPLuo2QLJ_7i`oadx(EdC0Pq5@`gu>oD5qq`%uO;cQ--*SJxi(=5^29qmhP zVqscj;X-B|_7bmdFR030|^Xtk!B|gk#y34u;SI2gCYkh@{H(M_gJ?R$w zY+SMHh+gP^+2nS1O)~ony%n6FE5dX{cPS1Q#R_ozn&jxMrYi&-H{}=X%Fu2G(4vMb z(g>2}v-vH^4+pxs6;9~eO$rRA^GERnU8A$FDh?Qk7six4yy8Qn{J};DZ`Ahx@{@Qw zJ3wO$T;fJ?Wwp$;&XQ|o_?s=}de#??>`e=d-xqBEFu3kxG~ru3Asv=YC5*FKib-`N zaWmLLvn)+P+DwdOGp{}|v`=TV(uy^snr`jK(#i;WLfqcSyngn@O>2s5c#y5LpZlvp zQ=sa)zP^pVLqJgQE0aDdEA9;6U3#s}@6)GShotc(lxqF?d>&rTxzS3zo!#T)>8+yb z?(vRIRGWD|!T#%Zmk6edYf3n-Dy z-DPPDui*YOcE|`smMm`EzM^lsjh@*=fs~ry#I7#BPfQ-FWcU{j#ZAq1#|7yBF5Vt(WemHWw}s52d(LKauQjb|&D~x$HM|QyGW;*aaEL$#e?&+ zLKVXDE2{CTy&sG+tJiZ{V^V2Rl-bD;qT(mMyd<_41V3* zbeoM^F44WRhL>*)lf-w=8wRdRW*TVi6cdXF4&KX%5Sxiz#I_DAp~S~vyqPrk+}@Dh zJhWhejjDl9fVcwRo80P!-++8$E-HD##E*8SdqO~+N6H~PIg+%(pMbTvRpi=+!5ou? z+XCqd?VH&Zic--pb3f9Rk7`~ghD3AqFa7bjioBqABsfeQX5=}A5&^UIS7@$5uSW>P z4^Sk*#vaEhV1CYVu8T(%)tSgC%;I*9nU(?6`+DdG0+m7@J2sfH7?Z4-}O1M$(X2gAss%`NBhGKo= z*ar=Bir1T(yyKq>mCIDnJzVG~dUa)--q~04^^ertN=W#1b;>;ZqFvHGkyH{zjmS_1 zIviR~vll%9_Y7SH#H9Q$9ybTY9-GqK)emU9;3gS-j(*!r_EBuT`!7=2mgaG$IA@2E zLIM=A4nzJOHU6<4G0msc?<=WI=SmiM;`NMNW}03zUHr{3Du6S%pZVf>RAhAMq?tP@ zX|(cKkscAZSgeQ?akuGvt?0ifGV9TjBv2G}Oc}T175L_EjckpGymZ#Sx8)Z5?=6)~ zwi4HM>x+!%u>E3DIwC&?@RV z@xm~RqTu-g$^nVTzS^I0K{N|Qasna-4_=(;4odtM&(7MxX=1d|+G^$?`uhoFG}@N1(R<&Y3Y%{gVHlt( zqxo%a^kcZyaK$|f{lj3$G7E05dKfm4xX~h4M!$p%Z$QGH;1&UWRca{U`}JXhhtfmc z2j=HQGM}_)2~OG)w@&^xHNxLET1Je8U-bMlo<_TN8Um0yK$6Hl(!V0pdAio8GLJDw z&nU{DX10ip{-yNY?*Wp@AD2Btf-^Ga=qo30O;k!>U`UnkX;9vXW8hvMiAEm~M2jae zW6LWLd6BQ^q4HFpE5Y;U8dKOuA~n-6{#=oH$7TU-BD?!`@!?r zO9R7|sC-|f&R^sb6G`>f{kdwA2+T^M|GNz1?c_0jQzs~(gyuhBffAV!--=GvI)aWl{In|54+hw} z*PiKSAv4t5Gqb6LiR!%jGVH-uvWYN6Ze@?C*P1&Cw>EWV;KsfeaMk0#wjDN6=b7D2 zA3KG$-F9mp4O_l!3FBAstsYlnlYFMwvr2yL4BF*Gr7M=rBB?g@z75hPmCW0K+Sq-6PGXflZ;oN^TZ$N}oir+R-!e?D zR=-?u)lhI7d_Pax7z^*1QH;-^ws1$nqISMfPzfyjF`FdVIXZZx6`_HL1Be0QQ_!=S zycIzF&Y9_0C9(-Z_z)#Tggf}@|Hs1wzx5Zz9L%w3J;I?qq<JQuGbfy*dwf%p$Y)htW}^RN4{MO6)6>E(5=@8JAupc?#l8z_ zQLrx%Da=uoZfO4EHb2YZ47r@#aNRWHsr(UleG8_!5ilu4*x?F*I3YD1) zhQsLgWidWYlgkt)l73Nxo}bz6%qu>lyj?mw1^FjxGF^#_Jr_IoUxt(K{p;)bt%PL# zt0K`n8F33JD>s;@ZZhhr->~dk+%+~fz7J_g1eymC3Gi7UT@nP`46F)h@glQmplQ!n z^{NYUa|qaN1SPfOL(;0UQ=L#xQ@gr)Iy6jxQL$YwfAzu3vKLmfUq1Y%KcKm0DllP2 z_{kwPCZs55wZTtm%Su>u-fcKljJ%1mj4KK@*oS zKC;iC<#mcm!1)^Y(&A3h#it)PA50jeMPQ5xc}lo_yU3I++UFeO)+m2f2TM7u&}P}D zp)@`3p!gKB8Ah~>(V;ai96R-DwdKVEhTI!i{&gMJ(eeZ6v%{O28%D-HE<#dC#WB+; zW6R?Gk4Hs|`rRl>>Qph)oHM`GC}(N4yT;1uW(|8Z%L;IY+VdmL1mw%+_Y3I#d=h zsD^I)6b;0my!(`9>2SYRqZz&Oj!x7Z!M+dLj0(1l`pIJYJhO!1CeP$Vn5#OE2Jsr2 zzLRi*Z82Z>&J*{9#9x9F&n`YgUG7p|XuNITsZ+B)&i%tE5ywo{aH|BTpeC6!TQtZm z{n1Dz<*hNrR)Hp;d!?H6p$a^NEa7O8bVfQ6TMeAYOsv}&fwMivYIO}IM>+yL4e6Jj z@`m>1w~uiwqeRff+{*|}88#0J=RC?O&F*6z(r(_jkNFqx&K4XP-PSEmN$R%T*pDqw zHb-;r{&&m;$S+!%Qfkc>pt^Ob%lw)F+(Tvh0diXcW1*x5BW?=EcgbT1#uNISI$ zPp@%(E@c^4UX%8qqz7jQarVrf>1>JTZO0b@clpX)Q;S6~EZi>8imAWYd^-=l_lP0^ zi=SE>`}s~E&A-FNq(meEUz&-IQzhWK*hIgMc7khHkJ080d_%rZA_lK$jz+w9ic*$F zM4kH_-w>)LjeHi7UsycRd^K+Q%Adl46TdFO)^@HkS#HBf3 zV#A=qX9FCrf)yO4){kq|;hUNur}|@s^&l$@r+SA>y!^$(klyf> zQ+fBpRz#evB5Wj7iv1?f=P9O{1X*9m&cQG;e1-~0Trme%6t7ezqnD9rbml;(v6!g;@l)Zi4 z(JL1CQZ4**0#TCPYmInP!H?#wS>7|~sHuS2Hkti4N$ua8`V==yC%Wz|raMK2dZ01U zF;rcN-3Sn|%5PR>lOByvZ88_a?ytkhErsXsn?**El^TvGD#e0D%tL4bh0ZqP) zAZ#K+(98}U-(mR0OZ?-XhrtgvaGT5pDoJJN$DJc(79OFDpR8@032x8McMCQz@lanI zz><%b3*f$(nBiNUtiY3J$uJr$n>#FSVWD04FFlVfm>kJnue1mlSKaz@GJh@u{y7AX z^Ur|0kn@9(A>btd_HC&v64>HL-25Z~aR7S&+|modGYeK=O*;6ezfpS-b1HOF z9(xN!$KTUgr*vRR9TNe-(-NQ65dpNKd%gZr3<#BOTQO<9ox1PsBq`|bUu{@=wf)uL zUboLz(_-?$xFcjHY_~oJZrvbsl32&f)456AdmVQJh&fpK2GWPT{1Yqw0$klzAdYZk6i% z$qC4c`{g9AI)7jaskP02NXfD%c#OZa@N@qYyVC!mudjv7kN^g<-4 zjkMr^qy#er_29nv7IBp^Gb6*@Ag~X{CBPM+DvlPyNgo*X_JR+TM!@1>>1C2-`yKhD z78_Ptxs!Jt<2vP{CNtc^t#zGCjxlpBePh&S42c*stPgu*qzK|?ZSsZ7CtM;eTR@&&iT$v$uV(aFk1{6u9IGWw7-g|~+z(Xx%7DfFG5 zrsftsR%XC)Dd6<+jm=OGcg)61&NZ|jaVHt!rKW8RF{-$=v^^wW&y{G&KQPEyX72Oz zro+n^4z1hdV?s_r%EN6hXIOZZW>a7NA#HKpL18XelPI`AUlTdE=g&6h0nP5K-46NC z|D~T0Tv@Pfw;;5*zg`1!1`@%ywZ(Y%5>lrKz7&F=kVryI&uHL_0dmUub@&xx*wD5_ zW(7b5C$^MN0oqs4v9eA3nrIQXHT;Up<`iuqXWPl}fF^9z?0< z7(UpaUGxyoo8hI4nu>4^=%Zqy)y;OTD6P zWMd-M!%IPu#-89zyU$-#h{7Js%Cy((5Azw%Bo>R`Hyxv|plZ(V{ivGY>_gLT>R6Ps zQ$I}-Z@#4?;`CW2-ppxOM&0TC)V#Viuf>qkI!9~#1IgM;b-4RG0`Gr_3eAO-d2vc+p}+?dI_k zkvq{S6&u~Ismi&4#b0jRe8(k?;o#Zx*5XvA zc!=B@3m?@-hsF}5iKh;YERwYCO(!ujY!p3Ke_BUL!rZVgI1}*brEY5NDs8R{+cEQp z8~ub-L}v24i`tjEn=G7k%)&`#R(o(A$j~yQ9MLr0bnXTHko~ms^}9svhNk*0fR~J0{d8!iQhs)ir>u!OAJ-} ztFsH_l0Ryw7fi<_%YqS_$aIJjX~K`4d1@<2ZhM!gn>9rpi0S)MpMmg4M$!&(%cQq! zq6**{1-zv6N!|JC>B-*BkRMK(j~X~t;-xRRlnLkhylX?)|BiaYug{ z`;ib6!>(MPHf0l8cIQzkEhg)Sd_u^B2_A zh2}7e&V4hPb(2*1?5nYpC6l4qmuQ(W;OE_!tl%V=+$Dw*RcF9iKE*Dr=ltS-p=w3{ zSDK#*))Xo)h%;OT{nex6cw&&8xy-i8LaT_tNvJvX3G}zck-7E9>J0XOO$hs{QBqr@ zPV-;?p&YO*4&(Oitj~F-i3f*#N(!4jMZen=@7MI|{Ql0c-}(O10n>m40n>wfPJ=6E zSOXm%xG#0@!Xa8EYC6aL)7m|zWM*~LwS7{0nj=s8e#1L~f@1-nNzA8M103J47QU9t8I^BM%QX}tM@5QJqSM#b zJ6KeVv?(9SY)BG+og^aX>6P)u;naB-DMJPU-3^voVyvtNZ315C4Q{zI0b( z;%_s3`aRSQF29z^PxnwHCOKx|6~)}WMBZiJJM_{tx@?OZJKn~yDf{19p`cE1)?{te zs&}?JOXSpL8I)tOP}@1YoK?vx{OIAqU)irin;%(?nL*m^b)<-*w5CzRyJQApi+LqG z3M`3ZGWqDS-j?wvjNG+U^m)TG-Kfb#EEEQYMa5J_Gk-aaT0YU!brES(1}k~F2RZ2D zB=HUdf9$&bj!gTQzrDhzxUgGg-`xwDSUo4t^6nbIqpByCbw2$S_Q19Pr0&b^vL@Df zYkIqShbPXQsK!~|`j9s9@+MRe4^z|+^wghf*Ky_|Dec1NG!phlo~SK6C%7rin?Agm zZJHxq+;_6zs}iPCzZxC1dhs_|{%P6B*+79SPOC7H&u#8&foW7M#wUkZsJS#PG4Cmr zIfA%)qqY44vS9J-?vlF&J0k{`gMC^_2BivYRu`Y$Q8g*8H_5$_oy>L~`N!JDH@!p9 zBMTyD#kysIc}5oweSAz6CEQq=O&t6S-h6UQQ6K9fe05LU_4oO7z!0Ze<8g6@i*07ncxxne(gU`a9mb~c8B*6(5mo%cP@v-n59 z`-=o4 z!bIsfMQrUu(G9zJm~NV^7q)R?D_^?2}I%V_qDm#GYD+pkJ9 zgTpfLF*zZPpgdle+i=45;C2s5BY{PkhVM_w1ipAbZLX0@`oefY-pVx@bHudx7b=(m zk4=yxKTqs-f9*&5%liptB8)Ws2T!6pcID|g74{Xmw3MEzhAx`#=~qjW3AAlLR+XCX z+9f7&CYyG@dVTQ;@AIjyPBQ6;YN5!p7~r`4?+=Rna>S21$@qG+lSL}o+(12M^``UX z#QIaQvRR*dBpV_vG6`JO8Wgj_LXnIjgS(3HTS{v}+srqqOoUMJTqp5A9!+D7*!#7_~YGbT0YkrgZ#lNg_$93zyb{j{2xXq_!T(TP5M_bqF!-(z<+2P>uhlOZDV zxD%c}aw|NkiwfE^j0Vy&uY5b)3&LYVZKmv3o#2er_1<|~4- zSNl|j6hD&V@m#PaE90;8KP<@nB~R4rG;WO{G?xF@O(8SY3yF9dix(pjx0*Y99wf6< zstG+Tc+4wo8b*uPr?7;NNy=cXyxzjunj#Q@EBdX1q;fC%WCwU8f4+Me?4iBWneOIN zpdfADgTQ$1>?V0^FAM^O6O3Yh{a!0HBfx5yuuKLsRwxO2Y=wxr@g~Oq#_qvP$Oy8Y zWiRlNj-V*VM6zh#3EFsF{@wh)EHV9@I}MPD?1fkEG+Up1lLSPvpPy>IS+5`wRQTXg zg=hz!U;8FbK+xS{T8`0u%gnYdeGi|hsfy}X_d7n=#5Q;=;Sol}t~b;A?NQ0x&E6J9 z1&cA>%wa5Yb~*Kpoff}pcb`+G)}BI_zr*0&qcMBbF!jePI4QTKU zEG+bhCq1t+dbvr}i8b;O`+C+>*2hXD-e-2RLZgolyE^*2x^akzhKeSBPR)1-r|rD$ zp)g4e<>_2lu9E)qX^GGe3JsN8m-pDtAE2*!OE5Ar0?ecnMiN0N2!_vi!Zb((${tt+ zpe`6d3~?*SAk>*%21_o`!w?WS+#GFaA&B>LZR8?&YsDobx&(=!xI(7mf_uwbB1l1G zKS-7~i99G8+wND(?B>gVrYud*&vP*+BH&G6lL6|e)0e5=#=|2KLH;Gm9OHojEHjg2 z|E-9o#@KJB7(2|YVoJZ~e&qK^)5~31UItC&PwcFz6KX%FJq*>EGR8fXR|*}Wx!{2M ztw0xf35Ps1k&UD9LCKv|_$yFY{rz`I6V1SgJvypMy>OF)lp+Fu6l*<{Z@RpWj?ZM} zsTXh^F8$!8&<#LaskYyxg*2N@&-64epV#deS}%D|wG13xru9w4B?^$5}V zNJ9=45eywz9hG?J4*(YFSCN_WkdZnLkYRa=GE2bwx}L}^%}yPQ%x`6nKma;M)gFMQ zMB-vuzgM^r-zyA+f`kwRlYmY~k=UQ*DRFL;aMYn&iX}rMudOadVqX4ZyrhB2|BN-! z4am~I+05f~V7PjPFEsm7LeB4S)nCKDZf78{fg%Y0N$_~Dfc6V?iy z9Td4+H)(JJelc(0G7&U$#60Jqr+MB&b@VkI#6aL+Lrx1JDT37;!X7X+3kKMoL82oD$U;xG zis+b_3dWsl!1CSMiM~3Nb=%f9%!L1*tp?yna-d)RBM$^$5xugLr-1oZ^TETueM@We((M|ZZpo0ne+bH4Lc zZCem^U&l$j{KvKFk_M-P-}3g6Jsk{qeafst6i5ml#jMa`LDy$j@eN;ar+hHrO?6dL(J{ zY{y|WXo7O|;a5@YJ#qxp%reYv=$HHLHmWtf+HbJYU8Jb5iC+$M@Ui^QAvJ>1T75wo zmtyk0#hsPBci9U;FM&56e!5pDKU)1VVHB>sg;L|J!{4LJkuh$_lq1C)orQkcGa=d2 zb!}u6A`IT!^OuIX2nf(}{&#vvH;A+Vkz3h1KifKr4mreylqn>2z=^3bMr6wkQPVl! zc?W>WAp}x@S0NK0rKDB>1qI_D5zH3*6TH66LB|;7JlK^0oc|UK+>n`qogBIdhuhtx z0C5D4CbXZ?8r&#il!Bv4)bagTJCnlvXTOa2N2X+4EFBa`*tm$(l_iHoV%L8Dt;ekE zp7nJTBce~es-%jlOBceM*M)vIi(HshpvCw##JalV^z$z2=IIv^D{34(3Ure~)}%*Q zh0<;}eyM$_-`}y>ua0+B+-i8}#(rc7d%l8t=wqBNG@jqV7p2x0)mijuKbnyQq==;i zKD#5KF6I2!n_Zc~@v8qEwt4GzQe~1~Pl8$TKqmor>il8fH6%|~poiZr2pQ~tFK7?I zD8~8u+puMt@b^Jf5An<+12TsYuoOH*B-M+6Rl~zE;juNrpaK{}j!Y^6w&EqS3}Bjv zJNiZ0zyNAJbp+59yc25$QLsU|1!;K1@Tw5W>-B4Ci%H^$@7@xFD=Qq}vxPi2^8O(7 z2EQ=?4oOHzfUW?O*+NkwGqNS&o2LTwpMO1(zuKJ1HC=VDsj;qi#y!Od+Jc6Zk*$5>y8U-0Ew^ED%{_f@*}lf|BjF3D zeUW;5S4%FBv1U9Jy#Ca|pa1523_=<^GVQSB&ig-cHAzmsShE%gz2O&oBBMHgL!Blf zT0|<4ZLJAsJXO2k>#%F{DK8#=k3@pPA2lL<{MU7<+AuE@Rz0mbNE*YL|3q~qBD>Tg z8iH_O_yxs4ha2n1t?`b^vGwZO+HTNWU`;?`1a@1nyTgnQ$SyCAteItb?;Wo{N%b>H<;H9nGyIN;e*Ed3Og;xSkU+a$_GLvgnTGaQXz-w|C$*- zTbM*9_OJs_k~@Uv31v{uWcM@XL9N6J^>Fx1_cx?lZdsv;Q|2FCOc1 z=n@jFH$q)H#aQU!ni?DwbZ60GD$BFpU8Z$X=OgI;l1s2m#?o60^ zy~^v6UQ$ckMVDLud5Frp97q9S(eTY{W)*s$rqoeD)sy*~q)gZJG{v*5$DGRC3k=-oO1489GLbP{O-xDMfvO@A4klQe4t8(M#Vl)fLHB&P) zw(y<7V*}4Nc(11#g4h#}-jT<4YgwN2kgkVw<&3UXx9B^xf6m(^kh+dKj*jNB)L3WV zHYAh`v|-2X+If4K$f6Llu~d-Ab_DNYFaPdUyW}LHrH0VU2D+s5#n>C(Qz&AtXa`^IZ5PFZ~mZx(2aq;7*(3?gHGIen!~oxEAg!HGo+jp3BAFJ z1y*IW^jMZox|;+I8`Ag8EnD>1Bhlv3*D-{Pd9@9V<}0O|-1n~kr{drJ{qw!pYyGaW zV@ZDc=w5>qpYO2Hf0E=0KTK&V|E!-|b%!h<6L;@wgxjo4jb^tXhP-i1zq%Yr)!iv{ zCsXQX3-BYr+{v#HX869f1(RxEju!$qfRzs}_PYw%XYowQHpW$gAFYV)2W63OS%+Q7 zTUFan;4OFkuIqAL95cNtM(JVOFjqdQ0*O**=$qIWo{q=rqZEekYj|7Jfl{OmW$}=JKI@rpPj#UnL6afo@LhpVQ5T8vJ8$4ez!G; z<5gqT>iUViWkRX>!i&WDb=$b3ZDgnFNnMHrq@IbB-^0l`71B-}$eM5rg5E06-Y&n~ z{6I}!Rig@@_RxrkltFuMgM9e9fn@KzC}8J00#n+0l0Qeg`XNe*kR{-*f1x3p#H~W11f~P zRK)T7gCNF!{Jz`?d@R!e_2)+K(0~dJ!#I!$FhKYPgx@y82}VZY;;|hL7`Ju7VWnj+ z#wTmDM7hiJ^97#n zyAH~r5))BX$s^ieDudWFs>97&8Q~$93duO~#J(szDt^nF+tW{EnbakS^JI#g=d`n% zK?-N`rK~E;6AYftXA8$qjfR%1e|YNL_2f{^+j2ONBDFeJOk(bDo}IBS|MTqldjIQ- z_g;#}>CmeeK;S0NgdgX}Qg!X&wL5gAC1pz#)Yog8$eP;nXHa)dTt6scu z?9B5*+NSn!=c7-DZTaKhymXwFj>zeHGX4@y(?O3dqI&h;TKw*VU;JBtk?TkgA#r@j zgFrkK@Dorn?Cpe> zo;axVfWrlIQZC@LftXuk!tq4adUhXwwZF!u#AihyAr%Z2sj4_Ny8kQ;dO7MzIvhuYo%%%KA$`Ad?3q=@Q+!7 z_AUUT83+^ztPcTH10NNHw7^XltL|MXD9yyh#pUo|^c^>}bgZFxuou41zAMg1XG4oK z=l)F6_eXVOBh-{|AsO5F1r9j`D6GoS1(Xp$^#I01gucLp9|0A@7Yy$VDSF<0d8ot= zm1AFjKlJ?Jy5EuU`$$)FHSFR*%_}}_eyU&Tg`34D%nq>_#ee^p#(}dy zO4L`{nc?g+nfOdcK}bPVd{=D-C(lj^cmPl&PKfr6z=ad_n#^BJ2JtIPJAPzyaQ0E-m8LrAa#KF+UxsO{kVu7A4=_BTs=!4mWE@b=%PC}fpOU0X-nzAP7^XgJw_DvCT%kFcH~(JX4cm{Zf-P2~+3gGD`QoYhL2;q) zKMg$-jo@%Tq|_HGR5$JWsU|GMU`|F*c_@Bf`_;GCNo~}2;a5B@&X>TaPb}i%)uWXs z;jD@fIjLt~S#A1(oq5H{M|!{1a$B zl(AFg(H8gbCf+v4tTxk%87N(3+*{^1*cDIVDkn)9P$IcD%#aX*N7&#jy?HMk;Kyf# zuou8kGTDVI=RdE!NKYqBC5?TzxD{npwo~#Y8hd>^IIZxgIirt@A`)^LUuA2Ox615n zAFRD=#bwHBG;;ZUoN@BW>QnAaiuhJInBD5dQO8ZA3TC=1tF#Srw(8Glr3rMi?&@D^3-XC*wvCG* zc08Z-c>I)@Yi@4<+YRPg|9ODE+IcS#mlELj+%wbD#F{CXq{_|&rN8u&Jf%CVX7xT- z+PBEY+0A?C2z{io5`e$qpBBfIR_8^9lZ{>9R96?4cMWg;BJ1jTNfcqTfQegA(#Y&u z(=wU;C5%g6y**^39nC)EbsJ@lDj~if9=LOq2(|<3UnOn_X>?z7RPFmI^tJEKN|F%! z!{GOFkDvVh{;+ou|IwI?+JRdKYsC?n z(JT=O(J_J=fg`@wzAYpw^*GV>ID`b=1J6z+6O+vPQN7auR?~R7c{0eqDxtPc>z|=ZbqLiJnPQgzf5>8wPDf7PeymAD&}oI6}!x@NJ4+9l%6p{r+7Jk zjQfw*nl~al% zM-CwcHY-cUDMonglD1E7`~tzUGjH74%i9~!k$H3O2bOi1 zp&uIDz*-198sP9alh~+Zu`f`A%0jskjM(B@%&;}NlhtL8queW)B4cIx#wsam`l1KzTA*u;fj2a1MB!dmHt0$*!??Tfp_lo$A`*kDw{_~?M@BYrgUQUERw?qaB+$RwLG|b3_ z9~8#JY~FjKXKQNo`0n@n%y3-Zs)9ij$iM+OD}=9KhY>JcBAQR%u29S#y^3ECmLyWq zkFa{7I?`Sd+5l#nbyK40kV8f6?Fa^UIW_eJG3iIOTg0 zcl?@XyUU=-pLNIJ?nCN0+z87yb-#^!t;k>#m|2Qoj^I(i=>@~p{>G_*pAR^PY*=7F zTK9$-NQhw#P)jiP6KJf@n(lldh*84m7R*E?ADr+}^C{R`E(kMY-5|oUvkK$8^eds; z=Krzv9pG5^ZU2Qt#D$V1DH*eqhKxktH z!eSq_F+6_y*E3Gc-^EPi=Utfi3q0vVHK0>eFDP0tu>*-J20Mx>UDkUqJe{3=H^J_& zWhoMITVwXvd+Jk#UrrsZwU+&Da@A1Y&+>|I16NdPv1_ZLUu4y!*Vl&xf1U)dsu&A2|*9km^f3Fr1RGMv$ zB$0I(h#?{fcpTzCKr$&qs}8SNCVkM$Y{4X1!1pA;0F(YO)l@iHXG>;A*XUcjXQ`P13<<+3RveW&}z0! zJ;R5yaw(OEiz>~Y9FVoOQh%+oc{j)9bwb=!%(urpm~#BbcRJ6D`On7bp858F4zb|c z^Wq$-LYN!b1Z0*Z(eFC@(FRaC6y4|vfV`(QpB|r?utr}&op%vhFpL6=y#}QnV6<@c zEvK)wotDWJ+jctT=tCpG=qLXtHxg_4Jj(wZ^HLqfRAwuQ3jQ?K$zGf96A1$nif=Y3 z##hsxOZ^sBQ=?2n^JO>pvpf4TzyJNsZRX=G%VbH_9wm{7p=nw+d^G2H7d3Z>Fh(in z3)W?_YDEmb%CJfdI(~mio8C?1^(p1M3=FsX9$313FY1=SB3>F>np-Mx9-ze7M}>T#oTsA1`tZsdca2J{Rh; zHMUB0B12g-H^7&VE;L7xmbFVdM9@lY;IL@7S?R{~`3J4r{9QE7tvH4BXStrqqglE7 zd5eHGit6xB!BrHh7~vDW^g3+eg0-@z{ZF0x`Y)Ulhp8(^Y6aE;hPePQ zvhMm7`Xv-W4fvFpd4h2jsC$swAsDUE>&}g6OqHPjOxVE@fk*`w)jtTQiivV|Yx;5+ z=YHHmU8CoQ-)1TY7^U~M^b41~rajpokg+GK-cK#G#Nu1?h9`SWgBLWz{cqDc)YeY# zuS*kCjQc3Ox-Y-}u&7#3wf%MW>ox)Ud@B4WE$L33eps8gQ8<0aVi|o{9!Q()RvhPj zWZ(mmBLJdewnyO~{5r!#Vs*oPbcP&3B;jY;>rY-O($8=Q5Wqoit3{V<@3mdp0Kxak z-dJdVZ7nG3^Vs6UhD8=d)nCO$U+3us-cGaJiKK6L6JV@6u=dB{)GIwz69yXJnoNrA zH23ZH^`dV*8N6WUe{y@cu+>8SglRx5M@3ngDkp8wH=h$UjgxAUf&4n%@v~Y*VgEW{ z<}Gip8sMwQ`KTeFD#M8$`j+|Vb)C-iXLj|lWE0i^7qqi#3F`}=Z@(9Zr z;9uPp!P9y#Z|w3>OA-F@^{cxoJnfFb{D}aIxId}5% z^*E_hhLFn$AUWMoR0<>Ukib_6#0T)ia+IYI5E>F+h%6IC1Y5(^Rt4^4IM(VhZ*kjA9xDa>dW{u3@H;pP(P`q@}20_W?FP z@!W9&xt>uCgHigJ1%qcw$43wPTGKeJx&;GAS#@AvJQ0Rz?(?aB-_|14lmFXlG;O(4AjiH3m6z;lBU z(7?HUF6@ZWx4u5U<eZ{o#KrSoywH5qHh|gEATx4HOEK60 zgr`*=2j&x-J*owpoU9XUlwD26v0eObLMcuEI&QE(osRlUqFhSG`>*HPN8iQ^y?vUi z6&6BiSMTZAMstD7pPMC@m2O)^RLw2lbkF|d3kAFBkFd~L>lrM>+SKki<0|+tMSxX` zrJ_dJPcpiKLx3gNb41r!O3CHYzg~ijPuc16nRSo{|CzjvEe4rOtuq+a45Mr*Ma4J3 zil~FfaWP%9*HL6&%}$k+$j4xILnyhl!s zjPS-p&L6-el*9LLMf6sGBK3ez5b~lm`SzfIqP)1-T>99{F+jBHaqCyo*a5(0=$0k+LO( zUuqgktqWg}POkCg+LrP7uXC#MZ0XxMo?m)ew3n-?mig6-)IcYp2g+6)KPSVi*+cIJ z3aV|r)-OXp)=?#+4YaaX&D_+KM1LD)uU9*C*W-bq=pS7b9y5t&s;=IT&yJf6KVCGh zA9Ddj1aa9RWbu!`8E*@z-}?6?vC$C+jcGSFNXCVjq9AeuJ3IIs->~1-P1)ZLB;X)j zziV^kR5$0GI8W`4@x7@b4%YO(wm*}LQvw{@vi4E=MD3sNu)CMKS4_=k1y%D!jzj+O z)O%WGhZlq**!UbT+cHWQ4i`mjsi@L!o9IeVU*r732FBE{mx>tcfopC>SH9F$@0f=tpKN@PWhjcy9J4gA znxvJK$Sf;lZo4VGL0^Ca?z9X!$5A(;_JYESy16~yL90bg^Y<|SN=4?rs?}3L6zZWo zMB@8>8NR_lPnvGzq)OOn^i%RpJ5g! z=l#<4xS6pNKw#kv1(Zw10m;eTGFy%Ve*Ic2cOLfzGq-{T6dDi=fXmvN&;aebNgL#A zh|LSK#JE|62qR_aPHmGW7dyWm~4zZ7HAmKPOD}3A%Opb>5(%WoY!=$E4&&gBFIj)FQDtg<}41SBJY2z zeVQ1KOM0(C2Z`yTn0AZrLxNVJR6xyi`q^=GokiVujI#S)NZ|LlDR76J!VE}bG4@YQ zYxvr`x~$B(>yqE)AeOzv20j!byER;O_)<{C;O(HML@zz^sPqk%6&5TC zX52W}weDE2}VS z(cmu;v0Ub(Efy<$L$=Y#B^nkfHkw5?R&wX_pa1kEWpag8VYALa=@XA z@a(CbUQm8|WNkfK*Xvryi-R)jY1e33^YEM^iNwYTJE90gS%etfRX2!g8<&P@gWH_tzlDRbcv;x-&&w5CTc~qVcz5ObG!8A13 zm+R`_j>;U<+0cJ zfB)3(6wWlqunr#_FD@}K zpGmA(37O-oE9^R~*A6qZJkGUl_RZ`5@@U6+MMIjJb@wkU`2Uv7jXbiS$waQH(yx_H zTE<^6F#uVbNCih?F%wr(&Im9hjJ`ox2?-VKAE1gsA*qJk>M&h~mU#nU76g}s(Et!F zN@0v7ojclO957$LoaUuv;KPlEJ`w|FyB*1B;JP{uUd~NH&Z@>-t{gtmIs=xTj2?9F zFEYEoe9=(zk>y!LWN_e`^)nB;4x8z-MP>|3r-YvKc8qv*ie|>3rvc@#9i6;wu44YZMQ5rc)g;yD=5^>tyK|f zA=LwFqg!v8CFaxeDoM08siT8Uje5*(-$)$xvDgO4sg+^a5i?IrFhyB`O z_JV118;=cpSXtpVrOz+DO}q{@FXgWj&e}lbGtS%9F8PI_^KH5Gs(Ws++n(6wByY4m zDR4-Lh0h99N8(H(Bh?NanNkB5&Y<}J)5NRX-Xfy-z1Nr>b~>D}q-v7k#MBI?u6$@@ zA>Krl3z~LWox~rlL32F^S1+nGyaZ!Y)9T6Dh=YRdrUg#ESWU3znl4uiACstu9ycP!Hx+4u4J+SWz1!-wjF?I${iO=VD<5tOcm;~Ah zs-9p&m_U2%eW>TC_j(RDWB;1-3+GR2s=QwJ$$%vwx^{A}N4wl5@n1I-QLRc#+` z?dIv-BKfoF&cC*TlGD@5nRPZ!a~@00!xzX%3Cs{h-Hvh|sM{aaEdUZ6P5~4&^Qj@R zxJ;q?S5N@LxPgxbTe~i*acB}9N=7V^N&$_@Ggj#1Hj1$AA+o$bIu+;_`3Pb!@5-5a zKrg=k>DVDUecSy?*HkNzL=^T{5treK3kuXclhy-UtI9e=s`DDy_-0j~NP-2Gy+zqo zaPH*Q!dEPhU&$GrcIKtJG~c_;g+uYADjf!Ta7UiU{CCeD=6(%e%BZYFRXd7`5>ts<+w99CVHLOY3 zf0vKz5;^jiyfe$3ZkkcXMw^lw6%@!JvtQ=wV&!9+31b?xlqI)@X615%f9}oLzFU?q z?A9~O9zLxvt;+f9>lZ#Ywf$nz*nOAH{jvP4>f^}3L-iLp4t9xYtuK%Szzi77PONg~0_ICrAFxskg293XxAPxezX;i+P zY8Q$*h>i{V%5S5ihaVa_n@(G=>g%cU65B1p63nAXiGR!!)4NBaVk%dG*}%iU#zj|g zHji!LOXvU{{ov9%jWd^Jq;f;rq3nTJ+ulNqTSm8Xt-uRwk-3hmx9OAs6XEI*jl;?G z`OB9Ofc~gQoVgG+0-+c-D2^Z)II>&6xE3k*q;Z8+lbMHT?r(LCl1e43MJ{4rRtv;1 zPQSh#BSL)i{>YA1@Sab^o0f~qjKxNSzGsD(uY%2F~x8WRKfb-Sj$JVho1+^n45 z)6iAcQY7-fuH^v`?#cxy<)8@CSyD`0;o)9e1@6{BfoueD} z`^IO(EMlr)Q>vNaJH{|h<7QDeaMFeUu5D__@L^5Pn>>fcf0+0-Y&ooMAVl9)C99>? z>_ev&kgMD-Nq0wYr+vW3e-r_z*?#X+AK8>eVgF*d<;9@{iB;O)F+mnX${{Yy)W;VD zr|@TLQy4lvx*AN8Z5RaH3iCD%sBnE)Y@q1rg@4<3-xCuFm2MpX;w z1`R1RK)BRAia&-*F^^TA_2VkIJU7fL?MCM=#$KdYAmL`Fq*|tI#TY+Q`~FG{Gso#S z(ht<9YhRbG5-qPP%jd6RJNPYRvo!x4bzVF3Z|zleL;EBV)c|D>4qDv%PoDUX&0+oF zguZhI_!oe(nUW^pV<^PxBxM=>p<~7>9m+1{(Sr|O;SrBY=a_#X%J?TupP8J8Rn2o+w%%99ZmB@uLi@^*j!0JEQPz&bi}iy5zx zJUTV&P(H8ppp3*Tl1kA-v)5VJ)myF#X#&;rEI9u z!^y){TmD!K-9p5`cyGBsudpn4BxYl#454{KzYb)WcI^*b8Gc+{ea^wDO4Ez}FY=V! zbos{vRdhKGi^km?B3mD>3DyqId5Xx5$73tLUy>9Iib}NeDv2ByRGsx&xm}>2zKlYV z5*U2i`0RYl)eSLK_P(}t%26@`X;fh+3ZYVRYZKthFw~v+Oy!;{m?wggA_p-q85yo$}Vp z_8N04mDLjb#Pp(NYV&vA@emGf`a{y!@(U%S2Ll78*za5s;KxJ>>y1LHUua$bg|nq7 zJ+<&$^EH32mv?Qt2%1u|b1?qGs95S9~ELL}Z=Q3j<6az5* zF>=s9l^JCp!2v0y9Rsy*vDs?ggoah&qnK)l4g+4HNUTx_tx3$bw)QG(`pFw>YSMjp zRXcL2N5*({Dq{R1)_r@Ypm@C7+IBALcKp8D=T3p4Wt)vPBY9YP0({ zu)1R-wy7_0(%|anYih4c{@$u4Cz8LNaZLbc=Xs!d=qABbpoqbgEfjbF3mN;j;B*72 zyaf|-MdSQvFN!kk25OF*3M>=K>_57b4tw}){Jssi7BwE=@q#xbQ*SFJvKFx-b**5^ zaoD1zK+TQ67ej+Wt-k8gFy4Gyr(*i6+LXt49lPSfgYO}>*R<5?GW)CeS&}54dMHMG z+jRtQ^2+WA^^Fm)Wj|S1scH(ao=MWMwCZJJVY(jDWFk@?Hfd|7U|?}4R^ZGgYTvFh zin?SuSjPX#NYp14psmQdMPuFSq*LgL+y%l2L~8_~J_3m7%mp@&1xlT|Z5*1^toQ(flKn$q9r_IdGr;cI_z!R={&<*ZKN?URu?G82@`{@Xn>qGtMP zc_n#gYQJo6(aqL7yz*MXs@sKI+nRI_zp2jC4rP(qeMx#LaY#eb$nTK@hW=_p#Ol}S zF+U@Pxie_BG2q75b`|D6X-Fh&;SA@`WHcFrVF7p|I*EJ-^bW}SamwAWW))*)FTf%k z13(;6f;*LDyEvRZYjDpH$UFFKv_i_1Myrr=mn!A{4VU%AKQVfi^7!&I`kvuXvyZV6 zQx#f&dz<}ND2-~%C%iHwqteH=u~TRLh-#ZJ_-zuE>Ck&HmodS9-JLLJi6-_!*E?le zQaVB>t&$c-FX>xQ-GQa_Uj^R~vp9#+DiPbLR?$r0A?O;hnQ;^&F3wm?T3(*BK>A6C zSiS>z8Lgsj;3Ei-hXqO5{L2%E8{pNT3hj1Wy|D^KuN+g(2+=qSu>P3?0Xr8C6reg7 zKu*U8gc0K)q;~F{8l+EaJ&}4)l6Qe}P)dwr z(uBU|D|E<*v3pSAlz-X>n3hu{A~KR1fDiTbi*u{@^<+NyFkEc5J@MrV47UStCB}|D zm4`C*QQMZ7S11%wW0XJ3gR2BsH6X~uJFfsHBJ9i8K*@R< zG0@;=7qAj~8__?bSe)YDHPUzJ(HLiZfR(tR_RsTSk=aLEL#oy({@(hU-P+`4{ds5k zT0=g~nxMOKDO?j7RjL+i(pLT3OWm~jxTIoW-$`rD8BA3v7hk}oj?o>3hBrXACS`!0g-~yfkZqE8yGGoysYP4n1lqj z@D*${uWWtjw1J#4Utiy9X3|9zcZ>0MP60!82EI} zSxb;TjCcKY>)+0&>zY>9cXT;EC*v#8H=TU)>f1N_sIcV5lc>3Y93H-BNKvJ6SxwXN zA>V--b0kr=ps0Xt7+)S=!z$01S6VpcAc}N|V>Lu3yiy59g`t^*ImFNbJ3CQI_MB?o zmt8OR(Z1;~G1%<6dz@|)Z4iY6_)KN`l4M}y=Dd*oV)m7_qtBe>wH4Yn24w#1YMe41 zJ890#{Vqfa+PXgLzH5=QuM^Ty4mzC?ZBUa??_^gC4D;PZxjI)^7q90xvBBK1-euuw zPfAwu*!Ym0>Nc+A$usYz<~znclp4;ZK4qHvSnD<2^3L5YH8`?7YvWw)=BAd2jx19& z8vi{Jn?&OkX@obreiofj-kEy?1D8Mt+eO*FTn23Da7N>@Atf%<7H_Z+flYoU6i>I~ zZru)fSz@B>FEQe^e-0AQQc9p{AQ9pi(nS@wA>gxL2`5^3p70)9%)GfDM1$)@(l70M)>{1Ged zY?ZH4#ihmAXW4J5!OY+@{t;VqgRALUAwM*K5l7t4eU*tV^Gv$Ckv+Bbx84Z1S#W3k zm5ykA+EVep>7eS5U!3dbLW%v zHk$=|=xV#(?Xlj;$NI6UrRM&B*8~jAm)Wl>`C6{r%^kS|wk)_kVK*E?iI1KJf)?EK zC=ah`2>}_$o`CAkuf`g;CbDF1v7}r{2302)Q3=QiJHE`NTlq9S0~c5=%!st)07r|n z4PAkGXUVq1y2bMGk#jx=0;;Yi32Zs+nXWP-pHa2$<30Twv8=;$GkEEj3gCACIc^e} zvRb?;W0+$`KPsHl=GubXnzVk#3^$3uzO2@h^2y87WD3s(f?@soRTLNj$P846Za=@U zz%>Pj2M`xPG-T5=Y>=SIxwsq@L=s-{C*WuqSAfOu${5z!0RUPujmlR)bahoud!bN4 zHEb-V4p9ep%GYsozm)aeDiO3<<9YjIcVS{?Mj(V0 zzI9i=zu0%o#RQNvcy70h&PIWxka8aVfF`pg-GNZ~k)yX_6{&nJlho{Q7z_AGigo7P z8ofNAnbC7Gaawr&Z2u!c&$m+L7evY#hH46>lTV3l614O`!>CphMSZ+?baIJ%*T#s34(5$bHzwL~-sUH_=7lr~$74E1U=SWrQ|VxGDu%dh-GkPteH-bTEQny zQ`5qezGNTb8z3eI-G8Fc9b1bNLe2(1Z*<=qrBhDyzuGyFx2mb>y2S%EsfNcOdNf2Z zU-b6zhkp_}RJ7wX1+o5Mqb)9OL{mO|L7w6lNCC)+x@b9(3M@GA1H5r`@TzIbV(gWZ zFO_+91Xy90L2H#Wf<&}xP|W^!+){?7nv(fucW>Euy}f)7|Az`arZM}{8kR&V*1WCJ z#_JAn$`nZ?r?f;WkI%YT^;>UJyth?r9h=E+gZ|kLs(~{%V%M@5{Ms~5FI8ut=-TMt z)AWqO-p>FNe9;m5@2z$_3#^fMjsv;s(qP$6?a6=@4;Fs`>drN4^8yTntpV){u0#;N zxD0PM(*+D7T;K<>6oSZ)*2#h^hwf%!W#Opig@vavhbwbTr}PHq|rr>-K#t1Pu%}kwWbjHMdM17vT-cVUKoX1 zMqST5JC5nR=>CypxHc(BWZE{*n5GvI1VBRvUPyqg#|eon0-SD@mHU8Dk$zG~ryqs^ z2KbTGWp8A*jbIqO3SIzy)$i?wJf-mrhH;y&J%U58*qW>~K8*PAkB2)UY%iR4vAN7f zw0eRwuqwdU`WVw=d%?Q$T|q}hf|n>wrs7F=U^pT-Fs8Y|sUK>|VN&E8jww(y;cT_= zY_W%xt5sp1G(PhmWEvh$m0}=(o;@&jJ}D^Bc+_^gWtgU;Rx?0GI|eHjJUl)xna8A) z6`a0qmiy=R^$W#|g*`b>?_TV5 z^DcEatB~HPT`Q-Q(*M;yWx_L7Kr#Mjgs_rLX+EQ%&=qg$y%}X3hG{cYO-G-14Wep= zEf98FBDamVb%uF@=)zD0rWUXV?|;`PX30kbGZtPunQp8&)9ZgLI?a*;d<#iSfbNXA zE0Je__a_CrBmz8s1Qbm_4GGRF45-YbWGyfSZf?5L^5bD;`c!RUcIszi#nDSy;YYkm zii#R=JHe83Q^_ag_wV14E_&Hg-Wy}i{S$YXSA_DdNx8jGH~`|e+}vDcOooNclMM3( zF^01a8YQ?|;e}01PPPSag9{P-QWZR8SP1BBfto4v)?~JvK>>tz8O;WA9Dt1q;je@J z4{W6lU3F>b+^CF{kntnNXK^DvLyzLQ=56__W89yv(C3)(^L8AK*|hdtgl*mN`?7oj zUWIzIiT-yP_-HHAxjN0pe+1Ahm^gKc&wyI_t1TxFnKBvZTj^9ca z2L88}Be(Wtk66&hoa290*vxS>>)Pw}Thti0+?5g$)ZpPW(Nfm*-7cn}U==y z?;E9-=gvu=t~w@>fHe-S22HvPB(-Lbs1^8Tm}-p~PZb0w9Nt~M0z~ADj+->!H*TYz zwYow9foBIbc+9-r=CXDgad9u@7Hs+G}RtJQR#Lfv7 zrA`(IRqROt);{8qh9nLj9cK$rZNT#@As>PLmyQoc>xRcAlG9yz#yg@$W1Z4X5`C4< z_pVgje?ThASYNSEQBlSC^5Fg@YkfoCoviLS4lY-ULc6i zo>fQs%v*oFG`1H=zR#~yJ~i+tLwG=PU`XH&iURL(e;yib?gQ%Tu!Z~fKB)QZE>Y4G znJK3@O5H3Ovh91@BQ7;HMpcb*O2J!RyW@!!)Wdw9%$p9%o|IOKugTY9H0Qsh{maAQ z?JI#HAoofJpY3<=|8Ox^(pl2!$j#86>L{iPxtzV`i9aQsXmh@l)Xs#dguWOnT~fs5 zj2(!=8T3M#^E^Sw+D7;?8GpFMjo+^_9CRI>@=$q+qy$`U_(Ds=N(;hd44pJsc6%k( zP^Xdi4|yj$p{?_dUGeb8)y=hOU8DQ~bl+|0b|o1^=2o^p7Sn10&jNLiDjk~EsM;Lq zuFP0O)5?4^=sA*Fl(Xqu76P3GWVp7ay-$lUzDLOCQ{_(a1?wA`ZZNhm&Y%RDkw1n8` zM4aBPrPGylTEifjwKH&y53{QC${#Z|^VZB`y+-F|!)rc8-Szy&wU&J}_^5`vW_kdl zV$9|3UY<5e`O0*jrKQrA9CVdxbOZF;^XR0VQ%jF?y}1JH4(O>f&Kl&-{2tuy6FMMA z4j&i`klW!t5WdR|-{^XB@?g(Gkxwmp3LK&Hl}hu}fMD<&p-KgL*jLoE;Mi+y3K1K$ zNbp_Yc^!cyvJ#vGm{kA*$`2+)G&-O|w)^}(grSG9YSVKvYKoxl?I%GzyBt3dn~)D| z4152hXY9sN(%-^*vVwG%3?iU+3zgF>D9lhe0qUb{S>U%OTT&+H{lPQ^_lDP zoV?M4L5@F=o#eeZnR*_uFSGYJwVCI{e)LI?ihpq;q@MdvP8bSK5Vn}6(bJomV8#zR z6SKy>AzwW2`-v&lGCsl9s}Nuxg5xC^#;NC41c9?dc7LtqsalFh8NSi7Vld&3q5EV1$s5C*3fQiE`ekpbNz=5w8GgqXq{*&%qQm>(mp zSpn9aA@lh#AC-HC{p5H#TRg=M@_~qXfEalHZZIcdW&sp1{pc6(wv7-eEHSxANnk^`X|ENk~pe6G$p;CpWA2=;JrEuB) z5i(c2d-slhb*h~Ldt@y{HuzrTCc#qxL%+e?Q>vhG{>*dJ;J`lb7O50UM5}mvC6#g1 z>NQ?zMsyK^p9W6x4Zflr7x6D$rTJQ6V!d*2_MlaCGPH4|fl>>f&sLpB&XR88`t`Q)I04>G}d}Jt8DSI|o-iWF*)I zP!R$!CRsm#LiBMa(*b5yKu7{wt$T)6fVcJUt&?G3Xv;ZgokDpMxclxZme~VL_ZIz} zsIH{FxpT#m;y)I;D6HxyLUWkPm-BXflfA(ddTTaV%=j$e;@#08{?(h1seA%pifT8r*u!E9e~Ev1qVK z(V7!L=gEr~oN{%(z4M1esLSOPN?LwIR$7m_7LgziV8MWJ+$O3wfZjvMk0OQv<8R$w z{F4=5id+fvKeLo@48tklZ^=QdhY;f<6A!Mwlh`;IFH8OicGfXt<6aDt!4z;>5kWFp zCKdT%D4I}rBZCAuA^CC2N*fj%clD4=Y<107IK$DlxE6(vyg&=~gT%oR>Pg# z8W4Q|HUa9ZkM2X8y??}{0wxBwg7TIq&mQ?K`~?8gXX>aA!8Y&{Ay9KdyOhK!RzJ%?p*F$epPb?>rcjN z+O&~U5MMc>%vt;Ul`11=_gXvWy12RhmPscm{*pHnvaPuBK9GI*89mngw^K?3#HD%X z47f23JhzA?r=Y?Y`6E;E(_=lb4+0NG7wo&wlLK;;wh@)5;jD|7in-B^oqTc-vTb+w z>prttKK*@_!6cGq*=+)d5_@=h&?%RrL!J=!`5}xOEf3W?xj}<@ zyz3zJrF!lNum&e63HwVh_ugIC#m&P*hU+4S1jPXgR=mjbc&fMtiDg7-rkoi#Cz?cv z=fD<|KZn3T$-0&|gXcVdHXlIRP%wZ6(*Iyl;`74r1hKt$7&9|73<4$)KjD6l))M+% zz1_PU{SsE!tdHkE>IQemzX4wd)OU*Ew*#_6d5VB7VtK;5!)Kzi6ZHWGkpMvm5tCSm zMQeaOL*L; zd{cSd_bCrwbgRTQ4oVZB#9W5E>df7#pdCtUE9o2~QP~Rr&^qF3x7_Ml95dn#xbL;X zH@5azMrYr}$DdQw#n`Q_toY^PNjVJV8j44v(m^YQ(-9BD?%8o(&Zed&;!u&h>dR|} z{RiMw9sVc?DZp_nEe~Z|e494o(sI4|{^w{+#B^52Bd3_>eIq*iyOFPgu8yoW5-td< z9GE=FWqy+i7@ZqPE?v)~o1a5(j)kBBM*O;#G+Z9fOQyu%4qq5gc6uT|_27Nx5C7Iv zfBIH#CGV?4?x^a?!Gc;0s1e|D!~m5;JC1Crf}Ai*4jc|RL*+1?8~T32M3b}@2zx<0 zdU}K#Ai#vvVfi-5DpG3k+syqbAWWvD?mmMK?PZ6C{@&NuPj6Vi82X`4XX&a z`yEhqxQ4*Rjz92jstBKaw-~P}Xy*OfmMCnBx<3PgCT*F1`y4vvn<8$+#N z;p4+|8Fe|Vk8p}uU$`Jci3qN4&DG#?{I;&f#S~ruoFUMSKQvtBG4;X&&we&Ty(Vra`znez}t^u*c(Olp%LL|L5kmN(Vi{LcuS44JYwSa`j(F#X@ ztur9}Ok{eEOyRhI1r#)~QFgPvtnRm-GjE(-zM+@H(#NcMl#p?ngA6W7fBm;yQ=goR zV82?bT%mdtL>=UJxH7SvQH#vaww0d5i3^?_8uery>m(uU3ao!16rf(YHgA>!4FX#l z&^6pNL^uRp!#bO|_aiP`wU#)x0Gkq+96bx_J(Q?bCO6{?9|SyuFcXdh02QOIcpf0^ zfkZ=n_#Z_gv~E=!1|uA03AKm^k~2bUm1tL$>3C||i>Ki+RkR2(7yg~=u&0hweBBxw z>FXA|2Q}d#1!98?wt7y++V#-S!HNvv9;N?@v&E!Bz-K>d<{pR`3|u4*4&tZPWTCE= zy|Gq^2cV_eE7;Mn@rYXs+lp*?G-CjONRUC_k)9pelZF%1E#GQeavt@yuP52E!8%!N zAs_l|V<}whYg+T@cZC`Z9EsVSW!jc{%3Np9E`XNC1yf$BaPgS*fL|-Gg4h^GAEeo- zAy4)A-BE5|>Y3vvR(n7+@=~AsI2gX{I%rs%(}m>xoVF2P-iHy(Jcij<7SfG|!>yaivWy!;iE&%f41)*?8W6nD6x zh=v*c145=rOF3A-9xdTM>FWwR>(d}RL(DQ>66!=^CK#Cl-z>FGlR`z+yzAy#PWIkd zIV9EsaU{0XherNgrEzkrZ-%_kQ*Ff|I^m{J*LbAg6rB&Y2@q6}X;dsG=jH3ua%c<& z#jr{|VTrIsYAq=hU|^Xfz!N#tK7S^$PFNeLGx6b|&c~$*R}1MNE5c z#wBv#Wzoinu2HA&7X8ajPIYinUi*k_Zc+w*9|m*KSoa`AETI7v!ZEl$Nysax9nygT zNpfCV^fJ3Nx)a+M6rQk<-n+%S)?DnFtwWZpUE8(yVi#iN;wB*i9o!T+HH?v@W-Rtc z?}3ev%r-K>3N#<|ekd#4(8*(mqcQ?;?*G8vCBgT~T~ytl&;fzsAW_PxOTSZ5?D&1K zZF50kK{#v(mkw<&UN`?{8MeSv!C8YR0tf&A{=|6SK72sJJh7GIJVZMMVQB9GrCAoh zl`|zgT7EGl`c$HUvpW`dmdX5_C4Tt@9cIG ztprGD+yN(_ghJG~W))Cms1qT!$L-cK4CzaO=kIe)+w#E>+1q27A`uM7yrTJDINjru ziuWtlU4lrWI=Eefk zUa6XyszNdJA8Mgcp-jAc!n%O+9{(JojWvx<8A2lH@$e0uot%IxmWzK$iabCcV0rX` z?J>`$rG}+-V!3GSCMUZ@(yRg zy%&ZXJ2lG;RiE51#El_$IL<-=lo0eC6rS5j2BLg2-_|V3;DjN7PwOM^YF+OiY^WuV znVW-Tz*ZvwE`b)vi$qk#Cm;t|@M_ii%-0eP@}oA0Mh0Zl_7IMU!jCnOq;7NR$MIM5O5c?d`A)HzMjyyx2aL>}>GzOAR`k=|14*)9! zUoi~AI$6u+bo>USkTg8@>roc8$#z*bd!l~X)#DjcU0to5$lTVd>oaRW_=Vn^-%&Mb zX8IM0gA0MOX?~$+X)n(7HA0Dt^G!=PNlF|sNe$GjCE>_;@Q`^GO!fgEQQ1;w$s*^e z*!t-*d)PlT-IFgtBW#ayGRW@RO6PK;P-dAqy2du4}F zpm6nVKtyQuybYibNrEDoxrZ=q9v)_X-gk*$?a=igAB31bq4oxZW*omiQy&6U z)Y0&)uH_fJ)uW+ZNQJx@P|r>b+nO~8xu!k#BB7t_W_@#3yzjuBlHLo{!ko8c z9%3su$eBV@hC;`8pv`5u_XY_;)$D?;gAx?Ihm%CBT->JiNd8Z^iNF`Cw%q!r zkI+M4N|lq$f!l{kE0CI6>(VXEZwwTBSwxPrj)pGj!M(&)J=3UzRRYuj@iw0(#WEfS zSKU|nH$#&|3xUKxbRYd|Q`nQ!O&%aS99sYBY*vv=#b%Q62q%^>eNlzIfIR>$?>G|1 zqct<(bQI3d5~4<(D#hr3@7_J$MZWnxhN5v~x8O|xR|By}mKsodY|>`CXXrJFpAHg- zA$O9Fij9Hsk($_epBr!B$U&9{6pVP+Bx)OfFEAjQn7l|8|sHxZsdlX;-E#D4E>BCBL3MnuvSk8HgqsbqEPf#Wn=!m8M6R^ds=e zK}2HU{?-t|m0vDbk?!2yeYYn2=H))EBZ6DE<>jL3TW(`m@IU~w@YOYiS6cx>F||nb zbvh}|bt?aU&0lz>FK54I6A21hNJKZFjX=oC3YzP=Xued_C^imlb~~|{@nN?e&Ed_& z+<=%@HUJ30mJ#6v6pgrpP*ajS&)j?n!;XPT!FBANzVhafJAQ$jZnz9_zv4-%?ZerJ z|3>VG-LoqrFVM_EiHxmC7Di!Vp+$0K;ZyWC*uH>hDOy?qHx%!OMxrJLLDe?0N@^1- z1xPTkeud=V69)f^A1CBAv(5RZOnJLZV_EgXoSr_dL7ex%yYd~*BVYzSDcD`yFlJs; zNAN!|EEZ>TL13J}2LgW{!M-UbCI-TiA~#XF`xOA=`3asSDcn!MO!4Fa1LKUqGStd$ z@_3>fq26G%=F{dKaSel?h-PB z_qs}#-fVRIG$_YJVkikif&+@#u>%!8c0268bwiV|h)Us#%ri#q1ff3lN4J5sxc*3k z3i|HypKdgL6+RU~yB{rneKbR2TyT}@YvQ7y{^&W`c&qOiY^lI1pkqP`0Fv=0)@d3Z zuDIc`qFmap=iS3$QC8*9_ImA3{K&y`zLM>uuCP6PA~Pspg&ECDwZeFQA9HWCKL?`Qf{|lpIf7@|=okZna z@VM2TZb)w1^drtk=Z(?Mm5NHvqYmx)y>I}&8 zX31Cfh1}cc+mAg6*xfWqReq5EWc{l`7;N!y;XFrEf%XB*AMacu0pWyzIs8KyU9yWm zPqvyDywSxckG0jBZELe_;n;!2#S^n488(8MwD_VgM7W zL&%s^t_Gef4z?DFt-D8ae9*$kn%>-}@#GH5E`Y62a!h?af&~JFCkj>~ zEk~o8y70uOX0U-oKkFh+o97gqAOr3n>4TrL{)#K(DyfNWkee^gHQub))Hlh!*hoLL zIe3+;%g0KI@xGq>PBBe=plyVA1~r*|p^ED5Yd zhDHz0ZJjOA1>gZqs~i)WJc^Csg=)N8ECq7?2>+$1R4KLAG7S?5wRZY4FnHJB>lnV^ z2CV~W`Gf>Y94w`9w{ zqh7k=o6NFilR4h_DUOci%I$giaNIkfHvQMIjBq|D#8!P%cLyu_3uhPTYx@IAv%d1( z9L&jgIesXF+i77Nb%ZkTORT+2={()Q3vku~D6cKeaw0>QUM?OkY=q&9v z)eC0*Fp0CsuIgBB(OSO5zfj+)S|YXs%9gIQ0CcnnVHo%a}mxNpaS{; z;6W7?s=YKvufM}(LS}@Zsw40z@E^PURy&xNp(Y~N%gB`9&HiQdUXU{!{0QoLbZGb< zC<3sz@mO(nBiRRAwa`Rj=ER_RaQAb|Haod1`*yy|Hp&JPn+xBW0IMZRM|iLRlEV`S zf#o+xLD!?%M{w%!8v4Y4zN*U>6?b>|g`<;0plOljJQKr$rOuq`;kGlz_C{kOyIhU+ zygF(2VGi>t54U;EC?)N0n{$dRSI#{>zWL21#nI;%X5@l|AHACi5yy(y+|uOz=2`?au72>b#I5ZiS%uFk{W^1F00BFr`a!jYQUHD~M%V{J{q|1Y{7d+#50FTBqUq8pbR3LTVcSP_6P5$VtR zNhI5P+Sz%XZqdi!NH4eRPU|Xa3u7ur^JD!0ig`NYYKjCcv>l%f$T-{zf5_Ue=nr8f_M>Oq z8J(UJ4vY}x1^NR*szOfLmHuHi^>e3^_@P;u=BcOly?ve^$9L<`xhHLs<6>juUVZaw zJe`lZX-{9zwU%GP-&_}E(kGn6Q-1xO$P@4Rg z``C4%rASG#qA|H5=Vjl_W!>Yek=ED`ri7r{pR<$}MBwm5NPi0DFf5#m48wdaC|I%GHvVTO-AX+ z)=z-Z>G{_IS^OWmb8mBq_I?U50nlSC+PA8#1dnesOdi6ly$2+OwP$)cKtYPQGuqoN zVEhL*kFhYM#Vte$4uk8xwx02cO^YY!tIVIuxp%s@?!14a@Sk_#(IVk zI(%wQMWuH4@7%nBhDGI<1H5O=r=0+_z*Gl%6bcWxpr19&OkeIh9c?ID4Jfhd*?I#Y6gBsZpHS>swq(EA%_OI|JgR$2;1fCPyjBve%D@(?my8*-Pk zTScE8AAJ{e(bCr#+|9Lp#YW7KQwzla%6;5nFZnyoWE}Dvgd0pE6z50zY9913UmdKfx7L4_XdE*fX$;lX(sR#$vBn!h8n zPw>&8=~zzOz&at4p-HqC=y?EkpgAWNEXf1>(Peudm^9j%+<*UWcHRBF+a3Ws@{fr5 z*Y7eKS+lF|1p47`9Z!hN7_9eo0AX;g`wd>sdePfD1NI+NeFRH_HN*Em)#m@shhlj^ z;lph*1-E%G?eCfaxL^0Ax;C20ZmjDTUY9)u#08P^d&xdA(FWYk?S3`|LPiIT4ea=t z+Q6)SF2K;OOEG}-A=4c#%cKX|ep^PeKi@sRxCt2oZ?!Uu(vp zmRrP!-TU&UsYrv_`u@(M(_5{&+M8ZUl_{e#bG5jk7gPf$gH1I{&?V*(7dap&71 zW*(+?fMP;BF?iM!LLuNjDD~HD0qX5^CP#?v6~6BwPrJD}OYe@o#DgZ2lzt^|9)VLF z?p|n{@RB^;w+ez9WNsm7Fc2;aC=HM_LsNtdVDM#X!=@Sw-?;F@R_rO#%E;#XUQ`xw zl5?*$KqO@d!g;Zf!~B!^!+Q&VQ=M5SLHs+5Vs{PB;`lWG+E$ovkF0@ge9-?1hFF4y zf!BnOZ|qV`VEkiP@+}0Ukul;{>+XHOS{iNeOYqEonKum#=HHc{zI&1Ww0K%CRrEYu zoOv2Qf{6ER@On+_m-f!DSG_ufjuE^Uz~c`0AzfZpPeUqe z4V*x3C1k+GsAbYRUAsw7Gtq=4_~E-=@Z{s^iv#ory-p!^+EH4kn?IqNs-`mr3lvZ3 zH=L7HA>LQM6_8JfPMFuM@xGjAPtYa!GGevj0AA zpO`>J%RohgYq~c2+Udei;?uQ{GiC(f9X6aHG}YXqaCo>ODy_0=N10BIQTEX!)7L!r zN=&mbT}wnYA2+d(K0~aP(#kVGj3)h8%;6z%P~#HPOvTnb)HR_0<%jO7Zw55}&^l9G z`%PJ79PZ8Tts5O)aD2N=1gIdCkC4)hB=0nAwF<%lht})+(f>Qn3LM$?Q+UIo4q^#;24Ntq9ZvEyH~rWPn%E3wmCMCUoUbGc7gh8G^rcMF z6N?K63mKMjTkrTh+Px%^KH+;i0OY3@z@a1b1;A>^tqKnsI<4QpAR-3^u?s?I0pkuW zG1wVC3z+_QXe0YP<0LrA+h5*{n6QpOcx#PU+ewsR%_)VD=aQ!ZbQn~DaMM8Yf_6J# z)<9T5!2%g|jImNIG-pl?s=9=}>bua#*zB-o(!MpiR*m8!SD2SfAxUgpNC z4Su~nnqtTOC;*$#TD8OF4tFq=FEI2H_!Y#_0L+Zd6M&z9mZs`C{OewUk0|-?CnUXn z_5@%_ZU&$U03aD80C2d2?%!JY#S^#RLG=hY5B~;$-iYP~N-JRQVT&;N{2~CLdTwsc z_&ksIpxamGjLP5EWyt+k;!w4hdEr?(?^NwM=H%LJY% z{lQO{wC$I+3Qn$i!U#YU4lfuEQY470gv9STS3ozV{gw~=#=I|dJj${0>boRx{YJ#i zXr=E*6*kwp?cC3Jds}&yL|DFkwj5!($G>~Wx=qpWQ7s4=rv)xuuDhbiukifY0~rNo zw~!botj7fFm18I4zo#q;eDm(id`L&J=r_90&=AE2w-ovvsK!!dmgyaQs{Hb8(HXyU6qj74X>kvuYnh3Oo5|a; z0#Of>yQKso##-ew>@KI2Rb%MPqgY6p-tIPmr4_En2VnX2iu&!S^vi9St{5Xw{8sH-qGWOOleHo`F!M zwq%J?{MM#}5OOS1S(P8wNdfrrt$bYXI{)ZKHYBn_$f_q>LG)Rkpc(uSVAVDJ5q7Zin1Qo=* zR2OvtlK{(In(@w~8gzm>>=DF>4tt<4Lu$4ojuV8ua7w`}5TMya=^XpC|i0+zuExazc;vq|I8TtqQ(KzlOenTva5CN{#xr;J3V7 zhFTU;8qVcrfHk%m+KftjQ2U2Xq6#ly83vXRRW#JPh{Xg18PE+v;%yV!C(p=FZ`Ky9N%{bm4Y44FGoAICZuaxxE_h+zcf@b ziJ47p9@zq7v2U~C-;mP~th2KJ)kUWsjxQSKX&^(?Fbw}gNd-1C&$(7AgQav;0v;VIS`L{O zi;2N9%<3=xsOq?P)^AH+WAF9%Cq1P_Oi)ISjTtT)J67oW>@By$^9LMaayc0Q2|)jd z1MX|(A7>*QhqVNUG5i*E14tg=!srEt5Jc_nv(mvS;k^+B3*iW&-9_FW5L9_*{BZh{ ze5<=KycYTK@b@8yBz+c^8}!W(yZQE(0f#Yf&PwJZ7?O=lKFk07K^HM+ln(;-4{PcO zeDTkpHQ{gl3tNE(3RW;FQQ)Y>PYfCSC3TeQ|L!|!@}MO0Ms3UujxY-W(;Vv0ch_?Q z%w>i04U1<3G@)SM+DdLTem6JA4ZS7^oQLLXB86OpFULT(p_wTC^4_)!z^d;Qdle|c z#~B59#I2&9Yw%3(J3+|7l3wdc(j00iv>`bb)-l)_XLla|_L5}9XM$f1GEDL`I=^BoSdA|8h_9ffdOLKA1pplG%7>G4>P~PIsskMs*hO?HK>^2zW#=Z zah3RM;W*2nX`CbI3g6kf=$84HX@__Frk-6Y<%`6`Adz_d{K$TO(qk#`R=MbMS5#WJ zK>f|D)MGvov*Iyk0O%l^sGaqB(om?*$>8EdlY-*2=A~Yq#=jAioPu|g3gM}O4j*`C zSougqD^M~cb~8&*X(Pr6q$7jlL!>+a%OmPM+pWV0%UsC zWZpZ1R33(RhX9PPfk;U>`62*wLIxGP;6&S|jvquEU;T5sN|VF4yT966Uz#Ce;;zoc z8=((!91vh-RkT&wXL3P~EB*~Kl@Sh9NTAjin5}sgH(zVL9~V&4qV~2d1folj#kOFrH5h*}eUGGrswuxTE%1Qgan6v+hfqOH<~N^KWK3bW44E8Cp_~oDVS(Ah(+AL&dds zzptkJ^97!V5w|&BqOIW&q_h=uK7T_kXcAL%Ta7!|9ydGsB;{Q~ot5*s5&o5wTfUE) zwFwKWp5h7RIHGhD6WX6qxAyY|*8ZM$3P}c_0D|2Kr4ED`1MAu2Au$8wuzsCa0^rb- znBoOn+UVdVkwK0_{x?w~6c?%5MUoC=sd#jPam#{nyDP6YlqC<9&2;`cTrM7i z!o}2(9qpU3Zr)X|BJ+fL*KmDI3EjJ**WgHa|5x+kQ`+^Xkvo0a@AE6#+`hVWiO0m9 z%8A2yCZKj+p(58vwk=t+ZOwLTXFb|FLw&1~(<#*w zBOKg`oPVBzBO@!SVVe5*WF|_JI+erVQCy}v)}VDdLZvOTrJ%!&x|R1^Di`P55npr{ zuI{BH&2C$MqToi(&{@s5@1>=r%I}= zeUwSY;@a_O;iY1&M#l4AvYJ6Els5e7x>6&=Dt5PM+W2e%eHo9k77$OhW!^V*A$uF z1NHFxc|2ErUWN)uOWcCLrne!xpDNAcy%$0UZ%h+M4pbOd@g+~~@}m_0`XnM0ja&S= z-_gB6nUP_W$#ACwdF;82KMu7EnDU^807-T`wzuYt2zDFJP?g+3dmQxK$dKR~{R1u2 zJ8Ec}M?V&fg~gw1e_PO8@=Z8)ue8tH)OK*Ftb37f0OP&DO6#lkp(pWBpcik)R2rUW znkuVS5S{s5-#cQNI?iF-w7V_;%fkgDtX^v+ZS0bHNHuKRHWM)dwm+|{>1i}^+ciT} zfp!bod$XgZkV7~PAEI0ku-*yi!VJ{LN{Wp6aPFqB=25yQ6vz{L5 zn+lB{>fhs{K2_Bk)eGp=a&7qCe(}rvK}~_;S4;f%~^zf9Lx@&{;S!a7r0w z_-@b{`E9d9>B5z>)gSBEf~W-PqeK4Bdb^ISH;!6aMuFZ7{NiE+a5cic0%$k_;5cC< zIE7WmBr~o^^kt3M0q6#N+c@gRql$S=0hNiKEUqTYING>4l+IzQxhOr7O$H=Y8;U2P zQ!xNLSRBCoY9o5|jU1}8oAQQ?_k zfH{H-&II+*p$ZfTuma0Q*hsI#?Xh*{a6;-=2WJKhh6N;?nfR#R&Oip_D+UOKKpX1l zw|efN_;CKv6x8qi)-tFNpRI{dXjbRS|5W+ELRbTq^}4g)oq9V(86qOoS7{H84#Z+W zkb#Trih%Qdnxw9l+M%;0T{6{N5i7Xm$fmMUqQeULFYUtXgt2XC zR4UceGSYEV1{n^%+M=hkjnH+AJ5(8Ap?cqZHdo4|mL(#ncv{hA!hMrfB@JMx$x5_u(2uoUv za-b$(RhqL-$W|Sma=g>Pw-I`0Jx%F#0gP!aD1bP9I#Qw_ljO*zRwcaMQPwWG4FuUy zsWa?zxnE{C-cd>2-fXVXS%p1kTex};WHzALy$X{LMCl2vigx%o_n?j1`+h?T-+V?2 z$*6!Np!zNRDd@dBK|j6XW{G2juMN4jF#hbI0s2r&P@Y2-DsgmDYCrd|1!QPY7ee6I z;;4Bah^-X3)3129LDP-Qhz1=Yr)oNyfeaK-ZJWMG*@xvG!T+^HW{@SK#PR-YWTeG4 zy*Bff7B<>TagkkqdIVdV^ECZi3v5*E_BcQLkP>wg$Sg`wDAz4?@mkgs3$yS0Yxb_814q=?V5Y5>DdLv@cPg`&f=T<&+&LRJMBGN5&5d~OnD z0&5cj%z;u*blg z54ssRDFkIZ-d9uq_fmr{Qc*-5zwfd*rnFYdH=l#Kf9GT~ZL6C3Vy}GCj5%LxHrhum zrt}xA@=_XucREa|KSOD2^oTswBP5T7V~ zSE?4C7CXz+R;9?=nA;1tO_^m@*O^Mci~RCfxs$qG9m{Yw*gS_Co-oqUy%7*JeESUy z7l^8$zFq~2MF1&=+yqBC|6KIsV-hVUdo(VO;x5LRK}*(#0-U6NX>!*u-6i!bapYuj zzjX^NTDU~uBm!9^U;;rV@1e1S3Vrh1w8F5BkXB9|NV22+IwCN1sf=KfVnoAWG6+qdc5t&t4!ta<1-}qBHjw#8Y z{UU3)@-Y#t@W+7M{03n$01$wtyJ#LV6+!9?*9uGkz%8sGr~)*~gM))Bn`EKC&uE}^ zk@03wHWCuVOu~H;sU88463BW%VGlhzY+}eXLpDr6{I7e$I%^K4#Wel`Z$6dHmZCzt z^HRf~rnpFU9qDE0rnO+Ol2WB<=9Szu(65v&!OTy#)-QT80?-Jo7PTy*7@2d06A&zv zuo|F#xO~}Lg+YL%Y2+YQ4vB>Y0UG?soqfN>cLJ5{xFy8IwX}&SQwLO~EUc_f;3`)G z+-X~_-*5f@nD z;}+&IJ9kcwjDO-3Y4jAOrwCzzbD`1rVO0gVyp}ds@xBmJ3Kk!*O#-Ed1WMP|{;TPj z&RjJgC1i7$f=UIEfPnG=xqaZ!0c6*)ip!8UM;i=_5{!U0Z6WRc!2J4FJ1_}w+4u^m z>b9l-wR5+_jQ42b!VOYT@kpW&l(>L{0B{KJ0k-~DeTG$vZXy!Y2K~Bq;j*t3ZNIRI z0P)dy^&pd*pwL94rZV-l$OR)S>tXSQwu_qw1}V|1pWnl*iHr)X~)V;6aQRF%x^v6@g|DQ zsejT1=0fG{NGx1(6z^+G;y6m@k!DrkGvXtuT>hxbnW&-7V#Q8>!5QjUrWiP;x zojHn0Pyv9X3S5La>fC)8q7Jm*Q*Lq3vaoQdpx~(?iC(1F?Qq~Ng;T>5!ZY9#_DrIH z5P%vMNQ2RmdQjGHY}}JP3At@p2F_Rm0NLOWKx7wCHNu(69AgGKhX`hszq$Jix=RBn zv0zjrKy{J_Ta%;m#qofrf;PP zMUd28m?Z&a4IG`2jsRyDP$yfohj^o3pesPAN{iM$_DTCz0chC6(>54`=?cEK zDmYZ&BY+hJ5EsY<{L}t8qJMX*r#vi*TDyf(Yr+GWjU^b5fkr0X=E-!C<+WnyhfCoIEJzTOtZ*gpHSEGwj?`@+bgwhC zGBIJHEsQjqu3fuQ;WkPQH&_hzWd|8f$x;*kONuJ)7N!?oFIB(mz^tHRBd@}Af z?pCP7fN{W80+NU9P54RrM_iFWCYYYMy&J&%e%1Pc&n~6x^1Vmvg-U2K0MMv-6G%XU z)7;!V$}Iu&JPWnD{-FVPE(iec)ut5-5+8*Stiikk77qX{L1GSC{jO6{7UtKqXiOf}U_?T((9Dnh^z-PyBtX)pqk&9hvcZNk zE9o!o`!O-Qzvsz;9pA?glNkmFy{ZDr3@Sc26rt1Vx1Q=6sq6vBA9+JSHO;wVKtqV5 z3Yn-WS+?KIx{2kpi2El+JFP;{+el5R-uiONx6>VjkVyjMa1*-w`1i;*)&A(zx?C;> zTHKwe;1s*i|I<1CMk+X{qJ%k31T1q*H5tyubDWK$4);mjlM*9Rv<2|hIntkpqZO+J z1-wxpeuexg#xq~tI_Fk|MC3iVZ(4=aQs3UNiB^Zb6it1;O~**{Wx*-DIN7v%c-{p8yM-dyiW zBUmlPM;@@onA&x{(C2}W_T(D^gwhCh4j^@R{N#7JB(%P7S1>rUdEa*;vAP*7S{IX!uVwgT?{TtovZMcZWe#!FsjWY ztfR%0^jUb6{Q8KDM1*=$)+8o;k|Ow{7AtiYrSi~yEs`u|u?`mw&0+PrOO2=|W{NVt zE`_9iLbWI=D^oX)PP$LL*(MZG{_ns3QX=PnV2!!(_25LpXio%;7!ta(mU#>|NUa$_mUL%~SitaW!_mu4@dxp&|o>N0A zJE`0oq`{S|0nRREVqhu{U*$Ce*j{hw?tpV=4nbk|^@(w{t|8 z#ajrG93>+=12zA|ukR1HYiM*i@46;>7s!bDO>(zgFxROU3Q7KClYZ(gn<-Yz_;eM9se$jsd7s zUQ`w(%n%Kltm*Gt@#qL`13k0WN=O(AZ?iJ}S<+TvuaH0ju1bH5`Qf+wApQ`g{HFsW z7s#&CUPY7xRxUFfnaLAw1~bZuiwkwwA6~JhaWt*R(&P$WioRvj3|y5bPoQ;GI&PMx zEX~#gARt$S+C!P*?0K@xumOZ7T173$yiIgr|5FPzJw;xH5DAG&?^NPCni!xcbQEzw z_L1}lQyadxwo?1}K|+&v6a5s;$fedh+WO@h?=3YYa>A&Be6>y4N`=_uczw40qKK7K>`D!E*X4T0QE=kjLPYi4Lf z{7!c|6b@|wDCwmig||&n(1bHH047Rz!iDJf~{L z$8&3O?-NgEhm!oarUHJwU`F=7IMr-v)Bu`fwLq)ztgg;hVn&!vOwZ*V8j*nkhKy7+ zeJmYWNR-_5HXA!xlq}aVEz`|xq0iZ4sc`EEUzAeK(Q0=4nq7TfsI#TIC~!%6!c&rS zfvikKL}J`GW>7r#_?Tk=Em~XD74hl6TmTJxvm9HZq(TTzFQEdg2Y)m(q_>lWe-oHeAV= zHuK=#po@u_&BG<he5&ORsx04eIjxT_#~<*Y*3%khD_|!ug1S z4eprvsl`n@(&xQ+?v-~@q6gRh-ejR6$bytFvSlT@91|%NGB9xa%K{mwGVF2TyO^_a z3F;mHxczgT75}P$cw{6ZPMd^TY4xF5*2kL!H($j*kTb#2$HPsx6G)J|Ahs}YTdtYq z%SWsAo{#pCHCsJDLv<>hd`9X&!X5O@wD96OXH`K93ZIKNP|Ql)Z^JKBOeeV(#i z2ml+n+3avC$H#w~tOR%+!7`Xdb>Q|tCdc{xbu~3*VBl_QHFq!>as$c{b~lI;fM~Gv z_U7z3Gf3a(!kxqm;EMi`vW!S!$@z1f{4|NhaU#pZEgab3yQhX$!||x=_%?=UIfg~1 z*JX9V_T0=be4RT1Nq}|G_0c0H(q3M7oFe< z=k3?!^u)!qxn23;mhi@Va%y~-8iqq3FL{8$IqU><$czRA8rq&Ze=hR_TkE-YGgGrL zy!prGBi6y!Og;|7He(!jeq@|lJ9Yf8n)o2-H{+nvDh~1lEgtBP;CUknnI?V@8lA3I zjc56OnK3?Orr2P{9`Gc*i7wQCryfKj?=NzDGl(IsB(i!`KzJnQs zWzfgwDDvjbUkNu0|5(XMf#MMCK*{#km_ANEqA6^cnJhc^~kNtjz2!Mu6G@C#*cY=CUAT!qUF-?}D88?rH8`q>F@0f&2+ z8$QM>TF}tWh={81B86T1(N}(U1ssR}ItK{)#>P6pb#7u?!T)4y|BV+Un zFZ`w_Jj(}3iLR@}s8T)>iz03!k5gfVyH`(MO}3DqkCz*7ZNtl*`ttF2;+ryG-?yMh ziy&Vn>9qlE&IJ>cvyV^r;_7Tm){(x-eiDH70L&t6L=CMv>2r20tF(SclUiq_moD1{ zf*qiV`5PcKNDLancD1n5{Hay~eqFyxXhzVE1^nUDs|z7nES#L}QSJZyh!&5T|M2o6 zj5aN#dcYS!+2{Z?Qbmod^)=YhJ(kD%R#7Ji>Ku~x1CQa+ZSGfm`XJlY^jKvMSCZlu zFg%9sGAuFnLJXwP%yAu$_6h_6U3n$OzKTU`EByqg$l;G|)k8Ps z9Prob-)e*lRxe7OL|J{UNMB%bo3YWlrK95{;9S-@-_L}=2{`NRQ52d)V*I6aZZlNE zb0r>4s$)hZh@qmK%Ng0L;m#&dCSXpx2m2(8~uxR-mq zc<8#VY?fiJR^d0yJ-lQOVe6gb$X1uVnKk(Yn#-Wd1E$PJkiylVFXzI=NHZL)z_!VU z{nn`m5~iZ`RD@ymU-dJiVlQEa5iJ|2#S9pwJex2mkr*>r7h{2;qt)AFh1;HXIJtbb z`QdCV4V`7?rh*jBUmaI0P|A+nR;_c7uQ|uqPkf=_i23gJB{e5Kt_d89cY~Q@M!w?yAwEifTiNtj%sl0>8||D7>8aoV4P1W6OcEZ=!tr8gsjRH7 z2b`e$hG+V)+O_2h4LFMrOD4S6%e0=W3rvWUt?Qnq;_RoB50usNp4>6>Qi(kDO21JC z<7zMLODFX^-G8d$0OxO%d}@aYiXwynxLu_Fl!Tb#0HJtAcAja<5+NWlRW6^Gn}mev z+j;TJ60~}}rpG!fo%qfTrKn`;mUGabfbT&bLO^fbqjWo80~}a0RT=(mj((e$$y8Nr zdb^!G*C{`%2k)mDEPma8(%vVgV`$L2DWOnw0)@7sVj@bQ{>B@naEc=O@8vX!Fiz1d zgM|h+!EhqU12T0|j^T;(a8B8aE&7 z?HDBy@Ur60Jk7k7+Nub6RE;_T)xcaT91|_z6U)ubeFlm&@B#c%WQ;M8wo$IaO|GrQ zH$t$EXZegJge0}L2&tw^<_yf6Dn%{TYVcb4^nsU=G=wYWWZOS-jmcxrVskEhxtfc6 zKD1z}^Tew{p~D4U^6W(O4Ikf4#sQa8dt13ulY=LgZWn8K{`!1=QOc`3%j%rIuAbSe z{+5h;CGoxOPYIL+=yPQ^Z~7(G|9z)20hu*!S~{v-ctO_|h;G1!8jbIliUKC~ZKhDq z^~A9+X#$hzObr1w$4|>XvE1#`E1!Ac{`|JhD91kUYLJwmm>=H>9$ByVK+Pnlr##mv z1ZD$}F8x}+=mbSxjXlcsyT^wrw|=@e{1b5vN;Xh$3ie#-m1*HCy6WM=MN`Wg(JIcb zWn}~P5y&ABrUU}Zx3&mDyrZZnzj3cnuFkMsFaeIR?S&=DNyxFa^twyZ^%2zk6e-E; zR`a9VI|6D9ARyGFp`m?XevV6)oODD=0vTgMyX(DGbfe5LH;v@Ov~&2~!o=D*y+WOt z*_jkQ!>KRR7c6sMa3v}5@%4&a9y0Yc3#0=X<95X@jAgvj7L3}(QX)nTf0vMv1S>1RaDTN3h}Z+opKBC1|pz+wez+xux}SG$TEby z9Ugf;&V;@oay?JKt&$HG^ZG}2P`#?mb_sg!Kn#)NST+>H`gu;P8~j=V#X{d*hlfXh zFS8f)9aB;1QE9iVGE4q+U&KvJbfEWT7;=Mt9bh|Sj5z~gOWQLyR_j)d4$sqBVZ%o{ z(HEtV%oX7|RJT^fPy1Sdo$V3&wQaLMBRsFt}>22TsWp|JIhIXi(_yqaYH}*9c zwC2cfakitqRm;e^tr{ z-w~cF?&ND-TZJ5Tb-Uh8I?_;}sGw(}39p68YV_QX#Qn}llwH9_`z)&RjLBJbL8ZL_1nk-Q zrUll~N_-vu_OVm=)M_NA@_31~*$0KV{Qs{&=Dbhbc2t3#uDE`QvufI#vAOX+;7wc+ zPAfOVWNzIKzd?B`8N;DvJhxWqbv$v9Ja?XhB2qb(&yl0j{yrDUrAwE<`pSNMnddVb z{Z(!}rnfAz)nIRCqv6gKM;)4V-Du~$7AK6UD6}&DIzF-tR5v=zWvE-9orQL}L7(XA zJlhV7a0r}A5ZNk9kAMce;EA_~V<$e{)hrhR@US4ErQpv7 z2>6v7I4m}98lh9-G$Y*W995e}hNWgN&S_mL*U}c}4w(HSmY7h@Uv@~Ti2d=2jRKG7 zYI|5M%deQb)OYSdxY?K7+^F_RpWT$KYV9qD(z>RnusfAh`_Pv~BIm1N$F^lr)YLzz z8CxxS4&DmD1SDvO+_1hGFajjY(9FRv9YQaFH)d}L5~5CBwMmMKTaUi+kJnd+F+m96 zhRrosHbNBre8l>7>Dz0&TglN@ec%d_F$p?qX=Rz5X5T-z?y>cqqHog>5EudS4A~+s zC81o|zu}nJAOwzylbwc)SHofvAbc!zT)!-^QC{P=!zqj=wULLiaKvEGpXSzWiuEkl2uljy72OstGbR0%cw%DXjSv*~%2viSJ1F3_`&fQd+?yk~`zDpygqeA|9lSVeV z90uNOup7X9$PTs}06$`HR;XKgVjnQ0%1RERdZPK;Chud(Z{=x09PBfFZWmXd?znX~ zRw^pqVCe_y$>j?qY>9s%PeD@Rzfp^8*pheJ;BdWnkEZY}C%hrKf0P)qt$EJ-KJtju6YQO@#>gO@h(gfu>B_9u7@JD~_IF?3S+F6QL;7s9GplF>* zeVO_wvJD0B4021v>fa4*yR0y9nZhL)s!ou2-u0qa)N@tEMG;*O zGmS4r#mX@-GL-r|-So#i)3ODSF~)xK4GeSrHhk~#A$Vt#XY>t4~w*^6muv3V|ANXatH*1N&QAC&a$ z<6-_M&4M_2lE++O!))_cE!22A)O7<-p58Z%-LN?q1%Ly6-|DR|*`A|TBjdWZ^y~Dt z`Md>7Z@(?36?-lX^1n(Do_>sI-7b#T$Re@SlQ$$hwjSzT9DlCk_)V8y<8et8OG^Bs z+X8I!(HZWSZBkt`C9mEFf==PJalvEr?8h z8QEw}(NyeU;k&EAct4$9XI= zbnAL^Dm3p^R(UubG9GTy0AW7pr+@NI+^Ozt2xJ2K=3vFS)$0t_}V z#;_4z<7;ol+5xl+No%mdl&JgX$>!X}8S2q392_LqGBHQnrRUig-wAGObe?^cK*B!M zJZKfX)Wn5vjhqEx8hr&l_{#fMdn+7Qj3x?yWLw({UAQ7!p*syis?^kUG>VK%kG>o< z%1{%dqC&QEgcBF07LB?}UlUjyd5ntSih%07(fB5{T)d*BxB&-m6Ndiur7M?S_<9A{ z+x}SBed1kkRp+~TaLs!?o&*?LH`$iJ`}5~wNkx5cN8wY^T>9Z6W#79`f)f-!y?C)z zt12~}W;>*lYOl5-QLdoBov3w_miAA{JAw4;P1|H9xKDTG4d1Rj%G5mksb}`4`YsLTy>H_1~w*jLDgoNo0|t2REg0X9cVE%q=&>Z zz}53ogSWbfm$l?!RyiD)w~L1e0CyrK3dbkeIvC}^<;n$my=U<dO%)GjzDAyex?Mhe02~soC1ZRkac`)lu8ghNdCZpUgG-ZxX(&O;Tj|%#%N4VwLaAt7 z2#LzoTS^+gXIm!=2~A?JLO{vXE-XI~swd`5PZ7^T@#vfvWTCU>?fd2{qZ$MB#C84O zH(2)~`OjO7tQ|JIE~ zfm%Vs52<${B!=<;3c%soVc)RbD)wGE%*w-U#mnoiI&l$5eh-agyWOBqRT&g zc@`x{FmfowQ%03x&*|HODi?w!;Dmk#G39yjaB72e?s)|)5P+eFZBpf{1||RzLX+OU zQ`A&>zH^%G6e>rEBuZF*={9}g*^&ptEiKrU4+>_s(ZRs3bEJIupeq8Xm0F+s|u z!DESPs85T|gM5sy_|?lsCCjd9^Or9J2!5LvLJw?zk1Of;>Mb$u-I&E0YtvJ~rP-;S zN&WZL&3T{8#Zf3_E5U-!s;R_62hcr+_KB&rc*811YFYX0ppVvtuy{YxyE^mw+L=PR z^CbDbj0_f>0X8OY(PzJ3wM`h`U?M`~l7_`MYSeQ^!01vxMSDtc^R_Hy0^SQwYa|fL z19LQPjW>r{*EVyQJcPxBoRW}58YM(_j3|quxgQ-~K-}EI&O}IhBTKXmUl7Yfy6=a7 zRs8ubED#u7R#>}LPy#xBkIg!Fh(-f)@O4dnZ+{~JhZrWYr)lqK7cX!5<@5DhD~gO) z{JNbm-J7@nPuUrc97@Gh^$eWc5kak){1s=db$6HkU|v$weivc#B?&Xtm6LKlmdNHi5?G(&6f*xW0fo$j4d!uWk1 zMg|WRA9hGh{Fv@aWypXd<_0w(>R6q0M%NtynCYpSE-|rK=lzq3fwJ|5_4~hW9qFws z1VdMu>F&mJMaj#QJ0scvh;cy-*T!h(n5;ctc>;-Zfay|V?OuNj@T@e;s<4z$h=>c8 z2C0f3FJGFSNCfN7KEa95P-9AyBK_E5B26yVbLaN@S3=TFcK8$U==PcaHNh9;VaCGSMd2Y zR;zDNt0X~RR$J3LwmNG}s%EFHtz)^p!lTkLyFJEuxi5n%$8;@wl4)xY_ZJ8*z2%GW zW1O`2Z#R-YW*GdP0}B#AK#JfFlu=8isZ=B^=r?``t^|*jsgt26c3afKY;nn$8BpK$ z^zb8Qhrtb+uZEPik1$-P)skD(z&dFLEudH0-JAf65&3Dsi9&OAF8;@tpmP%9>We`!uv+^sh5O-zNlwr-Yuguq?O8(857&rA4ub=p)CBeTLlR#-J4`y2$Cpp0`| z@Vdy+pv3y-473r0o{U%Zi@=MZ&=(nF~Opz_Y}M>%oHE!-FOm&EA2ZB zwjH^P-9K?W0`pvOa!K-cQ2Zm}1bFXOZGf(>}%!y`Fo z4M(gNcHA6B-vm!rOL$iH#^uhh?d~U4uEKsUt~1;;LTUh}XZ(4`=+8E|k%MF&dA$=XJ1 zK@?LLz>6E38{gf%F<+WK)9iyaWZiAicmKi}CW)zE-|nM{g-TdrOf$JyBUr`1LemIi zogZ_SN8?8Z+|ngIui3q`R<`wv;T_h|7xB7+_}Ej3{QzaAi3(#wep3& zT9=A8TrI{myGxW4P{~Dwf-+xnTH$z~+uWuXRN7z$Ga-LnQ`0(RG(H^(?*YbE>DRvv znf28EqChfx^4bHwz~M@MAJE|H%S{Raoe0ug>h^H$f(uYiKn~a7P=?6}%}}v{nT-Qk z)&=icK@ZnMmfaJ(+Lg`Lm`r`1fr6p9Oi#5I4^d+)t0dS5h3YV^1r(dkCtNl>4D>FL zP;pWTt?QUjbr|*@^w#y`75<6Ls!m&o79q zswY;3wf_Aio|C(&c$`Em_z>KqlWYW06R_e^YnLV z&m9T>pV~^6ZcwETCJi|T4mn6)B6!*-hFW`rNemf=(>OHzG@uGmFnKq&x%pUtakq!) z6gUq~oMBq-$jx|NQFodIN|^N794zf%72TDql*-R5WI?cEF-?ig2~dnw1nM%mCptPC zWzH~}pui^}II+zb%P58Km~01BZ)TF2n~Sci>oVncj{iAIQdltR6gAYjRfG>_#b=h-LvhbuPbD! z3?{u}=s z^s63FfK#NRD~XQmMv(MX-5D|qW`+}@PfzoF=7B*XsAHfEyqDX&F~iZY-Q&2u(>vtj zJ4;ri_11fy1Bt-6C-B8D-#Wsz_d0K|`jf$K(xrw?fj(6-&n>2dV-34s9kI6T3hc4! zH7zjxXsCGH*wHpL^bFHVZ}d4x$ewt!sCazITz_wWBTt?q)^YiY^UweK&!DQ~h=SVC zEz*}#QO#ugBS~%=1ilB$mB|-s$=aTZXVnTBY?3hS0PfdhTi_qlROfJr3+L2%&z=D> z1MzLlkNPa`;o%uE2wVil=}&3uDP38^j?;2c(Z20Y^=1Q;BGWb4tw|9hsF?jTLFV zQKlAT6f9N=c$^?VcRlJFcO>cqN`J_ta>Ur)??H`jbg|@qe7jM=>E!|DHZ#s@79)QpV%^h*`v45I{T07#JL`IxJem)!*a2LX4 zJ+M}++Mgjh2C5J+13_*ltQ7&*l*osFir}|42&uEGeC-CfxZLccLt`0*P^Up`0JOzf zV^X1zoCJ#(kOgmdst*)5$sred%AY(}=K=9u@?9~T!TI4tmBeT>qJ2qFQMF~U06Ey_ z_PSnHuHYBV#%*e@*X1v!yt^wbb#x5n^u(mV71DZx$sf^6yZE1dR({Q<2Saj6{7McW zMclGgUuU+E8nt;1nG1ZI|ISOpmAnKVC75KeyP~LIkumd0V{xTtXL>%!EKbt&aiu9K zN5A_rpwlBd4u-nZ;|CdsoVBq-H9m8~(+X#+^eyLpTyS7uT-hE!@Gn@hE3K;q0so7i zyVj(rKy{(;k7+-%rPHXQ{H;-DP~`j@*aU@{3FH(3XbR$D$Y^Q5OnelwcfeNr4XjL% zhyYtlP_PW5X9~3x7roFSU|;w*<0f}t?g*S_h-(cZJ)lVdTal6P`dP&I5y2X-j+kzd zseItjI0lD#2bgE*$U^_s|I@9>w0V`NzIRjn?*{d_4LK+t>|jg^4)(kSbJW1|3z;c0 zGRMm8L83tXisF&H!^lNBXq~^HURf{&H{G+-A7YQ8lD7u{#m4=+>zAz@N*G%;zWTbH z#{RtxM) zXEZlo_ZiBmuaqkrfns@BA&XR^So35X!N7nr{km7WQ7Tp~NO4Ss604V&-5((`TZ~u; zda(OHG(+|!FT>QNp9}qV(4gc4^H-!_+cqgEW#;1j)ElIaFetub^`@2ex1*lJznafR zHlwr0m&)qvd&l>B#(#Ag9XysgT$P$-I-K-5nB2qar0K zh=7!INJ}?JNH++Gbk{#$zjMwv{xRG-_6FU1Kks_hT650(zHXmgv~<5SCPd=q$q88i z$U*!LvZ!|xz#L3wUhTe3h4>EGR)DGoS-JYsSp@KjK`nszz2MJAd=)0a3JGkf$=vvk zI{*DlVu7Pjjh{^%y`+{u_U+-D1sW!-7lODMgYhq1x47b;o3hYoNvh&teYin%*Ji4@ zlskh1yQTH0FMOqYglJNHhR_$7dnlr<78zYNNqsO^+&}2$=ljl!ya1B z;*Jq(9xZKlPO@k*Ynu)!E2%Qw95p6qCm+QMwT13Ua`iqYn-1x=u2OIX#KxM($KM7g z378$ro5{+@=2(fph&!4+RBkhfE&o1b;{@RJ*&4^#Bd}H?1{nH3*b|t}sUr6GL1?zJ zIpEhZbAF57l{!xVqp+_};4E#)kM6`pDp}0%>YkCWb86 z7k4+elgHPqb8yf|WHKV64I%3g1bFbRkopdGE$}fRg1Igb&Nw)f0ptS10q|4;Sa7cq zEa@!&jFTV`09g)#?+*Nt8vkn%u)zaC670b6dl4Cy(0!ero>p)qrX~MxnQPAlSSr#? zq^VNq&pOq#T5=;&6L$GbI4B73{%Bbwj9$WL35C)vJZyq3R64uU9qafVE6~bHG(<@ z95k@{m`eo+6(O#D7vKGlw-eLT*AVDT#7zXq{1X=G|K18j)GO>;z*#~p;HT*#&tW4= zzgT8~1f(Qz>&;!x%w^?M5i+KE5Q2GNpL9J-V%s&0{62;8?x65}I0mCyu+k4&0 z=Aq|pRaLZk?_{tROgvntX8w&sQneFd1~t1)s?LyOo2A|?HSOI(r)vykBj|wC7=VZZ z5NhD?W(YR}y-wkTZk-xtA$PYH{@q2!mJ-SqK7cGp)C7l_mygNOyO*ND^rNE#LM0>s z7pKOSzC!E&ro}x(nxV8r{!yZBgmhLvU?E~W4*uMcxp~vZ)`sJeV1zOAf&d$~f`Z~e z|K6WBG6>U?~9QGyK67dL#-~X10UO$_YO~v=*yIxXVwZ4;2j#_;O7VliWO)zi##f5h2cr zy%os^x5oED(*vgX-CfQpeUNcbBE)P!x9T0<00| z;Hk7quLM?^;((%h(T9EUmvfpN%A4ZvS8#Jm+C7STz|_Xl)8lh_!uga+2$9(c&B$o; zN5YSORJhN|O;-s*C{uj~kD$cpamfb(_0Z7?&eMB~e7Nv30m}k>8v>MY<%T17Jd7_I z_%tagDbR)inPJ#l<2*2(!>b7Zr@h5C*aLuw0ERC(6yTb>?Ae;ORsv*RI3_RxkwBa! z6a%(Vki>z>*r@o;5+A&FV97)zo^HC<&agq)2n_6CCJGs9jUrvH^8el6)!*SDEtsjj z>n*YA&L&hP=KPKKUI%H49t-jDkp*dCDKHEX#gAo#_kaJ4k(m9E)z&l;MgWvF!xQhc$zk7pKit? zm94b~cY5cQGuLS4ryd8(Ox|zaME<~teeuddowG#lsEbbUG)N#7I1Bls2(z-E9~HQ| zGo9L&C|}=$N5dDbx^9R!;SJC)1Ge;tTV3>-|G@hn)M{9K9UTe&iCGb9S4cEMasZ($ zV6+;xox$u0d=IEypofNtyS`erzk2;tmD^G`}^WnD=A@ zJ$cu|-?Y^j#mg%NI&-ci^)np?$b-cW2cL&@NXzk1TH{*0C*g>*SWR7Ukf zdj6lw2??e+syAgKgs3+_i}82QS-6V~T(#Sc*CL=eqC#Z9LQ5FR6DULx(Y1blX}~@} zII#hH1Smr|J>iC~16X#oJUZW8{HON<|0^omp}&V~z7R*JEbzm?IvyM!#8Nd`d}LAZ zF5ZbkQB0|2jOq$8pQ?0zLmeO|m1@-3an&rcrF?h%Ffm=wnKayz)gV}IrbX)0pc_TG zEhw@vTkr*4lcGD!TR3D5s+i=cSux(^ZE5GkJi7~CAdY_|n=GRa*A!>*`E3R)dcjW> znHqaQHeYK$++?j><>MDJ^L9odk|Aqyg*Bg0U0&H^hI#8LWcPId3j|7))7mm#V#ALA zZ^glZF0QCo*I#J^I!I7Mx0}N|T4D=l)zmr%RaETp%ee2H6=PPCAz)v!nQAE|d^~T- zw|G$AXUPqXhL7q><&}H-CupYc3oH%j2k)3emKQ{E(Gp-i?D@xVfYCi4DPiGA$j8wB zFl?T81_Q|VHOLQvJ+ee&0;&tRa~cd>UK)N5QN)s5BzV+GLs=N z#vCW8Il!+mT`=_N)29k8kT_9fkT$TV;^6Xby*5!&Qaq_Ii?jF_9kgEYTWBbdVjG9nuv9);5+3qhL*XixBbk>Oy2-Tf*S=m{+9`Upx-f6&6dTF3(l zgTTWrg`Dpg{|j>{wjk_gfB~b_1CeW03K>;!uxvM++p#hGLtO`lH5UbL4Zy5{k}*|f zk0`Y%Iv}6J0RT_X2(Jb+{=e_$tI~T24?6|(3uP2@K)&Qp`f6mD?wZ0)P3>IR<~7;Aji(2 zkXSF3r0#Bv%%81#6MK8S4p%GQk5G=sXB%_UkGR`-R~nR(wzryagQR`brgZS-?r4Is z({aDH!70Qp+x0DIGmntFik$quKiMHeK}B5#9p=47!r5tq+O%iJ#G-Yl@fc64BBT0l#61r#YtZV#6TLu$ zyZ)W6@A(hnLTP%L@v5!yg!H1#_yP@D1)%UnAfliR50CcZq(gLdauiNgo<+V@ghJW9 z@thLz0mw7KszV%h`}=aMwf|k}bzPm0jThp`xZXIbVQjR`QX!tXkT>)bp4n~@f}H^n zs$f1rkm=yUm^7hF@ia?SQdP1MEWY+J1ES}V7Mn2f6#?Y%!f-d17@OZGx(*$Wqyic< zPIQQNV;+SbEhmu7+`bnW)wWul11}KpV_($r;pK_W4pX8fOXibiB23^6henfam9zFs z;7SeI%zOS-XxZ5&mB<+W9ZI(#HYPRObPYZZG*f@oSgUt0$f1Q5nFaDP$@Xx3Q5F{q{MBPFyM~a&R`#?KiSrfhH zhd#o0_iX_B-fRL95+ca^tYQXlbve~ic#!O{ZRxFh6!Cqw^usDoP7o_An{FG-x5 zhcx|=dS~<+uZoPB1^YCW^nAACSH_934EIK#!1{j3R{^7m-1#zDA&zhD zypMTLfB|%RSnRJv9O82^By%w#L(MtJFyTINigB2lVPFpi)ipp-v<&H-V(Soc0ugPgpt`$#sUZwaSkorF< zoM>`Oai&Hs-Q7{TR5LtLq$N&1(Cj!IK4gNL7v59Hr88G5VMB}aT_RkdJbvPd7!F_U z#ZgEY2VFg9Oqwl-COhJK60F9ob(kYYLvLILG2hkwPZp~J#PXK;9}RG{&+}O%4S}=1 zmaQlm;~1dP>6d>jE+7e*znM>rDP)PSi)-~y?ZPkI$3-*q-774SKWS6-tSBCP+EdU= z5hdJ?2i1S5Qsfd}bu_lzrGQX}xvgtd+o@C_hnRKLQq8X-i4@-eZu+DESyAo=c@OT3 zck+ZE=Pa5_t$O&<$4pi3B#CCsgRJrhf|uQJ@uTq_li(rl8tY(w4d)#d42pBZ0o`agX0#N$-KXt5Kg z1;ZQ%IxdhZHp1-k9R}-**nfQvN#e706Vul=V3pNChkFbz`2=X@M*!{K_B&*`>bpK_ z+O10bG6cVmcYu& z28O`O=c%^ag3F`I$^j|<^tv(>=_JKv!&^8vQPQ?Wa`<`L7P|?J@`6hqqMJ6sC^&{% zh>ilyprO3m#u-b&I+C7gIpOxfxv8O<#$Q^tIC&t5ivky=EO6iw5=tqin&phgNr`!S z_lj(%Adk(aL#{tt*=XF7HI;bP%dE4GwtAuP!i+!On8Qa^m^ zGWEw7?mib(xEF{%kG@c&%PQ&B5gtlwt_Js&-PDzIv&SM@meKj1``yQ))!5Y+xBfxp z7x2z0vnYF!ure)OSI_6bfo^NI(brvU^`avp8WV1MI(qvF{=1}zxL-u3IJ7N6 zVz!T?TT_iyy!9qYTpi!OB2c=%8QKvOqI~oA{-+983D+zB3s63)6_0{R_1ENri9hv# zBU6I>ulSpEQhT^~G2kXaoGiUm6RiFpm4VDn)$|NEtxl*o#AfJcrh48oi?Y9+gu-7hac4wqhu26 zU}X{CW8ZGrigiXYfV$=Xl#}&KkKn;EDN%Q>wN7 zF`));gLYg`pX5@^qbJ5IpV44QB82a~Ntb zi<5W2G!}fnLHIqT2yiwuD*#4|$N>WK%*u!^E2-{+{-G3Gw3h>A!s(b0wcpMSxQ(zk zUc5g){tG~=+_A6Rn@Y^tT#m$#ejnetbp|?SL7~9I|HRmS2dkI*!bav_;zU)b8bBM+|(-UEK+KMy`-|X{p#?pkoU=3hJmp=Z|+qV zmVEHLU)IPV+C-9Cuba;35;8sgl9=&18?gcj{-!;lDZ7!f>EN74)~g9?-70eaH&)-jEgQ9A-+vwZuIfGfUn(kQAh=9893#WbDW)KC z>=6%79E|qrqAoN~#hr#o!gI?@r=B$q>VX}%+G~Y*1tE%SM$FOM%Phcu(!GaO;S>ks zp!PCXX!1c;76RxASjX2{1hCoflERt?Ou09pg%)e6RLRVGshzIhp9DkY1u4Y6S$($< zsxWVAAF&Ffjzb~%4=b9hRzCloxb#y!dXj;A(^aUaP0N0?5q-VYZuySIW~6XObe83e%yGZlzcLJEp`wShTr#eic&Y5=-h-(}_j8 z_wkR3f;IHYpr5GmmE?tmzL4ixFwAONXr3)ipx^ZN4(Mih3^%m)zGT*3cF5J!EHeDw zeQ0Z}o3<^B;g09cOpDYDo0=ZeNIxCad-7!vvnjH;EVC7f~M?i~hZ@ zb+!mBCTmZ37JccqIrIlm!HJrZ|4Plrn4$wpHDW2xCx5%P-4?lT&uRcZ-iU?L5{)rR zZpN;S_G$O$JFQx@G!~>vaabg=Wlj@lu6w+=Pfi+yHCWK}mb|H8U_WB*3Xh>3FbEx> zC=sZC#>@AR8z4HPdU4?SgD$rfZ_bX;&1{!Sd7%3^f4}y-{{3|I1xW{Lz?vtxoE*2h zNzQ=IdoXk#VG_$WfV`)2vRN$HfiL#9uc9ZC?)Zpy;jG=d2;jP-4LHU1azPw#luWpP zMpY8aZ!W7cisY2HsF5pJm&=E%TPkFg#}O+kQtQ4h9Tr$uc)5p_SZfhi!=cLeQzn9I zlmBNvQ^T6js=nbX<2PN0^JPDa*kRYgo22*W@u|W))x9d=3URi^k}=_unDjXxtN&UtF*j;2IM$d@bFqCR_V|!~QC@TGx$M zjXfsF&vINl==sEBlzLV&^ry~-ViU-G!EPMCO8P#$S`~-h@m5Dk7n-=O?yq&$eO-U8 zyj!CwNwl35;m*!pAm*r@p41 z_1+fVI3$mL6c^f_(&)OO6zaj$KS@nN;cz|cn0Ge@1l8U=#E=bu=yv(?AH-N@#t ze7>Y}yYjiY6?TWK0|jY^<2PGD$2-42B=HYqh%Bi7$nN>0#oI!cS+TJ4qG zjM!vp;JR~WN?-nG|6Jx1Kj{m$r|4wqf-X{{Cz@+?71X352WBGfoZrq@nw|XSdY@@1 zIL?jK@Ln~#H)u0?;YIXN6RTr)mw=n~|nj~MewZoK=S_iqB`lTaoi@T&_y-az*a zh^ydK0AKFEuocLDao}49PW2j~i@V8`1=a!%K}!i=REQu|K+lnp=zl^tOh|6>`* zEOAU3e@XEVxl^(;$!>qzxYjWI5xcP<{k!Z(`>PhWp)Crh5|ReZYsK@~V9CJLRb{5N zIu$2+W=5mo%>Kehr|D-msq{$?9dAK-HCy8uM0)dF$iJay>HOFVWF&Fjd}#`W6DGAh zJytnCV1$`u->3F4&XI*zzMf)XM}qWeIFTIU-8`#mToJwO^Ix4mL7j3Ptc)tD;}ML9^EXGzsG4@ex<4c^4Hcp5mny6 z4+ZKKwL1f@yA(G&-1acRxNO;@JZ8;SOHWT*!9`CJ^+cbXB?`Ipq2Osfjk1NUXV*hR zViSh5fR7jcyljhnNda

~g77U8ttB9UtV)gv$ji4EsYiG982osGY91!;p#A(nb`` z$JQ%lr5p;mYZ3)YNV^&~Ts&h7*oEDe$HRI(i?GFg$8de!ip*nEEJl*7Q_YTC$Ea^) z8MzT!oNG_}U5P(Q(b`DK_;_uesMBA!jKeOlZcN1z;>)7w)#jK&>=L##ZFv3F`rSw3 zvZxvd@#852b+)gpSB9wT5tX}N1$o$NU-(S9{+mDTtO5bP#(51FF;E9=D2!?VNDZwr zX!n=GTaRF_!#oDE{`jJy`m8{Rz=^Atwfwzk2jDh&*GazvhQEZ5&=y;!~g4`|o z1tl3oUnX$+l>KYq`Tp0R_k2kLgEgYZZh9fPvzygN1kfeTCKmi|7Dn*B|Gm=FI zhhTIbM&TkO>A{CEqI=rbFz5M>o3_T#{~TyOloaD_B{qLXwo>?`9wm4acjSpBi7*l` zapXBzz3<}hQ4Y2mcPyabvQ;!~Hq1>I=nSy;m6RMrej*=ttg1QON@D%#bs z^j{S=mk>QMVsY(%m%e4J*5uMMQ^4oVMpERuuqGKi`deeLw?9bQG&}QUsc_U-*pj|A zHXydzdKDrLvuVo}-@V?dRIi-|RTf3jc7)wpBelqn%Hexo< zxnaX*$B+X1z1_3nV4uHhWmplX%TG$`N!gQxV-Hiy1LmdtUq_ggc}d}SqIKP?aqzKw ztmHS_7yL-CepTRrS!T!mw8izE!=-?#-p0R_gqEovz)?qt0$?f)(jpNc^CLWwX9r9m z(D=u9mC6Ff1S_F7)C$9nFak^Fi37dB8CW!YA`tR%sNSuz?#Ff zr-frUxfUXey^i(U0K^**Ft@l|^jjS|osh&^#PWAsn8_`M z*mc`0wL&a$eUH9#ncN967rU!=(}vc|;(Yz=LAe&7;$lhe%N@^kMa!(#RlZMrpCD4s zqB6akaaIxHeHEK+idGz3ci2Hh!6(Yi@^Q>vYZ=;^r)+|;_HtHkfpY^CqhNCJ-gya zeh#w;m|zU-!&DcfI!IuRfv9Ih=ruIj5zXNugPK4H;Ayb8D%>B~IXxzM;t>QgD7Yp^ zL`X(a%l}xCl>M0YaS?1=Nw&OJ(3ARJ);GO@Rj3ySUcA}sllxaculK0|7x4@bfz6X3 zVCC0UxHq|?Y1bh7oZg-t0tl`r7^9qgQeLL+X+)@1M6T56q(zi+L(7~|KBY#0gtmgy zgg9QUl{t(cvG-43N=|!X0@g1k^KVL#=0?$)DpsrF_f}}8!sz60q@L^SGrn?3$N7wQ zI_%n>Bu1596P*>xhZUBY$QT`#C8-GH)@Va;3(&T38WACTpW^*d2fhrx%-W)1KPj3bo(A(O1B4|4 z!qex-z%3=N-HlRylsS5HF~O%hn+tSe;IrBGJ}HV=tMMp;7$Xm$^LSN92aPe4ND}3I zt1NI9{{jPSAX7FU`xcKxRup^JdY_9heKlevOUI7X zTBF?XJa{cHwe>m5QB`Q5NMhYjTGd6lHD>8#k=K~xh<&ng@to~z)XrB+EO1#uqkf?e zfk20y8n6hUm4M9zL<=xr)~~XI{DUUAlfWdvsRm@g5Q99e>9fD81Z01JI70Jg*7w*D z;j%<<3_04D4^_B^bVSTC?3oc)&-h|Lyiam$i7nLSF}FA6NQ^~|oj0G>U4O}xv0?NU z=}}OaZg7owbN6nY$5kLSGrz3qe_(!qC=x(QK!zt{V{hx|bI7dTx2jOoy;!Iw`hin7 zrD7n0_{I5i;%-Zut$97Fv@LU8Ts^_C4}h4#)=JTl9q2c zaE68E7~LaK@{&(_YYIPnWPFi$Al2bEIOeHc7>3;;s+=W>W7T+%JvuS;=j}9$99&yL zf~uKTe%tS1vZ>X{u4#8u4;kYQE!g^x`V59D%|Y|^jS@`gj+CSw%Hg7um9AO`CG%R1 z4lf?E&?Z^vkkU%;$?z%{PUjUBx@1Z+DNfSQr<_Y0sub*KmJpJXbcaMl%#&Q#ciOV1 zTO*v9ur^?J4pM`Wk&&8hm>9$87mgFSs=~qHNP!RxBH~BMm|EUKy%Ka252l-N%Yg8T z)6rr-NXdbN2NAOXVaZpg{LxF?i~R%%B|GgfV&Cz)r;P7MV{oE5yA$L@maOsN8*B25 ztgiISiFC*5O-HcX%+6x3YQ5Lpd*K`oI;tF>%gs6PJU2Bj-0SI4IBB?kU%eM3lu&F_ zh0JPWzF@Y%bTcF>oJSIiWlSe;>Zcl3G99&cPJ6!?1KX0zeRlgb)|c_z%OqJi%<3uZ z;hvqX6J2C)1HXlHT8)V9$r?0ynGIlxR|v4Y`@%))VpR8V=8m&bWS<24NDY@=3cHQF z$N*m&YqTtFC+YHPAV;_4Cthc*+*>N(h8Je|kiY+&X`j}nO%|6(;+cx-#qfSovL2J+ zFTYQHt2W7BcYHVrY0qh>bEMGAei14Lhl_`bFS^{V(bw6mn@K`S#mu6QdO!HKcKqko zi=+`pX0@C598;<*muNh1;Y_w##-&^{MmiDjhV{xyu1GE`hmT09wt^q3;|6`?`#>+! z=*Y6G=YqVzc0hL5bKzu1%HxT*&8Gd{pCw_maX(}Lx&1Bns@^&s7Tv=mOF=hsqD5r7 zDd$+)7?`E;vjK7)Qg;4WU#j8At}gbcu}BC07C&;|6_&Da;{6-Go$gck8~I=S+Cm>h z-hev-@&`XVI=0ghxB%wFlM1jN@TmhZ9YA{-h{O<1Xu`?FP=SL12KS%_g0K4JjDY0! z6mZ`xvz}|9HR|RMicn<5{?C0w^&3I3=qEqD-ka4su6|;Hj)Vzsnf&}}S_P}@cTFyt zj>pnVzn64DMI5DuHgE)iDKQ=;6+KatU4r&*~Kb2K!jc1qQ#=bMAt7s(KKCy%_zO=i)UWtvs3Y@ ze#ues{w>`A^cww11D8y;Gr@P5RVhTp12SsQW;Y*k@)C_`Qf+a*o6IL97$lw^Z^OV3 zd6FMy&NI~R<1G#Q1vw94mYf-flgxRI`X{6A+@8t&M{D1h#_}H3Fj9mNfUi$#At_lP zf+!4Gkt~1{w2xHB?}XlWzU3feP^GaN=_HGzbITaO+-u`x=KSeCk+qvcS1I0skpi{DqDF?dazV{2*$3nzEfolScehaW*!r zDLQu9Y^trmE_=VlE9u7sGhZ_QxZ(T7$mmpzUlWxs8x-uTFE?9GHBNEfb>VKDZdzRB z3lQ~H#C>lX2%FS1wZbOW5g@8yVCQ2u-WaJ-i1J$RSyMo+W~;7`aOY7pXf$$7eO!E6 zkb^b;PTRQB*j3o0?R;Q{|C8UgD9J|4cyCR^PSpA3##0DycpD?N_Ora`tRvwyXtr@Q(INXzJ>p z`6n}EZGjjML4HNe&|pTyZGnv!932n>@t??{Wf{>k0$9Y*#9QS1qLv5Kuak}ZVh~$E zAc#;UYx45#OGytRP#@z5Qy(#y?Z5UhQ^q!YUK@R6qlXRJY9n)V?})XhV-qix9j)A6 zITiM|v~W51EBkRedD-rRRQsJ zvMe)|RmG-G!|E`xyFkk4Y5y($M%Gm;7Q4q{i&N@NCB1Qic=jCz-QChK`&#Lh?ieOX zHAdH??85@-M6c8DdGaAs5x9|Rv6DLY#Evhl^CS)V#+e5+`qKpy0zNsLjuRhkKiAy! zu@H8)y`7eQzt10te zOd-bp!Q?ttRl1aK{Jt5xMKh&3SIKAfy>j`fIHv?3(Yv1|A0_?XN;*GNr74li63Eoh z5#4k?Rb`P(Se{Y{+5BvsL}xD`;vBxFJMq>gq01wEe-~HoCw9^Hfd{lRZRCh$P2fQZzl1FtWpE)giT3jg&dZbz6 zs^8fPl13JmV`TNCuCs1P=5aec2xJuLxrmOqGr!*Y>bdEZGS$igpBt6FS&kXM1KZS2 zW<+{7)>E^+us6Lkb|euZdc5(e7=OC9wTu!uiT*}Rj98@BGy3HlcnowD#Z|XG%%AUM z3;#p3CY!zJ?sO@@;^1)=9lyWC;Jij!9DABd819VrNa^E(zsTg8P48-(ysJ@BDM!ix zJ`Og6$Or4mC6cmBLEb7!|>=>;$AVdsyRQT!_P7RoW>5z9=V8W=t3`{0HD>-@W2=^_c(Mha0B25Y`0h1gDx5(pqOjki-mt=oDlC zkevYWIEWdDo;AR7b#-+S=tqQ*5M;D)enaL5#KsYXgCPhmiC5(zV~?N7eCThZ$R=sn zhSbuQKjTUb4eseO#&c__*4rxij~xxuLsm$rM14BXRs{-^=waC2a%f;+yJCDNGU;OP zvef82#|Ojs4FAhwD^KccqT~bB3)(~(>RicRJl*)4bmM&2Eh!`g<}Dwz@ZF=BeP(#1 zWOkD(cS@0sPSA_{gHhvNQ>Q+Ap#<*8L9=%nex3o3o%+PPk7yY(d6EokHJby5k{;q$@ z)y0iO`xl!A`IYRm_nKQ@-IwMf44;wH;A0>WG4Pub z-pn))eix_^zGB8QAejm$ICiYC%@v&=o(egbm8$zembNBS%s8Nop{4t zKF&HB9rLPn<8>$=zt0|(m_6$3ZvKFLda+Y%&uJD&PW;96p6wKQ zL8Kg3E}h}$kv9YJwlLL&e5d>@9BPrNO3K}8UZqdycuhPc$B%+lbdx@W>BPvox+5j? z$Iy9xR{Lbzc|^C7K*;>6f)97#Q2g2^6UklB z4_7uBj)Za-23d`b)FI-KUv`(2l(f384)q=?G);7jjXNeL?np~ZzwLU4gakq+@JvAP zE;7_Xi12H(XU|Zf_Rjc_sl%G7mN&n+h>QfWHjvh0a^F(&uP~;NGVP6aIl6a}gmON3 z1UR&49`jc_U-j}#d~9$Aj95*~%_&*(SrThpu_HansEPpZZ0>AzgT>nV*Yv~_V}EMa zpOH;nk{0hJ3Fo%5Cu@iWQE#cKDhfP#jigS1(I;U`Gu}4SZE+`z4O?3?Yp*O=_8Th$ zYV|gO65nSvJ?1%-+`J!FH>d`qUTC4o<+plqV-tW8W-BIG$oRAy~-qEtWf$H zESHy#MBGC3QB0HLQ9GSS{2V7rj7|Fk*4sfgH*(r|B#EzIj^>k3i(aGiAUoK0KKl@; zb-wn?KISV{!g~(yte3WCdS5Ln37FonCZmo>GAFGZB9AiMeHTaZL264lw3b{_?k!z` zl*SZ6zr^$Mx~k5~Klx`jnli#y-l+_HmE*$PEvC*a82)W0`g1|)N8Gs{#l}hln#S69 zZ5=I_Y0(g5kyY~+(fS{}*@7H@vBD2a8H`rt=yokAAuxuFjI0TiO%Q?u#naIE_#3bW z*7;qMr>&X#_)x%V105~|uCW_8v_ekN+4=b{IIJ^N7-jL6;XVS;1o%1eOPG%cyR%g5 zgI`LtVWK&*0kB-@-n9x6s#TCM{=vYIZzEiNVZr&REOMp7wa(|1u<<;(5%?%%Z;A-Ea9hRqFR~;renmdsUhuhlZ|Ni}|Y(YQ;xhVE>2L}WK5!#kc#Y{m(KJM^DWDpgTq)OZu+i~D|ul6-<45YitM9g-V3cJ4l))Z#WzB z*>*hLSn~XoEtWA%f}ivVFKsQzEx~igz+XS12z!<9YVH+D_&2iMhw2_XMo7Os-&U(q zuxvkj8z0a_`|kcHprGxb5+83V;L|04raMUIRZ^I=CHr!(J~w;770C?^Mw~+!^SLL2 zJ{#`_(O=_}y?W}#n=Hjfwlfu9T&axKnEVB^r}A=Ki70-7rS?81@dApyI2vkniyV;{ zb336_h0*Rq132+5zt)`dpK6`OB$lTQOP7v}iZb=` z0vG#TM3k7Do7*6)DGoV25)^u~aCcZGb_p*zr7_>yST`R?r zuLuJd7EGt>ok=Us&>+QQ(30nEiQ=zyZhDI^DnKz6x;kU2gN!ARrtZ~H3|FqBL_YJ> zfDP~Z-XF1%#?h)*4uo$ui{JRmQCqbY=p8=SirwFB>Zd6`!myQW6>dEaqyJ=FC7#HW ztfOSoNwfaW%Yf2v2r1_?%I$Lp;vM2dRGvEz#tS7qa{azYGV5T5;*m+EqQ5j>XC(^I z6J1Zm>kqC?eBVTp_PT3J=vycEOqR)J>L~Ij=P(dW)4=sQvTezj)!%1L`b}2t z7tVRVJUDpXWocmDUtH-)lrpK>0w>296|dHnOU@NEsO_~+<@iI!Dt z^myXOpKhy6I}7`BMFdj~FM65md12QTF}-WLqh~h4!EgP0cdiF{QQ)do0AsA!epf)d z>0s(8tkz4#KgO5!>S5Up`pZT-zi7}q?YjFPyH~@U3Y>I~K0Y}8{1A>72BK())`*Ob zrcG5|`tt{8-Gv-6$9nzxwZl^TEhI4*Q-Y2M=SS1>G99oqu|kmBJ31WUOEBxxiAU?_ zpWLdfWB>UKO@h$>#XF=WSdg?~?sOQ)QXk3cyr`P^VB34~;>)*^`lyvdSLl74n!O}{ zK_B$$)eZ2LnK;{$2MgED`W6+ zX833_eX+|Sh!1fHkSo??i@8fP+?mA4A!Vb#thf}8rE!UeME2>uxfFK_>JEljkom%m zXKT$(>}LB&$kLiCv_99TO~>)7$l6STIoyh0@)*LFkZ^A61=V46Lw7!+WINr z@LM0Im}E$Y`%XhH3we_^=9%U15Ecds*<6#DNx`P$*Q=^+-mT%N_dH0xO}QFUN8U%B zHPCSt`^CD0frC3*{=}>aciZqrl<&a0+tfRn+R-E7-1?^dNoU`c%C%YtL-v5r_vlE^ z*CKx$3hCZ{=b-9w7kj=>XyEueZc{zdNrOEfifgJE=ax6WH+oz4+NYUnR4b$I;MXno z1}9t*m!V!53^AJ9W{uM$85yk@Y}m+C<$-d6gH95irxFo(!-sy-menm`gyeJ{2aO$M z>OKV$aaC4{NQVsBxde1J+?o$~;=bwYw5Z%KC;o&U_tN9#$r#PM;0WVg9UPL|^BbK|+ zl|hb-g;hp3`)ZI#2lD~m1Jnr@^3hLR?H$r3?j8Xhc+{E2jnuxCAua+@&GKk*L#hR~ zc8d|kjqMHeV{^xsIr~dD34@i%(x|$^1->C3Byu+hkORbQ^Ew z1qiumkp=E(zfT~L)vUlWsLoW2>taAr>F{l?L^ihioNJ()S^P`+P32A6JDCSB=LsHs z@k=S4efC~Wa)EC|4wF!BSZ2ieZXv_f2sbRYw<0b%k$yMv1HHF!1#4{`}5Bvjd$& zU}rs^g97AE zx^4!?QZ|gcza<+kH9^C2_{nXeyXZc*IaQ^=x$-qIdXr|4V$iO6&z0HsY3t44%;c}y zLPPXX0&Gpcg*6K_B2aW|>pQAc4L9SdXFe>Pt<}b5kC&BcdwLhDsZ~XwcU!(x2V*W3W5dE;Op!IPu5t%=Wm2ck9-TfV!Am=6Uf?0XDpM>jxND zc$A203~+^Zs>Vg{|K$`NbEJPK`9BNKk2fVOnE4SBI**SO*+S=mom@8w znI(^=Cc%aQ9tQKGZykf1iPlr$iqdU=A`~dO*2QXAOBp0d`h@hP7nBq=Ji59nHnUNR zcXE%*jCfCr1yH29_Y}o-lm*_FVcE$B=di>P`>KXJRMf6Wvbg`oq)hiv$Wz{ud^4pn z%fNY?Dn)iGymK@2Z{Bc&2ZryRn>a;V*vvxsM`U$b_Xr(4K0mg+Cj_xV-#!Ma2FtrB z-J84dLts*_94*)EDS3*fy472XgX zQf7gfc38VMlrQG)gfDNo9#`-yPBxC~IBp%88Cz$ILGr_0wWnIkzvVLi92v}UNqT5| z_e$hX1d@7Ke~-rQINTBz8kZ^?4c_!JVcl7HL6x{E_nly7bEfLWCl0a8v*$RrIS+*^ zDLbCzkK%OW(?@HtlijG2GVFR5eq;W2!_Y9Po^s+_j-h7`Mrb>vSa#!wCLig!CUBf; z3{GPEXjA3UZr|sB#$~1RCB%h3NRggMH(Yr{U%Zu9+Mvt;MgO+V)baN1@lex`4Hb$R zUv9@f-K%|3w-g^q#>jM`soC`4kMuIn-Ti&~Z%_S=LmcV2O5_B@o>#X#+3(icW)c?r zqxn|dKZddLvE%v1p)k!$`%LOsyBI<_fv>hdp<*Mj#)*tVsdF@`zneH}tbN0^I8^Yq z@42?G^o$m}m@kP&16IrNSrM+Y?bKh!2tE3r+~zk#)(q$^Mh8|jZ5hJo2u)I;NQKJ6 z9WPB%6rrrFD2}d)Z?5o!9PBTh@tLG=VMcG87|rnx;h0zmL`>uA9Qwxk7L9SPY8;y7!uACx=pDbeh;25}s8~+yL?wdOR%`Q`R1&cUlVKR(B9r zxMD=0O^-2{%MMcE;5rO|9p?4YnHF{QPwA{YB)}5gH-ADXO-1)bBleJK-at4;)s+v$ z0)tgP&>VwMwsOk0dhw(hWxy)P(5amA=GtLIllf%u6Aad# zFRHJt=W z|5EWW-qzzAgB$K-5xb*}w0TRK+Z}NXc2karPH{5Tej>A|b#*z44Ij3d`N>DW}N(;V5DMFQq>}@cl|F+vxmvZ z$Xj}+DPDK9J2-fRrp_2DM#cQ7EC>~eaksdKSdw@yg~xlh8*yd-R&WKxQmK4&5jUmU zzucz9Fe_jqek()V^h5wRQo)r=l?I<+gs9#_IN>B(5;wlJV0M)}<$?A93ch3kTjm^T zCH`b!G~44T4C1w!V>Dmm=D82OBLS00VxGA`K*w_ZlTMVwmnO6RiqByx#N${P?kPxQ=U3y(Z}Err zg#hj{cNO&JxoOI&8$;UWlt0Gv(#^Byw}`tV9r4?n=7Y>*uuXdD-a4WD{yX*VWV^!f zX8F+Dmo7nPG-HmGi64+tq~^=gmbw1kxnCC=-1rr@?E*ET!HY29VC^=Nw&qp)t4F*1 zu3-&V_m5cSxdWn)+jvKg9*Vg!$GzXtn@KC`)$|`3$m7tbh^^hOw*4xmGE(EW)y9;) zgk;6;>Qc3-le(%vEd!N-+H+#M8@NCupd2vSBoyexl9 zjG!O)84nH@+AoxR4t6_!=^D0eOp@F6_1%k=fAvvItr)s7xabVp1#cUvl16RAil<4( z#h%&Bey^gKd%I~9C|StcNz$6aD7L3JrQJvWVe4IfcdvJX?!s3B{Jil8PwXGmTnRfx zozZdL-OP^si*6Byw8Tj$f4Dmh*GP)}A<*>)WqpUu1?c39{0B z$jA_Wf~ekFqUls+tw{RZ>%kCIlT1T)35W|j_fX@RJI3m;I&Fu!1`>*%4%k%#24 zTTq}XE;oMAB0{cwbduIjvB8hq&G7yvx*T5EMsneae!gu4+7zv%;-KVZMGaSTOWbyz z+}$=u=aYESqNOPtj2=8uxa&4m+@G`NO-9P;{)<92i{`wrFZ*-&xycrg>=2ik#IJ6EKcEuNR-5 zem}WSo~KGhcGE;n^FcnA)s0N0pOVmv&{)*!XcRXsWXZbGDHmbKtn1qNvOd%{mls_? zvY}fx+5=vz`+)}{1Sa3s?8Wlr|`CRGr#teiiSoz*IDeb zj!P>4ZTfd-Lp?_`x7G<&Qd*yi{_pz1ZO-B|c@o&1VXI3jS)1l3N`L1X3zsqu90JxFP3!p>d>rtK6s<1(4? z5Zrv_$*}b21Xp`oP=Ie_;eHF9X^RB~} zJ}!3DT$n~D{?RI`-^#QF_R!u4H#r|zyf`2 z0cn&D>F#b&5D7t0q#Hy)KpNlS-gn>o!v}l}GYn^+z4uysuT{_5VLc{T3dbT4l#L~4 zJ6Y*BIQ@_)RmZqP&NL$*!H7c2vEZ}URRjOxO)+Dae4?*x;JAcQ*z$xLH+F^Rb-{aGOL3v)n5ywE0~KYdXZRXO#d0MvC80Ie14KS_W4d57KA6D!%DS zRXF71gzhWqkXPyrZAAr#O%=Ssn6f*izMP-bDKE}u3CbIK={+OwS4q=>I~F8mXGybx zxIe8`vh1w#{_U%#SiLIb1+O~no;msCN~rD~$6uxu?Y5d=Jx4j@cOUEqTaR#b>sXsu z+u*B}7tys4J&7D$!3LOq)mS-obh&_C8~xn+z_Ha5R5YF+6R&3IbqnRqbz*q7>|~X! ztCu-6sw#ut>ehdw)w$jP`EFU~hiG#m;^M*I^Udj?O5K*Oo9|}uYf&YfRnMH_TTP#U zqc?fUpA0x+rH1}Lq&i5G@<%e!3e2E+tT@ayIrZNXi2LN)9i;Yo7ymej65(U6 z-v)g?lPLye=tx6gU9?Y~-YWzo;>#GkW_eD+yCiSz;uP*yWJ{EetdwMqtufK$cwbGl z=~60j^aD^+)!FAx1ZSVm*uGQNgb&=p3VZ0 zjfiAdE&0^yvyaF%jLigG5w6*H{CYPuzPt+aV{tL>S@m5%CuG1I?0X0ZS|Dq2JWX}5 zS5&U1J3-QA?*xiYc4XCR5IbRP96J&blh4r-V%>vdn%|)sgVfD|AHPg=?8=#~@AEB3;xTgSB~L;tSoxAA=fYnkHWUZ=A>U(L7l zN)wWm?;GX_-*opl5@mE>j)ndd&bPV{=n+q1DYDT zdr2ZwJH=8v(Y*5eEVl4MOy$ict?L+iVrXxVx(8>8PLOR^P>e%zyTGpLRPO4{+H z%Ziaqni|X zeG=)Hb-)SfLoh(JKtkVDEC~*B{e}KfKGOc(&BK>Q%7Mn953Hn0b1azz$nV^w2B@+) zrlMJ^RQ;dW&M;If3Zrh$xJN0w{6o`CGRYp+7Rg+;Xu$c{iJ)Za#c5Gk%X@^fH0ORe ztsA|n&*Y$O+2X4PH@jDe9B><>4@MH#OaHP_HgE6M&GO*fV)Uo%yJHa{Ht|*ExV=Pn5yoJoyUD*^oTQ7A z2z@_|vG2~Fm=_+RaJ}@I&N{C;2bmiEAzt7yo;%YNI50Z&K-hBN07-E^os)R$@srB*5j@&%fejbRxNluzOHQWv< z)&UFd0evC&`K_l-ExHb|n|V%s^d83N!c{*Fv#r=W!LKee#1Ua{(a);}*zr?nJbW$rS)DucBxYpDI+&={IbR$Pwmz>oy zhqJ|#xt;PnO@t);+%g^Xd>bn#Zbt+^1~_N3{v|o>+6)!VOjUF;#V-DIK~AqPt?h^y zbIs1O(4k4!i2I{Sy1OgCP5zCgLk#;&*OT;%Q;=$d^d>UvL0nlm$IP0=|AJ3 zfaU)7o32hZUAvkPy*iD1vC23jT^CFXPIxoqQzgG~orYIPl%;2R!^i_tISF1jNR5lj z&TT++j$w=p)!YkG&0fAqv}1og^04`fMJKsR&h9=)BDTO@rD(_r;iDHOo-S84i@6Sh z1RYYgD$3^OX1mv+9`sG>|GS`8B^4LGwDTumiY`4X&FbTe9!sL$xcGtc%#6qS8qVr z53`5kx(8Na7Wq&@bU)12v|*o>jE@vKh<{L486bWy=w54e4n&gfjwb60lJ`W)gO`TRv2GV(@S?dtKz z&x*~ri2B@wwdqRN;``!#-IyPbo~05Xd=~fD>17ew&)Qly3i;6Vy}~G<$nV?mlPVAL z!n1eld@O3dP9FW4qGR9m>je!Lg6r7$5hjLWxoQo<i7~N!?{5 z9WG4=(G3jVl?!6Vx^N824xtes-+a2vvU-nzr);S;6utP?fgPq@#msF)0EDI}cNMDs z+H|qKy_oW9B8Abp*-D878`}^2T~*>~p~kx{X&1iA;R?IS77j6=Cy_&rVgERHsI~k; zh$6`u*D+$008Y*)7J{hI z)g>%0Iq>ZZjkv^C+cG;f zsQ%QNGwPesY-q05IGXO*h+2R|9DM3*esidwep`8eFoq^iJSa*; za-w~qoTyD(#jDNJXCF(~TUQyRt61eCg+uOh=Ax%N=>{>-Wg4sK*i2LlGHttpg*IJj zCYc8+u$D%aB9;>Edm2G)3P0#MNkkw=llS!39aQ|BlrwZ{x_KE6qp9jQ=;nsIF{jFu zYQ6nSfzGMEQAUZ*s}87)l&e_eUCLG`YcOws7+=@W+!>p`P{$W=hJvENQSc$QB9?8= z`S<3`6LTvkYpVBzsfrp#AIUms*Ol8N1Z1K>>--hxkFBqGiP%ursM;S4L5Uj=6Jpcf#W7%d$L1jn(MN^7+Eb zN^ZURQFc$g`8NMBsrlNXCE)?73mt#KLvLy;ngeg$`YLDRE3&G3U5);-aF_d>y?*1! z-AZE6`N}en6oeyP*7la** zJ^dxYaMf`W_+L2x4^Inb$9tX~DTIZ{z`#ICLoqZy`pmnvt-hxtvG6S&DJ>~ER{6B)aweLF}HG8rc&9|nQ=Rbw0jd7V8J_vttj@{a@sITSyhVTvpZT?bMuqtm)_4xL{M$@tc_Q5}o<=#uz7ZiRo zub-C8hr%ik`df`}lMp*)@v8BR;iAl$(l3$aAQe zL`9A>1%Nky=3`il1S1U-_x4)dR!-HKY237Kq)i`4p1a2_AWzTJd9}3`8fld0>!Z|#cvhhfj|m!8YXoSg2Gjq5i$nzzg&dE>M^alu!`d&1@O@W+f!{rO z+wbKtQ&!sdUkbFyMi+;XdapNkegE8vd|+Yb8LVL3rl5ppA)gWbZHR62$pMqQ*h4L zcc0~G6^Uv)tbE2Faq)3EXU)n;T#|wI!eUj@9Ae$0ShfC2smR!9bxpG~yu(X!c+#U& z=RRo!0jrsbI1_fY<@@QYkr$}DlsU+}iKmc7{{dW7TP$kp;6_OLeNcg8cFM{#P6F3tQj5>T5S1eIqnH#%?xJdJ_7U2L&xi}s?l1HG?Uc}hVpmq? zACig2P%L!dd24}+isQb?q=^cl_MaQH%1KbyL*tGDit0)o$56W{QS@sio<~lI90yaO zP8-5a@S!gWwtYrPv!FW9yI9^jMsy=eR!u>Y_;`~-(V5tN*Zv)_x-LW>`mH4ZkE?nJ z$?e#2r~pE0PvVv>I~MV{>6lwdQnj;4!CyD*q2zIMV%d0I4Esbh>4o$g6o@HFY@qOxscgu9JVp$2q)FWS53 z?ZE+ez_5nMe{X_eZEH zt9P%{%JnS_H}t^}$2LQ43dFZ1gz1iBH;8_JwJGpf9w5{#sM{c+#Pv>psqQi!paj#q zZ});IrVWlf94yHFRSt9fnwbfVH8bw7M23 z-zv9}I*M*lezO#nSEnhwTV-O$d0Uzm=8F}f)kkShh0o+iBYK}{2T5Q<*R*FmH9}f^ z5#&^Hpn+M#UBNG+DvQjs`@mK#W7QJV3A0<6D_G+^@5esoq0EqBntr3<`QpCyL$e$~ z+5#<7GP@+)<3okMSn4aj(Y018-sd6*?Kmc5kz=xb3yZz3kZU?H}V0;XHsWm_{aNfqLk6~+7r%d(=~^DW zJ?=}AErfjKO`dwC$%Q*mM1Wv)Uz^Ci|6aP9Nhz3D z;O1N_9SbYXt}p>UeB4hkg-ED?K_6~Od~&5U9)ptSkBefB&lKx-hLN=VyRJ&9RdI|C zZ+3}Luo{&r!<(5>n>aM$EDzRG%suQ8;lWESNSDaCkI~PTj@Wc%y}rhWD5RK70$nKZ z_v@}U-hxl8(H!bP`xejv#Z90GW@##mms4=4AbL?){*hZ=g560gq zx@ipwevsXQDBLF_enig@bD~q(Q+ncWaG2>xqpi@_2Eq2$XGFBnuZ{zn-9|y>2mKyP zfC(m|ZlyxagBK@;dl!)Obb}FlzfkW2#zl}0G?!#D)} z@qfR_CV6ce?S8(5{UvT>#uBIu(=BXf*K5b{9vM*8d}T^i#qz8RgVZ}n&vaAFrD>9; zq;FbIX-VxmU|wVoxo>q#xDI-#KX4#~aPH!v-s#k~u)9H9>zqknTTw;pB}A88XtFtY zBY$bCS0k`7I@2@SSjozv$;8R|aEhqd<%m zj7N&j;q_!3>2Y91 z$XG@A^T7o0LqL$r5@?>*=wW_$Bmwj1Knio@>PlF6w|w4y5o~P(9S@*YJU}{ha>DyK zq&YLA2~;$J7d_DS0wcXxNe zFMTeVkIE!1>SW!n^}@y#FTT#)+QSRG>Fn&|_8(qtwgfdbOGgI^9%_lfgBwxi(HEx= zJpsMD)TLV3sgHXQ3iVevG>IdPRJkGU_ccCPYj>P4^oOj82iZp7Z@t44!HG|C@D+9) zDHG!N^Qy5aXY4F7E$+T?zr2#sCGtKawW&XspYLUG&SgYNCZyI!Wt4r0X?3AW@tE&3 zKvb68V&F?9GNBeLv&<97Z*#Xpg{+|8>Tc6PVXCi_3nrd$MMKg&--n`E3YQkrf7`ri zxIRf&7N(L=k9AeDXv53G*^8YoX*AL7i96P6xG$LItmj#i->0FCScB#%Cr>Iy>q0Z3 z?v>}E5j@p>pQW&e^!xquaODtb$4M7p9YwRuh0dnXn6*@KcmZ^Se+u*OuAI&epRYPa zf?uQLh?y`d=~;=8%TE)`b;^j;n2>74pWB@{q`R*L@8zv3i!$J-Rb7DwT+IBWm^DC) zewMm$-nn?*@y6b00U39Eq?9QPenZKbWxB&(F2^0o{rK-MAwpS@MLj*)}9f z8e+xTKaVxnih^-1UT!(~G{^yA0?QFa6_ITTN2gaZO-M}+p;dFOB1}&kZZib8xyH*z z8F%?7&^(j^haqMlO~%#LWGxmE4W9k@XLjCNanpRp-4s@6-h^S-kz=A+gR}DD(<1hd z5%q##1?kf=ah$Hd>i1$6?X0O+OW9}o zUm#$EP4(d5MBtG2cxmKklBflEedPW`d$PoQAypXE=~UWwQ`z@D? zB<7KWrS|Cx2&A1XopJqEv)jnEL*hqQ#bnb(_Rg{!GAG24ig14p9y~$xOy9`Ym0zWi ze;#Ft4YWY@H+5{rGXvLD)q|MNARifFXt(1= z2oI2Oy!!seFqru#3I~P3ky|4%JY_p4!$w@q9<*PXW-Wu6dTIDr7S6jO^p+HO7CN#f zByi=zTB3()*~o(im>*^XREhDQR@x?&6T`XUDb#?2B@fX7DIURDtoen7Oc7s4f`Ow_ zjsk&c92ZeFEbX*6Jrr@wEy#kh-&)^y6vZ1|Ue^q@o*>l!`_s=bH5D{f4g=y51oE^v zIi(jn?XD8~>Xlu!6s)26)r0(RCtsDk`$=>%k0I>{5q}z?mLluI>cjEsjFm8nw@XK@pI>rz z&x65a99-OnmKNaF%_}4nE#~vv0<4(jc;w{gPsreu5`o48^dXh0BLoT!b01re6kolZ zIs+-?t#aw3_zQZN4_HhCP6~H_+xkFNGz=E+8|v%ffRh9Yr8H5N7G7SuMlZpTec;8s z{$ox6FB0^Nz~$=n=EC7_Un692ZLQ#En~h%CeIvl>8y-_S0`5Rx8Bww74zTs_9 z{cjhl-*;_W#Q!aZpmjn)%uz6nM{%*bLN&HXwf9TE>QeoOxor&8-+7bqo(MlXr>ZbG zmCmKbdXkvBx5oKBfWpNey!0bYS^vU~L`EAVG;xURNmZQf_FpE&B3dFXx6fpVmz3MW zx*?V{Xi=-rv&0iT@J5N-iG1lWXZU3H-h3u)w^Tkvl#Q?wikPzE$Ps`IwaMa1)=Bnn zzx`y6@G59+e_W>Z+}x(OCv1f)9_y$f40k{i*s z_h7**Xs`13S4^FnqC4obF%zU<`o6WG!mPjIxOsXnL5}KXOpNWZGU_MdiA^Kjg%k9$%d_pvd4%1K`rZ&6?T96O6v8(DD<5e0qx=3ORH9%p1^lfDdwP)8*F-jRZ8Bc zPa{D64sKwe0w2y7_4X~k-7eU#1a|ikxw%x}f?eO+Lj${(V1EB!khcQU2a`Do<(KDI`P+Y&Y`>3L?v* z0evi3)x4{}KgO8bV}U~<(xtydKZs14tELHw;FU1K#9VU^i)m6j+sMs z2Hj;#H&M~mDiMtn@ffwjl|u|Qy%}KQnC}s1yj8!-kGEPHWgL4{`3}E}qN~9RJT?}1 zcAcqcr69;E!?cDq*ZV5@Gv`M!%Q7uRWc1Mli(4=wJM>gWrnJ%oHA)=EJMJ+2D$d=~ zhd}+p)lP&UG(B!mP)FBiMUAllUx^|XVSLO&-=teTechtqO|3%DF_r+18n3E2R^Jz>S%7iLN908jC9J8EHt0*dkjx6k zJ$UuJFyw(9_w}hMovVF|5jfL8)p8>n3|s#91w#7%DsaUh_r%LFFp|wHd|W{@a4|VmfY>$o+A6(=S97s z>;hAPppzIFkO8YUu3u(WSAm75tGj!cdj}RsWFjK5v9ai2F9(#(X+`C#F{FO70s$u=@YSGt;qjfin|BEgcjU&jGW-Omjb#jmF19bNy)e!Dc^bTC zSzTq%G_hwqc?l`F8K>xr~22DS@Wf{A|18!=foM`k&)ZMkMX^1q z^T!z&6QOvJaDwYD_|S$Zai!CBCx%Z)+|v&Gr&M9D2$-)^7eb!Ko3UVpp49FfILf~k zgpzlZ3`_b_{@OcP*fxE_pm<9*U(3K+Tv>V8EW1e_^E=B)ri}?N0#5{A*6J8{#@)yF zbX5J@+bm=3%t{Z}{upiis#Gl_5mAUcCGEm5U&UYSSVzH?iv?p$FLxIHq=Wk`|H0QF zA!MWvtlxusA8hFYbTwP`g{;wA&WAsLw0`gaMBRitT8Ev<14)n^8=NCZuQW&g)GeX! z0=&mw@_kd2z+)!?wyA+KqD+TLulH>C|K_$%ztP>fmyYFG39O?as?6Bcfo}Nc&*8m2 z)`x?-2aL<#%W`1Hw-6>>2F1A~qG%hk-@K47?Y1>79obaaS3w)Ys)6{IGZ@n~-? zTs%AoFZ@l}lZgVU5V_$ij3ZqGD<&_lThLD3bXxV#jT47 zg{?vExw0lzor=HoiybbN?wIAeKF6f+nu!qISkk`|>#So)>R#xWHC{#8zxvnm6SY&v zFlW_icTHFxsT+~;B#V4&&+E(3RQGe|-;3d~wdK8o!O{=J8I1M;Dpr!4|I|hCu;?d> z<#5JZ9M}y0d=wGZ|C}%sLbRtWnvvr%=|fv7wfXLk(48s#)u0%vI7F1dBQh8bvQ0^( z>0(~njJK}AG2aeNjNMZ2Cj1FD-{@&1lDatqJAqO$n+-Eth;jLez4%;8VA%*yw_MhFofnivYO13lh zPE~c@$X~n^R8#S%p184~)JapTjJW3~iwXssf~xG1s?Xw8Mc+L1N|rQ{l^i|g-zRdf zz~T>8ewM4wkgJY7B}))$`5=NJ5f;ROu)|WU&55V_6|LL({*Q4hvHyq`l;Mi*r#=HA zL2eG-g%Vo&1s5IF*%H0rn|`q@IO$Ui76Gm+3UZU~OSwAi{1Is(`9QQWN)r6vxij*yL$bEE22T$VG>EIWH#6amshOD- zc)GK*Gw^ipCyR_~tel;3(zG5g8z8tVEGn9Ux8O$k>-gB($L9%v-5?f*Bw(8vlz8AH zut0+V$zIetvz|c!@BRJz*MbxUd~^*C=AQ2v)bMk6Cje#a$lhLg#E{$LD+jeJu#F@G zZ65gk8^)`6l|2^GC$iV{f$uLCHc>=2%9a5dWUsW{x+%=h(Q#G%gfaf@ZakiEoI7~u zES;?=aeMvXlap${YHO_m9f`ir(YkkVzF-+`5D*Ck@)P2|e{-Y5d&a@u8l)q^YX82$Y;AR#;GVBHbe8 zH+bwNXn|0*c2yr@DjfyLdlV6LnXGRLLp8bCqhXua1P3S5%Vb!|^V|39jTTO0oRrh} zm00i68+bHBqYp+{EsfzxM9120pK}ysDp(QqA>8_q0-c?TWCg5@bhi$3v)W(M7a2^U z)5^&B>@nM#oKRmf#9r-bkrG}FD#B)jZxYf;7+?N|A~L6b3Kd%`s(qM9!?_8g+@>^y zW6*nmO#jX7<-6YXaku!!*zK)>*mLMD+Kd@1Q#}@9hLr>!b2$S7C3dR* z^%UajRJtpYm4WBp4K}Vgc2;YavDVCfBxLeY4Cxq$2yijyWk(godW}$ z2wERiz|(99OKHQO;qIEzS$T`4+5M%%oyub+Kuf2W=CgPTw>yoW`&;+rWgx&+y_By|zNy1CfwoNlnkCS&CdwbEP;P{;Pc2 znUttvz&f|_NrLCU;yq6cs-=W=*X&49Ku|NYu<(H%5)|X0FRQMuwy?BBC@U)qZX|o$ z9F^@c%PbJcRkwcq8Vv|+fR_wDsXZ(LVG9!f&g6Rt9AJ=-s?4CvOyEmXF8wGM?~&-= zlL)XyP=kY6kL&3gy()02kvr$V0CzO^l0c{vy zLbUHJv-goUhHs;5VRl0A)qotx^9+83UfUu? zobt+)=eZTQd{jnfv@-aJsL0VyWLcDCBl0bAxd4={tKGQ!#)Wl$Inc;;j*D&S=}yq` z5PY{j!K2BRsmV#gYwSAl-NWw_Xvr9+T~T+D+$MZz)EMuWB;*@PdSp_^9OHbl=I1jrEj~5 zL9m==lu~&q;~u_bUV#jhW01k(*I-5{=nWXG|KeLGkN$tETOmZug9WwL~0>{k9Q%w%y+Fb4|B(l|2r8ZD++z- zsiig{C1tBkG}%XNj8yUmexGa;?ucea_=pY;e6V#G34+yasWya`5}EzSMW7xXk6mx# zX?OrdCWgN0ncgc4$DGM_c8`GiGR*QMeOGo6pRA4Zn+%&pgehtApfL&ZecT zU`Lshsk(?Qt4b>#yO;;SG-`hZdRAD^md5rR`4i825T_y0M0oN%=uVyo>}3M}bjrqr zlb|Dhm4}DtG28q1aHl4jgS6`9MGQjuk@*6}F%T<%ge@Oo_(wN8P%8uTTwZbU1mOJ% zfTFNTq;Uy({{)Xeda~YuzR^`QqcjYjuA(sD&-pF>KPuLX4 z{ZW~^V|UIQ44*y|f9$e>l73q35(+9RIQm^HS@ZAfeOb%C+JO`bI#vMpT7xS9cq>NR z7=n5144oy6e1$I};ANSc(>(HQprQvT-oKq!??4g$7PZTWgaNp52)h7VFMjE)({{t`a!G%1V9FD0Ni$Hbh9Z#txmw5*&-x_29z4$QJ_wG zyx;Ebx+9i~0BMo&eLS)z((awGloa6L6CfMyhT81iCy=ZUk%fQooWHF0-+aOG_VI4$ zX^9+PM01Y}EI6Saz1m`YSde#Oscl17h599=?6MTK7>Sb8lFK)8qLua52kh{m;nO(V%|!l9w3eB>94@8{;fJD< z7G9LTM<2wgcldazZ?;4dF^39bj6AQ{^^`9XIWk*OYY&k!q;O0YWQu3xtLEjG?1mhg z2gtebc+Lw85T?(Gn>np;Wx{R~@}8ssmGxm8H&3gz zF1Yl=IWo}!)dYV!LewicS__AQoAiPxE%SEnHQ_-!az2p^C^P^cY{_S-S`2>~}i992Dce&c_P`9Ga&n*NDcd zK8@V5e(b90LOS(K)cU2!e0s0wImy^zCpQqUa&vQ|tC5c==h$cYZ=JpeO_+!2!rYEy z7aUs1LBfy+Q{=PEHO&+w`e&LS^pz3kZ1dqqFhpqj}#5xLW|~ z^;W$Myq-`%RD$d|(CP$mVt|!_Cgjm>10;7lJMzE zzT^WUV?4n14WJ0uBzQ6sAHLdwL=KQL0CS56Uf}_hBZ)?86qF}`C@SS?G#Hd8o+rcO z9Ez%Y@#$4lyVosAD=zNocKGe0f%(wz=d`|r?@wWS$3tL7>+1O5<-a%SExL}!zbt%x zNwXcFH5d7!=BLWK9pd*RM2{3#S?aRLAm~;gX+pwbq^adWNa#8}Zn*>-b)>fVuS!hW$gG1?8VlXbJ zpdlR1FR+VB*(=^p646p>1Ep<@n@D*Ifj0g~>>RdH4xfUDd-^Z>)0L>C>_{-BC_L3g z&JgO6tW5;_(bn0BEVv&2hLtc4ejAC-<8-GXkWNE=hVs_tXmAiglCnfvhqw~%=vtbS zFl60(kST!DPTjuQZ(ZAmJt{3@Vf4X;PZ~SRyPQ^#3p2xJsF71Tca zk?K=J%+m>Jvgk=Rtteu~OMW1eWw|7&)1uXCvTT7;sWZ`NF>Nt|uzk>tJh!EfUm93{ zzJiq!`HqcZ?x_rR97roePc2A$y~1p=-P0pG!7zeuXkC(L*k#0IxJ;?hGo9m`3z-T! z%ct0mv?YSlpV5@n6WJu2rgbhDQ z`|SUbu=+h^X^GA{tW9rd-(UcS!Q+^Fv4>yC!gN@Pz)GPE+jD>_ac8EIptU-IcJoFA z%1;J3?(A~YAW6)TKY+vr2Zc{u9BaYr5lb3!qwKz12>>KyBkzMcD ztPF9^Zijfpq0UqngLs9f+LwXPO7c0(=~- z!dDonmwnY5;d}){7}?Zg6+ny;;O9>OvgPaZe;gd09M>*p>Hm~MZ*FdrC%1Ve#KOfc ze;0atN4=@x`q}P=7!(vVd#jB)do1hhNYlsPoE;yv3;i7W2^~$S82y7V!Zti~x-JzC z4^=`$DJs#HQyi9>1kL zdZ^92dbJ7EH?2pAYW9lpq;kwFMf@TpOh_n#78vu-3+9OJbu80?Grf74&LE5s{t23_ zLRTY&=lJk z4_vaT4uR1Giv~RSGA}-JQXA8Dat2NC5TQ4As2Acz(4Z2;C-wv5Z*Py-#fX%>^iRYP z@-O)jl5_a^&R#Ij$zKV7I`CB6(YmmTektS+$Au3sAPgS(Y@p~@#<4hyRjO$Ug=o&- z!l+&|g%|uMR2frZLYOh}s+r;XN6--gqd@fpw~^iFTArtY3&d5G%aJ#ZB(c+n7owo+ zf=J=tf~gUcg%N=M0wK@hDtIAd-JAXQo`6F09lWx3Rp!)fxhr=Ddg4#)PNqzUDtf0OAwK=~;oBe&18H z_4kM$G8_z~fbRyLjywT30HAmP%G^wpb>G2!uJWIS<(iBED-vJB87tTMmH0LBJaSES%i z0XN*oS4}|TQWo4F5DRbb$IAwM$DOU`qckiWsz_ocBfE7T|`L8LVPC=4l?J7dwKSP3Go%OvDSDASC*S%~)8 z5GH}m#y)F#OFRsLJzDgMm}x6Ghtiq6krc|5wM8xB zj&LvZn+I@6{weKL$nNvJh`rGL?-3^}7R>J7dH~X4zc9usljRd$&Hj1X>q?a+&P|eZ!7!>Z!w~+RUl^D(jVJuZ})4;K6LsTEdvZyARP@)np*VTQXrB|j0z{a`nK8R`EWsN(>#QDENf1F7v&D;Gku z0Wyo;yHUy8!hMrk^f!eUEb_D0j~uCa@HLb3&vrT)`Gskrnji!Y&)2CI*uUK=B$F1JvGEAdx=48mYtSBeLO1FEFD65;jOi2AqSuSTCCl z!M@HT0n^uK&TbB7kxw6Pj~{0iCSPewo?`9-k9%qetGxviu0C;QA@$7f${3I8OvPHZ3O83LT53XTrOW7l%v8 zt?|#E004Ze+|Z{_*kmtChpg?M`8@{Yw!7iCe3-Q@KN-yy%B_9d5&)Xl`5k8X(8N&` z>s5PnIIX;2ktgL#415Eu^0PJ=74>Q6^KJL5ldl@}EuB%RXCB>VrbDofunN`DXzK*T zr>ejIIte(3P#Dn5#2&(hxPfYPyP~n{tQ~9uQW$l-O6<#nX`qDkYke>({rO&7JsItR zWXtDmBuP$Y8Ch;AktevR@Ay^`Gx&I5pHYw!-AEx=8@8>P7JTqxsKpDhq6e)2S+p2b z*i_rog3yf_tiN@wYT2qPj6;oRSc8_KNCmTL=-mLsSD)MtNDHRs|5JZeQ)Tq6>CAsAdi!l3O zc}1Hx%#p;h$2W-%8N}jB6&xQ0Umf#hoV_{^-HT^@(kkC}5q;?bm9 zc+nd2<~u9(#cvX2dqkbz0#<|r#oss^og)5D=GJGOCHlW5Bt7U)=BS;0%bDKIlHBvf zVpGlH_j^Yk5?7Y+{QsNO_I#cH4^h`0PUYYK&#_llLbkF(R+7C{MnYuo$Vl1QTZpLa zQC4JxkiD}LBCVtzP~-!^?R=Vc)rQu+~>aE0oMN|81OBM0s*1>PfOl9M-|@LCnc5D+7vLEM51Zltz^!|A#iqv_I8owtTT*#$Jy+7&4{%`PG;3Q1#!Vh!?svYGg&>{ljBxw*_{Vs~Qy z`C*(d`{m`aIs{S@7`otSQty)x5q0$Px4{Jcrt=ZVg~Z;jhOQCnJJyGeBeqDoedWF#7moR7 z9$tq&tBk%U5K<(`@ghOd@}-Ty#>T>U$V30@fkjwa&WR~^(ozgOcK7z(a(+rz%25VKXeTN4)VLhwo^kzjl0sAJwCtHc z?dJVF))yHatV%Xw4EJVK1fN;XG+clCM%}&k#h2G=TD7yrN`fRa2VyC04=#n~IBLok zj{I;BDSEnonyd0Q(8=^ghM;KTc#-EwCetk(O2WL{Q3+~!58v%bG-lLW8+`qneo7ux zic<{i2J@Za=|2sHhp23j~-77*01ePIg3ritr75@ z7)sDh?o?{#j4NNJye<{LNAM#iXxW(na=dOW{sw8z%gjJbI(h~(FAoAfq7VJoBJSUt z*#%|W=t$Gn3MUAB)aW@e1yL(+!@^h>^6vlIU%k(|5(K%~*6~Mt5`3YVa~Bg*{5)hF z`O#NJPUcNtka6cP*5Apu#z;9{$2KYmqG4W~Vdltg>i3Yv=fK!{O3qk|9Y+#F^Csw` z_{RRtKo$$jv@hL{N;mtX@Q*RQa?kr1 z3-)pv{|kZFP8>43zJ_Mgusw5lTAAR@q)qmq|6Q_+aq^U>lhkeBi0AH`q87|`LSJhH z6o@56X0(oLuMF+pT-TyE(4C@O_cEl8b1q=tJ^%1?5c})pl-fRgy!@bO+p?Nax}+09 zE#@h$#D?o?|5@iD3OLmkuj865Y7!7=WJpf#o;^9CgLV$V{-FOu8t2)WB&ZK(go&Z< z;V~zqrrwcEjqmIyAtrwGJ_Xu2=t7ij@9_UEwxb1{2qOR4+1YiBjBW!_1mY2p+G6DZ z2n6Wc-K+;psHFG{m8!IH)(|GzB*1M?vv={dmWa;aw+=qJ@K4pIgulo61ot(`5>~6> zer#@QL%8JEy^A1~Hr1und2MwBlB{~;q9ITNe`sw5@EE3b*hct)I(Mv!fOP?vgdy!= zKBOg^0NWm`q~IaR2x`lPu6X42U>AlEZWuOTz63np;w;mw7_Y0OQREKTsNlumjTYC{ zy#mb^tPZdOyS-$fzn%ZP0H zyX5M$urqo`%tb%=^z@lIz=;pa+;=Vzqf*SDc+m~MA*1`VX6kK@SyNM!Kt~&GQ%~Bm zbR@r3m&(3bwCE0O7^00?e$K(eYeCMZhCx0|knqA^lXK1UCl0BQ#n@eJC14CqhU@dR z4|)m2(8UsOG%w`ciB~k$k?H4`Yc#tm`jZ4pdIT%oKO<4iFIqaMz_~=6ti!9Ckt$`??ALS>Dj<@WezbC_jNd z{5x4k*t>1-<`xP%BWQJV+6_mSAhsXL=7$**b|w{7RYV~q16m^ZNT|&b86JEduoiB> z<~RpQ|FEIGxs(N&>L8c^Q4h#eWeXn4kF!4l@<7Sn?+I^E`%BSDE%|Kq2 zELNjqY}nkbhb^s^WAO}VOWPdm1&oR|l`30qG2*3u*$2FXc zm~V8_vISfewf|Hot>fb<;~#apXpI=SEuEvre+HYt=l|=Foe^#Ke#z%QvLX7tdRu zh#>-M1jd9ffv&FceAoBXczA3~4w|!c-Js13)Lht`Jc#nSuC)&9?DA9khI_Au{Y9j) zyFIt@zUeq=dfWni1V zk|(HsN=*`HCxdP?y!Q}|K~N|?M(T0x=$Yw;QczsN^M|}M(?KDgET-jr8EY|1#;s#j z;s<=ueho9Xg4a+AyhcM3rHKs#d>`VITm6f2M$C4r4xx9;xyj?gPxx(oXiz=^o6dRxN~Ve&ZM@KUsti;k zZFe@`tsL7@F437!{iDO38H`A z|Hge9>EQBlgEO{R&&O1X`I{S%B!FKbPG0D6$Z-&7d(X}(LBxb@P81y-{oe=PE_J3Z zYkY~gRNDC}IZ&^xkyG2^hxJF^^gc)%0;N0%>k$>^e^p^cy8-kItvfr;EyjA-Egnxl zrh5L*W}xeep~+fw^jckNTkgft#-P~6mE+<`r68;o1qO6GhJgk~3@#2Izv#=sg6p4n zip;!S=x_aObZUX!)&r&9dXEyT#B-hG7k95X*6GH~|g1SerkyEuVW z7{>7+RXWSmT%UGpJYK!Gr7T8A(B(SGi^nwh>|COG#Z(RqBBZ!TAK>T3C4AOQ^ZXxshd>^v_mG%T>7n7~U7L-ee3QAB zy18ZHi@IrU^{f{CKJ^Q-Vvd36f(J^bq!`IbOvKGidpv)A4_S}471UJuo&!#Qs?aDn z&v`q8jo`1qSv3K5zPWn(-X#kFOpvk-y@4YO`N$B&8=6mm#!FC~2uB72>ji9chnJ#F z-SU{`xrO5;_A9$wE6`VTQ(=GxIXNy0o~~(t_P#exH)f+?~OVDygBNGvEDa*SDx zS-#hGogoIYt^limbrd$iH!K9e7bL2%9es}BY+x$(kJJ~w15?F73zku>&#S>Y3GOwajJc)zb-%}7p(UPnwdT=(me^?88NcoH;MS#i;?Ill5HDcgQ0&b44TAL4uaoMM32q4&h7sLuL)dMsw{V?VCv zn83cx)n^(IK~%rKy<={CYwCBkM|AaJZdp5|L5W~7x7^R}rjBUrO5ots?m3N34$8}y z&a7ka@ru3){%50o0o<3QUL0{j)%VQC4|GrYi7r}q-EQM+qKzMRJ0vhpq;wqc!+(*e zU-5d4H&}v`eDC;V;M$CiFrBzd(pYCNv(YrmB-JnSD^&(%daZEQ#@1o2cpPH50o)1T zB@82a+12)ZIrBOOtV~jd0gy&L%%6dC(*S3HX$EF$8Q{MZVGwPHB*cKMtgKKs?kcG} z{{~F?p~z2_)~P8eX&`L|S_aO_>Sc4mDWCJF{f>Hx8=7FaW?A~fZhClaz0!L{`Qbp~ zl<;8T(KOkJRV(HrP-2zaJ;!cxU@|!UMBv=|cy2}dJOYMkcnF{mfl(B|@+(~yh{8)q zi1M$o_<+UawJU?UHhra4+-+^Q`EN)BXO3QrGv-O#teLuE_YnXzB}`0Y$)D}F756&A zVr)2$4NwQL4eOltl0vvAO?ZL<@&L+b31K-Y0d1 z$xz(iTe$7ZQ|71<;h71o_JFOeP$JQo$4BqYB;DS|(W;;u3=UYID~fQS++IJ4awv3` zPw!?7iY5rsXl*~F;auQx$^Sh)_Y8YGRIl;wM@pqr1*40K7_m{?kxjx^f;1<`?C*hu z{TB6OzMMYyBJ@5kX~e!NTZV^;FUhpV`t%J8Kc>I!n)m)tr?~aFeK5rL6(jb`#}|&B zGm#J*5PuRCgJV4ZW_|xXb7K_SrQiG)(c0d7)jtl#R1(fK1)e|WGJd4yft|97Gdbx> zN>vfCC>rMN^G9?be$_QU+2}N99piNynq>3%e&^z*-RivPTH)BY&%(w(Dp{8mnR269 zd`^ToJeFgQys640woo{@-j+Ry=hl6T<{47oP8FRn?0*NJo^-$fWr_1Uy*24Pf?~~B zoHzDytmrh^oK&;)Xt^4w)X-K#s`fi4ml^z<0|>i>_$;RUW4jNO%*&E*SC(Kz-z7sa zYZj7S48JO3j$%!p&hGlA!|dothYKnIs3{qrg^1+zoI@R4c^NGxFytBM@{97NBInXT zEHP-q49Z^vo~{zS{MU%0n+>z8q`p*A|6g{V)Ny1Iu>|lyM)h7{APFQQCN_iZ3jFtP zT5KI|xq%bL%?%HQsA?Vw^v#cI2lc(e`vbf4bAf@Xwz=(=eaI!WjZa0$48KTNW^% zIy(z`edhEgmeoAhBNtF4NGK0$N=J_;CAUug6?)HG+tRZoppi)QV+i-^I~jLpiooV( zx3bF6;2~vzujF&pu(DoEDH3={*K(DeJY{ky3ULD7Db%W_gvw-(cR+JKgIkrlnMLT## z57sTVN+k+02aoQ&qhOZVYIl=vEDE!22=UJ#7Q0zPQOLu}6uO(Tj-5QqrZUySt~PO2 zBkb3gx_ne@gdI@RWLfuj5{IYtUC8rd;yDWaI=0%P89I7=vR)1f?GXK+Xrh1hIh}N2oTR`?_Kca*-dLMtuVAs{E~HR)r|k(P%g(hD4#PO zkF!OB_3o4Fj<4j8Zf%(IW5a27q)JWKu%$8S@z9TFwiITcH_BK6orGRoIaQ*#s#C#n zWGa(7b`@)Yi9;>mO&X)!fU5n*0lMDup4&LKzklDMdqOZBM>-!$jpm05iecMsiy9X% zJ#D~G=3YWe5Srkta3i%a;R+s$fa}nDz61V(L~r!xhr8D(rOZw;^)#3E&C;17OL54? zC{9TSM`i2S+a*eOJSz_*dX!lHx6ki2aX#(HQSSe% z;7@GT8lM+gM09Akro1p^Lk&FMDrL<#V{Bad7C9FrsnX=R@@mW>B~*6Afi984PlI!x z*OGcJrrV=kW?yPcoCK6R;Kz~YiEjoF49@*haZHo68VHH0ruY8!z)!erZr1(%&Ry~; z7elHT4V^gFE<^AQ)YnI9#x^X4 zk)=v(8&h;RzPe~dNkI*WFM{TT;gr4Gl8mDyKPse(=I^a4;onc)>66A+M>~+1q`MNI zdMe^gG<%|>UtZ|R_5E&$V{0R1i#EARuWYX-d$nX`^}+UMsvSK ze{zfmil46_;+VhH(sGXl-%8C{0-n2Gmi}tr01Ktou%{5oClDB)av$A=k2o4=?Gf<{P&Vf5igVStmO$fyVZlL6D zh^7D-1QDo!WB`7r7!AO4az`&IKLkY?cNYj^qNQ~kWWuvpzm5&L7*@r!l-t2sX8?0s z30@&#Gfhu-orYI~Tv!M)oZk#ntp|f3HzAOKqxQq)*Gs4JCc9^4t~NRfCBtS0`hv*0 z4ptucvSg_IDNv?h0PPq8)?`Oh1J`kdJh@VJ#|8JYnRS(Q($e~B^Lz_d+wD7>CnGmB ze?MiC5)7?Rm!TkVA5VY|6T)b6c!)tv67{3<36q7cq)w*%5zEC12Byo?L5r+QL19AR zcL@O03w{Q?*|}c@`Y_g;L?8>kr>7^<_*z@BQHYogl8u+v*KtwsaKq)D2B|#!hL-#E zbabFHAX})Pe7YkHlBAy>?<3|rm@cP5okO-7%ZQnl6Zp8S`PV(&kIe)VXRO3{InjdJ z*E1j9FwRet*OFh-{aj<1DMiWAr!BXns6F7}KzGMKjoInaMf;;tbV~DrfhEbh$kGMP zKY1(iF>BQ;9gHQDg>yH2FHQfD%FHXCGx?>(P`a|dg0)nGC$=k;Z6vj_^4{p>EUagx zEzci}wFOsNx=`ocU#icyv8!XGz-^rS8|`7nG|`_iv^Di~2wR;kX{Y?O(0_Jy{Jyi> znVpG+!PqZs!igT^3?83S&yC&!p4s=YieCGt`+na8>>D4UKKe{jMv=PtfA-t5ccH*W z$99(EbKr^h^jXri>^3G{|H8xj})?F;hh|3 zGT{yFj`H7Ay%N8hb`2P7s~Pmxgp#@`LlqnK=oqMpnn4k(Eb}6XuczE@-Vsqa13zvG z3=53zj^aK*zkoOeAy!77e3NvC+*1&|Wob0Qwh8(yuqsCWbKb+}D__r!btO+$m;Me= zY>3$*TmkU_11ycKlAt96s2o&j4B~En@w~>cFPJ`h#8T~{y6nUfNAaJ^)ewg>kL1UH zB55eREzn26^8dN6?!r&OtI`KxkN`FXfg3@r3UU)f&R;-@DBR%Z4GwA{zob!7SI-X+ zx`5^rX8#vnl8l%Aj0_A+02~Yt4+m|mZ2lkyGuA&@iH6HD08WSp3~pT%l4k(YT2m01 z!1Dx}IvrhIgctx4>c3+GZiRrzMokGwf`< z1OCxCJXXE1;@*X zZXOJ0DnH>7`D~}pQ%8nL;_c`9j&%Jilo`A;5DA z4j1G(gfGEc185iaCnTW?vZ&z6MO21R6?;>q+Chm6qpZr$7I+iyrF7fF@t9de9~v?g?*idbkQ8@f~?mE_ZlP=*+EX!p{8AA{3wh5;gvA$dU=+ zZgs*JC%QXlp^M<8arXy7t%lE|=l1 z`Z-ah*^0#4e(eOqJ0d4+(Tq~J{PxXN%^J8)(^rQNSo}`AQwb%!_b%g_HrWWRuwSrD z!6F!w=5EHv+t+^X*mHtyz$DyI+4y&oXYW>peQj~rT!CH6`g*3f>&rde3kBOZzVNKr z(_E;8N3zSr9_Olx7Ws3g&0hW>5z&OP+h?_rZ?=_H-03n~{1zN`9GF`11a@&$%UZ^{msP-~+qgSPQ;x?jJ3A?4wG zZ|aQpy@V%DR|(<)1KB3HL_3SiskK>LDgO0U4{>>yviEbsA$(+JKd=D8&#w9yS2 zl7K@($ArBQK{BD5{1e22ZegMS?e?}4w0GpG1XnerFC(iLlCksU3(I2xG@Sn~J8H() zhH%f|Rln2?#Q=E)kUhXDfh@->@KQ)j2za`@B%>e$g}43y1I~}%qK3x@`PnEGgz+Fb zC`FJ_2+s~sJSk2{S%vJi7!9wTzB?Lg+!S7-d_F&kGme-lxCt>aF%jqvunVwtAPLaL zVe0eSBJ)nVfQOrUIg+z4KGqo0A7-07@pKNV7w~O>wKsQm z;)9G4=qX@{kR%{vsQE8f;fAn?NE4N@mp^dn&3q7{^75bY>|dY*BF821J-{Rg4p5QJ z<(UGeOQV>V;_S*H48I`9M|2`ezYSOC!z0sBUw{i59v%JK(GmKkwV0a_&>*%@kR`1xCC()=|I>Fu}1(t0SXP{hOoFe!a2Zvgg#Kl zSI!~_LPMQ1)`OF1*Z(iPM2cFC`*t>+c&+W{I;x!TEVAr_-*|Ua4b}Y5edbXSzq_;z zPfyS3j#VA@hf7w~=e1g$D zcaaGPJ2+KvT<`)sbD(sa+bhuDprc~{$nLiL4XuLF?$r0B!d|^0$e~%DExHMgc!pL8 z^2~)BhB~DrMh0Ajs+qJl1rN5VL{H6c67w( z5kUlRi#_yeO3<9yjyKBfKwW1J?rGq#NB1re6VEo2NWm@Vwl$9r(}fp`2Cozv4w%D3 zAl?wTZ|LV@GD-iAU~zZl?21T8jdH{ks8)m!VQB$^R_r5ifcG%LJqp+_YI^$C0{sd;cq=j;`PxMrD}!7o-BTwQpbC60FUL{3 z=5xAgZ0_S@#ChRHA`v{80Ih>|XcKrlN-sPG$W+E?+ zYW=fre79`=m zv908lb?A`tG}e=iOo83}w)@DriWBOE7*f^3jkAy7zL0| zbt4?^@kEtu^Up>1Q^L^o|FjnHDS;d_YGh<262F|$$-Q`mccr?p7FQAoFDRi0OPNt1 z#DI((wDc%WoyV@yWIMuJ6n2lPA23XcX<@@4Y_9%8&fd`2irvnCGXFvh;REq5eE(AxpN;%2@^>gZkG zzq@f33X)E-H=}a&nQ4%C251*hJr{z;YpgzkN(3}5H4`{lf+Z{R!(m~Hn!D8xrLI2I zf{Ct21gweCM9(nxRO)w2)(0ZB0JKYoycMg)Aa#62Q#+rmXg zOmXle4Gs>58m3q$K@9wxxsT8$VG@C@>z~RV(Yzye+N7kfK)L{40cwyCMjsex`QfLS zgZT{x8u$Y~Q%JUKy~F4o1St_HI8Yh_|Cm4|1OqUFQ#bQ{$dNU0TAyuk{0DC{dN+RJ z5*Wxz&trdYN)28eB-b!IJNwb1!FUH(>`S@?NE3uV2ylSg1~ecdrWRXA5^_K=m)Wr8P~RT$8WNW=f9t^!^$Ee61La~Lpz45McdRp2wvK6JUF1(s(?8%xNwz`x5j(?NyJiOt6ko%ckrmJ&A!K-^jM8szH zR(Jz~{5Nj|J|7IU8SX7T9-36R#cR}P5#CqDzZSW`4Ry(0H9!}WR6u*Y~ba; zJX_5J9~CqmpwV}tFY&c*i$k9S>tx!0{s%>?jL{3gsUkrKUWeqqCv%J-+X7h(5|ahZ z!UV<|#HVy{;KqUcv-%rOhu$Kb0-Rf75g zLp4(HkPIPE+rW~Dd}DbzTP&W(6(zKZvofy3DWQV=_=oPOG8Ij!kEqY^@FOuHfB()N z9O%d@D_w(?7`_SVMZjPnp#sRLgcw3$n1vq<$zI}a8>kqKWtTNL7zt7;VdfQs1Ha|R zv@X8ETjInys;*c`CRXyr<6wIK9L6q06(lYm1YQjWhTByJaqX@!J;Ey?B@R|LP0mjI z-X}sxtSVyc`j?0Rl^Gl;{iz1QE)H>&oX!n^DsM0L7FSk=LY*3~a>4~@Xq}r+60Dj? z=LFAq%KP`T$aB-q=oIS|u`j80rUW@sD6edGx?E9SVkSnqYHA$cF}46wBENl8V4 zvUu2)@iA+^P1)z#+KBT_sWV(??WRby#MdaC_1SL)s>5NiOmLUOWQ5S6U|u0=evKcg zt*!mPU{KgoH#Z%SbDVx!g9uN%3)+jsDW)KbmAVJR()?}ndD1s?T`I!p%Xq|lo8i*I_ymhQygwWq zocegh_eQSQ%>oQ}mIr#nJMsCKW0kT**)&>?F+9SnL-nirFJutV)*_gmkx>SGqV?k> z_~ET0>*a5=li59r#3>v)m22*aI%Dn^Q%Z>XF7SWRau=~rLSat7Wx^L^@6S)b(^2uF zC1|%bf97-{Jc@Cq6E?8c=yqY>Q<|(m%!o2WBC?C#K^aj=)PDZta~*t*zvY;n zIp(|l?De+~G8Zl~N%N@TMMXt6I~nrzV&dVZQ$*OijR)F|+#R!a_l2zl#J44<;flca z1;XS|d>iv5w%IJUfI2W7Kz%?Nkj(@N@&0>Y1i{s;O_=r5x)TM36eQ>nr)rwS=2(?d zyBLZ;1gJ)?7v(~!oxbE^%Yor=$?nQWwtsn$i{p?gN}5{zA@)?4omrkU zMV?*T`EQWY9YdNiC=51bobgWywU(i!zzz&+4_!N=DjXh8po;)7__1zqRwFFj@L>aR z^SQW~S?2xw2?JvfpIF&~vA5s;*~7l8-k&*K9n#U)m8sH`DJ~*OA>AP%N>k%BwR=W# zKUJ!^!ydcJfD(KVD`ra3AD;6Eh8somnf+jmGifiAaySi@Q3Bw6kK8O<|Da<9^WmFM z4o*%F{!23hRU;C51ixnNJDaK+*7)OMoX;4d1W{XX&0yPCBzX+%DYQOFE`kyEzh@OX z7uJ8Sm`#%N4H5wLf>*0y&4iEZzaU<4b#{nWLDd);NlaM+w+f;}gpm_mo)97hDWjju z%7UTez^(}ce{raKJXHf>ea_0E;JpWW&+uZ?t!`vEdHMJdw>xZr9%cr>x7RjpNQ;6I z8u|=i0tW|kQJXU%j7qVe@6Hd~l+B;!!l5yIdfb#*6D_}fQ9@hWgni-e7^zlqpIz>L z6k0=*5PRn5`A4Z!eAr82p>2HTvrP+S_M7b*#EBw!At2x2v4dPjR|q-;#9<_k`8!2| zqp3@L9Y48synTU*(3eU`g4zCSiPDdE*9=Ouuw;U*l~H#7tkPRN!Ky}G1W`i z-QNdGHTTp+kn;h9@o$tm`_+c<$G1}q!>sNDeuE^z z))}=!tUi*A`Su8=ZD_1!78ckL&;jENq=tET&;VRConmfntvI=j&kT-DSPWqld!>@m z#)`hQc*pB6G;ky-4EA1_uV6de%QSdA@$FhqdbOFB1dsPu>33;VW0cXO4$&XK=BcQ( zwV+-5e9O5BHNDF*rZ+C`z3809tF)0|{!+_w5+}ovV}{#=k9n2uUPZ9BGNIc^Nbkn1 zu~hp}>7o@KL*}T}Y|$U zy!^p1O&Jx1ia-U~>zLeiAfdprBXApN;JyCj>8uDY@hFc$Z!@pYG3`!l7a!5ZAdN>D zefTqyFNnuQ8u6lgg0Or}ca%=J+WKttN%7}eKWL=vMv!V+l#URilPz>1PvT8)xR2~O zR*=;Vv+)7}bn%3jBDNf3H=yEh2oth(f;G(t^DR zK2tzEp$j;cm+BQDh-QGLDLTV7X{Tq`1!u!S`h^C9^U;=;>P(G(o!k==`t^%XR5H>a z7fUSq>&7t0FJoTwnFTJO&J@ZtWF+GQtu>^??8&u%)r~r+UrMuieESRUt~hiR__blu z|Dtz&glEt-&r*kqw6%nLBr$UJB*!PsAzFSN14SAwXEyBu;}txfcZFFf+@N&89<6cj zdfW+t#m6NzVi2V`J8R}q!bSo2Kb$yfQCB`@htMn#Ti(Cu2@3-79Ed?#r6rvtuKM1O z6CIb2?}y;93D_S%M!S5@7Gr9r!5iOY3cw)nASkf*L#i@3?O|<490%-QAd_zHi|F)4 zlShD8!pp(n7nd)E1k9eCPMu4f&H0{0IWC)|$gUga$nl$AeXrit)#bLcL zAnH66x(rN&kSb^nI86{KVu*wlM90Xe&G)SL{Bn_T19B(;_@eVMVOR#68?=-8w>l2% z6lpT^IHW7-t11Vl)I*=G2+dIWqgV0V4&kN)hzt=oLs5g{1e(IBc;U?Oi_7};ki^h% zw%X8!ENPH{h~%+D8G-HZwE=&lNW9JUwggRWcqdvDD^6_0cqa*II=)ZgKESs!Zt!^p z$9-y-IP_elR7mwXx+c7cbh-Ziw<-1~a7YM3Fd?%76nxkUVOA)aic|e~bwf!}O#Z=$_xMx7%;2?&6c4xQ>B#e?sB7#aBXAmnA zQ3T8y!ry2Y8FkL>ijyE-!7PoEvw_7Bw-=#jZ!2-bw>}jVK*S7yb6cL?LOD#)qyfkg zKOQ@H#@@TJDZ-byRA8KSSBDXO0m~aW!Ged;c5|t4%=(pb(<}`|No}}yufDXnRGWuE zw^{oMyc2*K|Nfm_>*^bE7VI%8KSr7NxOht%bq<>YRN6#m;aDYri{X!AJ`X7D@0u-Fv7zi0U26g z(}zS1*nOaIWd%q(58?ai0o&>57 z!PTI_fp`t+%Am!D6V^HD2mJjACNwXls$qkVAHr=+p?V;F8XynuuD6^^FcJf`3644> zQ~(u*%)6yzlQ=nDh5@6?2Rs7Ux6Y9GwaAY?w;lv_?YcTY1J{F$0>@#Ml2Z!n4qa*8luz+!hC}2gWA=ZII1!TU^|I3kxP9B=4}LB?v13 zu`NO}0t&Jdl*JPD3fPKp`+g5z5?`P7{!zjWN)d!}1sG_{hjlbNPmK!Sw)MjXeEyK) z4IKa>mS9N)+yV%6d5^?jHa8JUEmr<(!1Q*n)E&Tu-ibX2g+J_>!LZZ0r&63!Pe>gZ z+WKbjwurQ6-if+WzYQ1IQTDN!83rus0*_nZFXta^1DXRU6{6S$MA5P|3{YPn>;`Pg zI#&E(-TqWmgiM2$mIz9X6kuK5H$`Edt2NH+;mUlEsc~TcfOZ0m{q;36tV(gfe_;wj zCRNEtNPj=K7j3r&ES@VaSTcou(!Z#0R89) z2R9E9^!|do5%xmR@*?CR%mESn$dd;MBa}ASO`>hSA?LRMT_N^|3Cu@Jqobw*J+JxSf!JIPrw zvlR`e*CB%jxWVF*5)7qla5b++)2=%j>iwr4f)G{M=tN{PRnzc?XV@R?#>c-rrZp#m zeHKcWKy=l?6FApNS{jYGbT>kzPSB9<3{zx)brQKx*!ShHQCfA+YHgVx%4y|mfzwqs z{YQE&#fnz(71(Z;{f+YnA7wPbvj$jWBB^H1o@Rps%2DGSEDW%Yzzqlmx~=qaFU-aK zf`SyqM4nWCD5`h;;f6xCIx(?ufL(K4De~_EDJqTE1R*+zKNrNT$kzDhPe<4ol28Ry zKSCVB4*EZN3~-82n_vKhHQTyj3lXB{|@4=10Unq2dp6!gD=hA>- zY=wY^sgvD1E~DKWmBN&mxd!_Whz9{DDpHY zkl{`2%*^|VFJnk6UBR);Rg8@PjfOnv6@$>O9CH{DG zS6;~qgqKN4NtKQZ&^;sNufTmx19y0dt%mbG{33KnGqZ#Vd>hC>GAkdf75S)J)?AfG(t)RhLCM9%1#neJAQgcww78wlK>+M7 z>?G+NFS*|`fEGg_@zGF1=(AV-*tac<`#Kz-KaU?7(STV^rs?hj)Zr}zBfenjf}%2uQoStmBZt5g3nm)2kJBZ)3BF$Msd|YC@AWPG*<%-^Oq>T zi;5_)8~69cl(4+GeCY?C?mZ_$Kns?3x>D~1q^9Y=j8HyeTD;5Q}^ZM zFq=#^0$&yI77{id%vM+O6z2I!vz*PIg96sj&=3m){l`^IGW9-&aZ)xJafk)sJ`^o@ zG6g;WRP7*4M?P(5ZT;pCiD{cAXY7aiL_Rh$+!uFaR#sLXk+UW+2_?V!_3PpCu%WSW z)X(Kd?(T`O0px1W?|N(=dL5kl)Ee<#zkXf*3K>GVr$+7Vxvs3P_6fd1M07&Q_`$Nn zYp%;DqrZOL_V%tLGKjFNAPxzH#|>W%e}C6=|1aDIe!YvCxw-iHgD*2UzLb^CI96HN z*uW4FZotD{c3WRhkLAYk(eCQN&=A~)9~}HLI5cRxtvvP@={`UG7#-KfMkC8C)LMr=%lK$E!SqWFm#0-SC`o@WBgp%;n+^ZCeH-X%2^t3`&d!oj|8sC z%w%V?U3r5C;vPXEp%N(Gg{zM5a`L`G?Bk|e%3T&&fyDWp9Zi}WIDs;q0>yd-2VRl^ zO-wNNKu>mbbGs{$7*jBcp-CCcnE7xaRp0A?xvfYKv!A2M?BwcqUaak*4nZ>MFcWWr zpUOo;T>hR-9YU1;SYzc6%`_(7o-zlv4sNlxef4vjoLyI8yUL3Bwvz>3oF!UuL?}gt zO+-Y5IlA-iy(Lfv5E@|M;e43sb*FjZiy!7kEtWs1#6`!MnfU;z&brEuS zMc+wcp5fzTsYiVJWlrHY0GtbdayPJ7KYsjZg!cv0eN4aNU~n|an;D~gduDR^xf2TM z&r3w)6N(rHlt(YjA|l@18}y7@!a{VGbDJHMOVAoS-KhA($tsU|Nc{G_FE1$Cl=ah? zll3VufB8#K9I|6hI(L1CDL5izSnTJrAPh#x((d|LDA~f-H&v5UfhS(*d|{jXJz`DocRcDUC!ThyP%Vb_u{@;s3Bpg7*B~4mnVkHM zNRz;aL;j@b*WXi80?Ib0do3js6BF>pmE)?_1s=nX@shl6Xh`2=^4f%tBiu5ILBb3q ztVKiN?Q`kH#cxdb?iTBOC@fTMTe#h=hGx2*sh;b}7}b86k#P}n2m{un;@Sg>1Ajac zfMPHI`0+<>jF-hwtlql++4Zotu@RjsMQFHtmYDv2f6`z!(I|ZC=p> z14RkjHw!7A{o$4c=v1H^oh+W8q#hcd#h)vDsKiYP@PsmXWCjPE zECOI7?0aby74cAFp}&CK!PL_71($XqtS7pIl@^X{P3k2YAiJDl)g=;nMajZu0hH41g#LL0ZfNE$Tt2W{`wPmR;%^zx+ zn4=>Pkf34V1^L9{$%3ehCq5i5F%+v_mdmOiqt!TA^t)fBy()hB49gZPvm`xzhA8dH z0Q(agn=5q0sn+zj1eUoe35|;4k*5BGP)+ZrpogbtuOH{risJ}UpEBz}6xQh2SeAj` zT^86XY%n%Z@Q;<_dH6*|J$^ry*I@HABjXUEBZflO%W`|L!0LRo%dGgvWS{Dk5o6z+ z91JTXqvIbkYpCKU6d!9-<>qUX&zgbVOZ|lJ-n~0H8fvh7 z`ZQ97O^$?iC{!wyy;i?7= z8y&Iog(Xl8fdI+s$rBdxu)DXT`FzMxrhL>a6a22TD6UkWi8UZvXP-i-|yDX!{&c;WRWfJ$}yu z-mtzTHS;C!OyNr)*I;D4GR^ancu;TG%;1&cEA^vhH%n?6l}(qXx8#1s9D39jR#n)d zu~Ot6KI>sf*Bb45dgr7S_ci_$ZkwITIQ}~PoBLNqafiu35rva#gssb+00%F5^}8L# zp@+t&+)^#>9Mq?`og}ZCuu2wD8>=ULe#rjgkN z+K~<^&Bs4U&<0vjiIwc;+QDShH+#_Pf5?a)X0m=T&Ibx4V8Ruz-7+^lHf(2{EycISOK0TS6DUTY#Se;~9Hz(>7JHH& zY3PYZ5YOOOKdmf7F7k|^X!5wNM_)6n)0QpbiV8E+)G?GUMN263WfeNQPsUzuI~v== zH2fUZYZ}Wn%c|v!t)z6>PiR>h|HroyimD7*B`ya%x*Rq~Ho|xG?@s;{onK%)pC_ad z6DxMF<%k`Ymy2femUoWN@1q^c)0r@l@zek&5 z8Cl9$VppV#T6b~_cf!+tbwuPo<+_CLaT89Ul~wQ7$onO86Ju^LwJMIo$3@z}_C&q} zTy2wlY&S5t+vF>b_FEqx$)KsSo)G-{Inh0PgtJY%8gXA`nq<(tba>;?+u7wg|K^Fv zo4Y|(hwcGQD2AwGv%Zv4*A~4EkGh?mogc%)ZrLb|>HXv01Rj7FzO^*ZZBB0=KDuJ_ zs42W^)?Rp$?-}`RbLdtUqklrG(%Zx$|nsYca4IyP^6gFR3wm8Vv zEhi+rw*`gVQB^Lg12 zRbBw|HiE;u!yzUAqjFSQ<2ydOP)qrZW~s$>%5W8*6jgTO5IGE@j2{=H+D9fPSl`_3 z*p~ieeO1_tA-pv1>>z|qS>0QbwyZ7RzXrxVf0aHNSS6NMRx*&f9{7-t!Mqr8CLm+M z`X9{eL%Mb)*mR#w~Q9CFRM6Wn1A z0T`}te4M*%@)hj~hc!G}_PaX-?Jf$C2}=zdrl6xDA|Y|G+>{s~Ph<)#$q{ ze97Ig=97nE!S|DY7NEg=IsEYiSxJ11GO$_ndgj2kTES}Iz3w<7qKDTw5tRe=t0 ztn8MryvK$2LQ&hh{?vYi&sgv9FrYhwWj6cS7Ie-rAfPTMRg+VIw6Wa|g9)xFv zLr;V3sCfGs5pCE8@S?Fh{k(TN8$iAu@8Hj!ESH3Y$sVQQy3uXg$EP>8c1N72V3UF1 z6eXXwCJQ$;GMw$-CR@QN^DH5wPJ>9GT6RnR^7wIr9BBeQ*#M!?gvv>XYTvZ z_L6wJ@bhn(S66IfEk#AAF4YfOBC)t>)RH+7AUDWo=qISWglMVto!~wv(VI^e-l!p?g#dZz8X7R zVMy<*|82Ws?2#=U2U`^7-q$aI<#NW_d8A;M1LoO`Asf zjE_g=jTKggK6-5r&8@hDB*vR3Wywits)}DVO58lWv>&pj$G_=}>3gT3O3-G_X2j8W z*sx%pB+rtTr@#dElJ8piMH^)@yIw&TBBJL_ zx$xq}-TU`&^NVijY|K_$!SyUD6}F8s7Wgc}@CpWS=$rQUZOO3%nHIqm5A6m(H6L$3 z|FEh6t1RGRpSI>k$oo#^R8?~t8+I_b*?op<6y3iDcucMa6JBT+P+std#>U5~&sjzf z*X(#fkN7ER2C%Bml|vq%DoeY6JtOhgrPG;l7b)fWPxp1crvix!RHiwM&HN1wr7{Jy ztxK_pbL^Pf)IP(`_Y`(2|pfBE=pc+twHB?s!%d(&~H=}R|VJN4Dm+d;OR zhqsK`c3>dwYd|M*p^bhFE$Ws{9Td=s;g*iF}XMS zu4U=;JdMM9$&~3GvX~xH_k*b}XZz-?54l8Hg`~tKi>p>_L_@cDm(c!@-a6dAERa{S z=nGhs$0?g zRkH4J*x*{*uKkb6rEfou@W`GkLVDQd_9g&K8R~v$f{#WvJZY~c(#tK`W2?tU6gd@Q zD;&!+cQzZ;>|+(^w)khPKQ1i1sHu5kZS%I$)lETO!YTZ7Zbs~@Msi|xl!NtdiFf>s zo91ux1c^ILt1}Dq)r4M&kA)9s;_0i^i?+UfA#Ie&&^>9)zI^DGZIF%RugwxaPFy>; zN0{>cue6_TT$F`{1uYJGI^D?RWW>ULdPzz3j}UF{7>vN3^5^7h?r(_VzFAiO7@Z03 zwO;4-V$x&%3*?e23J)uADkq|ihbGpp2u=Jl&qiCGo-OKNVZ zYHi3vq$LfnXlfb&z6z=Wbe#b3{l2`0ADnV=;SN190uVK=#0~8NtmpI3x-LTl7^T6E zRB%o=u+aG@IGY~_9f4QCQd<~!L9kU>UM|d?9NTRoG5M?U_MLz8GGm<3c>`7gH+8`n zeZpVpj!H{eKq(m`1`9XFCniS6#-6n16*52}zzcd!8?9aM5C9$o#9SAq$4kBrSw~cG z-2?G|Ff}ousIDH^zxH{(JVRkKd_U|y%_3f|OR$)qIVXcB#qDn_IOsUofg}_ZvHXRG z`z}sSBfzQ-Z$!75(ncGYnFT^MDtN&d@)jlG@bbE*5Dqo;OEjEwwYPnv%1TyW3I zj}uP#c4wfq)MyNln%Ibke-~DiP_r zuyJZ}>K);^p>c1>P!RYsW~}2Ll68DI;RS&e|HiZjhvB*MR2`(8LzfRo2!$U`r}v68RU{azMd-2%*Ygy5@#-; z3yIJjDinI=N%)=dlNzBsVQfs{r%~r4a{?!dd#G~sHzkaJN!seJS{v$AV=&Q6=_D4* z{G`3%3Y<*w{wjOY`c4xWo_q4PW`m*Vq*M zFM>*Ag$;G+@nu#kr}|eh86G(>SA00ECvMf-Ygb4aYbkm$^5@@!^uzzfKknaMRPnD` zijQ(!{CK59cIv)VX8JSoI8;Pr(-_pM&ypW`TvH{%P_Uhde7K({%F!s4z(DO z>j9nM`>_2tCvB2nFg|9$?{}U`Z$?ckm+ht*_vZO^BOd@u%QZ!T{oLh!VnJ~To08t0 zN*GlF$E3KEqxO0VGc%K96I2KZV7aYVaqQXn{a^~KyB%HAbqo6(cj=Y|_nr6^Rb%7g zhyZ5;2~%j7--2zt5?zPgI5Y}z38U17?`{YWwjAoILp3Gc(Di$FPWv`aGWKx&q@JGi zJRl+hybX~OEH?)1LD!bk5d?B_0OygRpbscFumHW|P0l++(763jIXXFs0jdWGUYbof ziXzI&_}t0&=qg8(l9Ne5vM}XrK}3CGjw<mRBJj{4Bkl;D-n-L1^I}{WYfO_!> z78Xk5{8)3q4HnB@G;?+32@em4Ba*el4}BW2ioFB2Ha0o+^@;22rXGT6UzCYL1E6C8 zIi@h+gwgb63xJF5x-{O#3V5u|OD=e8(t~b8s(L(j!g394C;5d8T>QvTuBS?MqJ_Rb z`$M>E5cth^>EJ2x-M)IpD`HYIG9Z2&uD2T^mJZCo9|cdJrV>ga%vzsYSI#dlKnZK# zxS-Ux;b|$S*8ds9p&beXm=Hh?4|oy8l)|zl9Q50u9ibt|=6Lq34K(|RwT82&@Q9T9 zwt$xgQ-Ke3w%`BA6qAm) zEghF>F!kB`0LX&z7knU2I(Y>J!4T2~Kt@h^a)LkT0YScbr*VO$+O2Ct;Kd6XxE(-K z(#;`E%*7DW0aGqOFo4K^mZUb$P;=5l=ZkVZy|8-W53mSiwFZlcNN+;r?DY%#tpFM% zkugrtPymF>$;CCgupn2U0=^T_Pf!3?0{0c5Zbn8=nwy&)?)z1I@JGtvNDSjdpI=yr zT@Mw(6HVyY^-V212Pc+61qEe$|IkL7nI(j+~4N zfe~*Q4J2O07VE7!-^nOcP;v?h5z$rrUc`W*x;A3`t1a6hUr1!CH-WRF3lEjxs8B?A zf?jnE=hvc>+${nX@%C&6I_Y{*#UkQ$R8I5Tq|WFukJ1zD3K`r{YgAL*^?MDemR&~O z*YIwodCT7{G;*Gw7&zAVx79z!=C7o+v^jidvv;uVR`}QY`N76gPE22yGcvIrAhlhm z5!@46?AX68?if0`gUHmw;(vh8{yA-Hq`n1UO)LQ5-@<5N)j>K1b9hNCFscOZk%HqM@Pa{pA zuIPwlVnS#_a;O?|jo1^}5(hLGAH6M5`D|^ovS?ba)vrWF7{1RQEh;>A>M&C3BWIqc zwlLK=sdc4{WMouSKRTbURis00(_K!8W=w^AEBjw{6utVrqtL0!xxKg4zcwr)yz)2F zpJiCt*u-|{xisqdtz{?#fhHa)bCeFIhiAM1$_8VPvM~CzKyzX-{iGYR#c(kL5Q59u zPX#I=4GsKI;+E|+P<&Aa@EsT^8O)&&SiF53Ph0IrvH?uoyXGHG>;#yAoRrV)0V#)3 zXptnrOWwU~hZETYvM}Bhc{u+-_PzB900KD1TrcLDRgWr=HK0p4|Q-t!7Fj^9pZ_0 zJq-LNEF**E)tV+o<(q5au-oY|&Ur6yj9zaekbU9$v5|qTyYrWA?Nr%n}}r;>DX%Ky(KA# zP;eF&7ip6Rr9U04u7Yb;9B5FeLeL2U0JPRJIW{H=RvQ>{VXE$p0AT{KkWh`xt*o*d z8!zvUSX9pB7Zp7r$98mZK{oJ0V8-Q_#uI2~p< zqpG<~ySsU{wR8ER(&eWx@)_g_2K4tWnToC-%!0K+En-k=cU*uv7C7?@vgeUl9Jf|c-G3l$==J< z51&TM8@WC&pDA{7adoV#>|gJontP6WcK^)6)>d$?;^YY$Dy5*l_9#t}`F$)T&9Q!A zO@SzV1N-0yW!>&vg2KjTchZK3f9J@YV4sbRP03ijVYH3RW3tIm^E(ysRbdzeA(vHu ze=!pa?n1CVd1R%xUE5wV5Ap87lb^@2!h$&iZa7tjhZ>gKLJTjnDUV>of@*Dns_O&d z=qHsk4(lzb?;BOdgVMeLKOjjJ^(eZxuSQ93?DsnXUUKZ+A@-lYPTytog%-w4SxNa7 z#a_S45a?l)H7?0+Can8|gQ8{>@2|-E!#u%={2b^^fEE5G_ZlnJ&|=kq>Mp+IS|o4k zd(Cs!f@kcwFULJIW;f}8Z3MA(DNHw}ESLoZ1`;ILfpF;YHu1Yd4X=Q;xOeX!;LaFz z5V@3Yk!0K)atMO^o`Z7^etw4Ph%OSdat&$@IV5+=S(*eLKMJO*_@d{wois=Ta09#7 zz;e`IhjpBC1E!S~ZjY%M$g%G{jJ)$7R+W!KUNG%`>yo!AHmPvpwqf^WLgYl(zU7!6 zGBH-$kOnnAnl(y3o)NXid&3lda%@24fSd)r1_x5vsP&Y_Bixdc>ix=hL!NY(Z=9PZ z0D+y_S=*i{GCOhYPkD-sQ3sH=G=&PRKZU9j=3P5CxHnf@?{QJ_#T6x+XS*-t>;m|E zsE#l=w8T%F1u#j!d6Uc}qT1toP}F8S9?O+ffs8mF3gFR`Ug?8CA`9-g{x!hu0WX88 znby~>Xrd2}5dghVBVbB}TEwTkil-w6RT{{Zd0QSBtDqQyh0cyY1)gKUYh8xeAxW*K z(54KM zyT1P7UL~udK7mlfr$dlAB0_gFo0}=(`^9BsLSvfqx&QqucOcEE^s=)<_j4M4~lt_{R^Jz$jfs~P`KSgE0t-#O^V^WLDZNKbSFwofetm%?MKHtd^BlOT= zt5S|}c=g5jEbjba=uB9bX_tz$qPE_exefj)r+;A)ue6;8Q-#GSpF^YF$+^QyeCy9X zv$V1CN&kg)ke~9`}$CEL$0Tj&UZ%;`hi}4jaBU-7wG>^{a%X2$E zoqR5&toyi+ydNOV~!c>Mv_qU+cV0iU}?E#@WJqCnu+0 zXYb2r`*&Z8}Z1{1tri-F>`Ltl#}<|6;7v%T#6~16FE~ z_WH`qwEHD&LMWeCu~+DY(;8J9GZfxxJF29UaW<~x!wXi15L^_AMQ^K zr@z-;TC-ZvjT<-_S5b*CBT9VC3?7c&NE}$N#Kp2yHZz{%mJ^ z2^UQQww?e01Ibu$JH^bF7pO@4Awf$3JqDo9IdRs&G22x9n$PE6XRG*7*dB8Kuu$GZ zEJ_KnMlqN5|XE6X215SisC}+&ldRMi+`vjTMI$0HI z&PC`+4aQN3I~XFQ^2Pwb z08<-ayojtH;HW?MX5Z!x5Ojx59%y$neSIM!Cd=MU;xxT#mi&ZB2^^K(Q6G=ybL0l~ zG8yFckZGBzQ;zjFe#lR!XGOZdn@ceLOOel8dxy_fjuaD4f!{qXFbc7QLZK(!;t2_*#l<+`5;?s#yyUrMWeC}oimC}<;y@SzUkzU< zjFAlu4S++NCv^iBjv%N3ZFg(~$<^rS=wo5~!>6&*KXB$%b~oF2*h9)%Da{<8wEV@% z$fe!2eZbx2S83i+tcqc-Vkoa#Alau%jU+x_q&1*lZRb(dwfpuaAjkXaUO_Auiuk>F zl)!hs`Abq;N9bAJ=R6)qUBl)!dz}_82BpN8Ta%Tk!repc|@C@|D8G&zd~9#=xLP^>D>@#C96t=CHymez&l%?wKG>BSR8slt?2 zd`LHu*u*=tJGZ4opQ_W@CCMND>BWB-9$sGA7}!Ip?`9kmHLBPVE?1{*D@(+Yguz+z zAy@UYCUQQJOu~2tR#m1bcgnh*cUt)Az4ctPgp@CxMwJc+LpJ*h&7#2T$_I|Mg%oa{ zk>cU$xGyA}3leurG#_Zm23p1y{_!f;_;teBe$|0erW;=Q^{XT`9%zn!In;wz0H`im zQ|K1dLSq4pt*Do$is)Zk{gESs$hHJ6=kobwzjY^Oovus0+K~KD(k`4QZAXI0E8FRd z3FzwnB%q`NtthN<=r}s6Fm7pBumy-i_FY$<89T|ZL*8EFiXY)4-H>&mUaD;XP;=gx zCP#a*{LxaaQ_q}_|F$=oFuM_+F?%AQ5Mo)1P`wgUQV>N5w1_YYSS`>zoCZ~`uta-Lt0Y>v8OV9=1vNNa z&!D(#(k+X*k8}LGsb)k2)!f|tXJ0HMWRRuR)Ns%I^+?5yd?v#`?6KilI%A0>(`f*G z0US3_iYF!~KOqX0D!83-Y%9ABxEB;4DAbS;3Z0jBqf0obxB&kR9^QDL#gYDQsl@rM zgu=3Ce?M_M=E@7QgRVbK;bwujn{ z$!rECm6HiigNLmKk_)|icxwzx)zV&dbNwkjXIpte2+s^DL6+9U)&EmAUJ53#1E4|V z+6-U{o!g5$PaNKWArZ#0ql=~(GxmK8!+n^r*b~E;I+GZ>hcnZeg|3X*gO?6^Y%A5f zKk^_M4I&X2p|#biFxY!IeLo2`yYjwCyJ3|#-Pn@Jt}C^;yG44>e0r2EHYDAOPGvny z7tLWTq@zX3L|ruqxjeJmH&dU2JmWpN*hNx87R$Jlpf&7oQGQ8QB5&FNGCbr%p&I@(;(sE1Ee z4L%%(Q#6a1XL$@|unqTIR zpEuVfT|S3FJ_oZ@ zec47NX_@tOvovSyDmTtX^Rvj9GiQm4i>w;K=R_vh{5Q2w6S>nA%*GrnBwik%oh2D!Fc@U{6vi@AJI)0w>W zQ#Ca9xqe{_M@L8Z1->tYX9gGN@^~07nTlY#oeAE9%#Ti>p}^IEU~}TuiDX^;Kll+d zinB(loBS)}LK$^sjy~p&j?%hRb?zv!AcZ+wlDY%5_h8uoE_vCBA4sz(=1RW{%lSOO z^~UQslLTNg`su`vfI@?P6#r&U@*TGbH*CM>eNB`TH~z772S5lAXu6&4lECMJMjpx{ z^@{43SicMaaA7o8VL(KB!W#v)Ca?v_z}y!r9lN2MGdT18ndh5~?aQH1N{Douai6%% zP(0UCRRwW6cq0dfhK|5O3VVJWCPe_U;f;0`5$N zt6zz-fyiI#*_CA%*~>}(5<;tq5H>Mi1CXtQxfeW7UEAA*OhS(i=t0RT4^|M zi99SpWbMqBIeSt*d3@z~x43oZ+|nJF_&IaY+;6Kjp6-sA@6Hf`2L1|h#cZ^eQLJ<# zB)#Tt%fb5X$}OFtCo5K17!LqV($QHUSuc-@!u)yY23Jr;`lB;@Ht)_lz_OrDbJCWi zW*IUCghjEvEoymH?xiaJVrpCyndHt+1IzRMkN~P)u`kz~+yx87&KD>Y4I*!(^5hu} zvpz_nijOMf``pl(hsX<$1{Yz@nQ|nD^hIQTI%zO}NRn}#^?Iw}9Cy%P)NMyJ0W>Vg z)hHpQ8AYTfQ%$v{zj$8WG9jw4td6Rlovuxo;bhE?#q)|xUhaQ#7es8Oo>%nuN>Zka zheDdP_Kral0d}BHaMb}GjBxX%4L@CT6AMd~q=vW=MCL0JLJI;32s|OMKRpg^la}kV zHv$jupC2scflknJZz|+|5y@cnx}Uvg$Td~kaAjj-KXhy$MS}|tRAE%14+;R5PuH?1hB3amtjt*w`hh_yjNXqPksN-nmF#(GAfFU3c$_;9_+NU7Q4&Mv_ zeK-qI5t+IBx~zDQs@FK=y7`6Llv-la7h_PJD3uTBlTeW4G&k#@B}v4aBNH%kA;nQ* zWfz%Rq|`>L-y-iQHn*_}heRakBoHhK@m+_#SuTJZsK2vR=@v!Liew0Z9HtEHlf&@U zLz*HiCzf$X8nv~OEe!8m70(a1eP&aD;x$uB>dxRGYrJM-Q26S;lu79zaCgx4;y89 zrTq%fhg7dU#J>&^-HC~b?JI}R`1$*CWa7==zD2yHL`;RDV^9Qv=Y^*Pl6MGZUt+`wD|sT=Hx+!a5Iguhx|_}oXPD@A>%cJRI$Q-rET zHg636s|Cm@{c8}m1O*$~FQ5|vIvOMVxNWOmuS2 z_a@9yv9rYxqH$h>Y`|<)C=8EA1P^Qvl25v|7KA6#X6hz~Z%Hjpq^ezCPFOoULDFre z#6bJ{i4soIk2^vGwSXBT8`*OQVbj&lF`w=&nG&lNJyYBvcT;yPAlhksr^oS^I>?M6 z`+4VdkaPU-M(>(~nFBj=ekeA6)N8c|tKn^ir%CbpmsWFIT9guK+Yb9y{1+Y(e@1Z| zqnJ;OKl_x9_=reO+3%1NRY~J$^rq1H|DX|nTDJ2gpFwe=^P?rzvePm|>hvxBV@|0( z_;s+`v43t%C+b#YykCzL&Wf}Wx&t<) zA&i!AEl~xR5uiO|lL7mGk|+y$Wa=C$7zjc#aWDhmRL~ILZE62K;hX~ZE4*58g~9jQ zr2Cd+z97L0og@(aWHU-XMn{FA%_n2t$x#Z1UjdCAl%*eGkfN6W^8utS-R(xi5YO#Z zq+mQE#|DB*iZ&YL+K~N`<6qvtMg?~ypbrb_0k-i_26x3X%1x||1o-$Mv^D`CPzz$! zlo1cRVM_4^)E%E*>r6pnYI4l-dVCWX%Ov=Hfkk#B78SkM>aIMOZ^&eahwR||iZ}~1 z(Q;UdkEIj&Yxs4WGzPbB{*o>c`a2lHOJ_O5#BBfB(8WIZrGQ)8k8M)_C*S7l9OGMj zk>?-YPb$sW(N|Md5zj~%j^>q$l1+`Z!CBp&4ejN&YdvNQmCx)07rr^kiBjSZkJ`0P>z z-2o}3J>Oq2F}IT>J&kcrW%ONnKe=9t${X~kPU~_6Jr1TQkj5brO~JuO7t--G&7%XH z&_IlU9!HAD?Qk~JdEw7P5UvB_1ZeB#_O>C|Tp%A;$*E z0b-;S0STnNzkh!<4xel=dt!c?7cq99t!4vxa>7b|J`b|+3JBmMgI^p% zOkeS*tb?=B$=P{yZjQ0>V;EDH<;cTN74-kH7JUatCkqn%k?3rnpZ9&ES)}!=zcIMjaCFt@2Nd`_1;T9qd z|4$Fd!*c=2qsG2jNxsgy6;~OwgKu{p`B!{AgIgKeU5HHu_mKn)7Jq+<)T);y+yL}E zV9EhhT|@*nfOlKFyV)%*y8BjdjVQeJgpPYihijW}+}W`*>i}FsD6zo%2pur!EUBwA z!iByf=>ppg6RMMo%MT#TtgMP|e-6_co7hLg~KJGmR6LHEO=ldg<)^mE&*mQsAC|Ff;M^O^qq%TuD72->+DaiXs9O;ETn;2p-`aZei#oZ6vDkw1p)UwD}m z2m&C+4!BZKeVCHZD(#7Yzjj*g?>%c1}lBV2<7n23;NuZw;?yvQDRh}Ol& z$45k9h%Uo=4TPVhqQinaxm<$@LT$hxo3kuJN08alk_zEp@Dt#QIypOo(%K%c=heHs zoKbv&6}V!@I{+^ulwlZwe$34DwqDoX#DT~du1-x|T~oNt!F&SuG)R8|RRAw{&U(Qp zhOQ4XT-@;EU}_5LGBk7Q5ghlI>{f5U=AX9V=AWHS&`dA`@z%d~VXfI&dtM#4CP5g4 zq;?OEJgmd^BtJ~%n(h)Y=7w+vILLoJj%N}-^z<33Y%li9%r|y)pXA|o`@Q-2{zDI$ zoA2ng`|~+(?QrxS`Scn~Fvbdvm1_-{cj3LdbBBp(h>eG1aQ!b@Uhr+2aQ5iwwT$L0 z{~aD%#M__F64YheV_fQ!m6TXBBo7*J?n6WCFf&$NHIy18?8fWrv5LY>xH4L5)dbL?QWgCuCtd&iu&oxw4 zWlizrqi;1Xe4JB7OCx$fnMXEy=#nN-^up8T%m+Z_*gd7^JqV%T z;7@>52D|IO&LSC~#yv}Oax8DhbP{9Y)6~w%!RJGGF)b{D1MgFULI)ALx3$0Tbt|UC ztL7k+*FM!+@sz(5Ej(bg`{aZZ@qdBi0l6q+U~smw0yTn=i?(Xns1|>rT9GPIEzH@P zT3T@E!XP7~fEmQ649$-$rQC^6wQul-*F`cAxzzA9AYb(hkR4#-fFcPX9tH~5h(OwK ze}XG~6fmxcWZ>}F&i`DAe3_f|L-AD9YU|(hic)iF*r7~@!lNijNKtI>?7R&@!zK`) z1a4cP66ECMKwzOcj`so4YZ#U%d@+NN~sV=0PUnLXQs-VK@ z@Q&n}pxWaDyC2h|?IU}0f8Hc3F35)vRd>ivvZ;>82#YE+YJE@WOD{hpN#l7M&K8;( z%}6MftGtTozAYkbyV%mzljbS?>eW;E$U9xxac|Yf7}LvbzxV1!Mn4jBc5$hI;s+H3 zkdMzlX*iD{$(h;}q$<>SkHO8lxX7|$1|`l|uQs^L5WvSP zua_XfaIhtoD|M{@5@R;Iupq8T0ETRM&QPYK2Tj4V^lR>ItBIv$2y}n2T5!@!fQ@-fOf{h!f{G`(ChqKn4q1cI#!%F3Ps!ww@L zEbxY=))exQfOutyH3T1(?O&k1%yc2!FbLi!_;x_LQxOv1Yy91`lHCnHT$eRBR83Ha z{DNK>{w>J9hvu}RS&X=!nUytKI>)%EA7pmWr9fv3gFiGFuwVx8Amilde2)+pQQVWk zp`jmhb0E9PR$&0WG^`0UgL(1eM>Jr3-oH-5DmLQ&hW0nr;?2v0YAa7# z`*qBb1>0JgLA`c5JPM@=(vRKFm!9WW-h0#N5~|gQiRF@U!y5>xIe7OVHVPzOuKV+d zpJYbOZ5b}gtS=Xq*k#y$aK7TwXu|d~c@V_=VW3>MLhG|w6%#qi?@ECt z6!Q8IS3Q83P!F|RJQAUNSx7Qz?7=GnFaSU)@P|Mz3hMD;fFVFq3I1x}9TBKrqR8BR zJ~OY)qS>~6n_L(0)@m>zR>c6a3K53opb&+e34MJZ_#3?u1m(3@3J7aI@JEmk6(mLl zGI==Vpo>TRv(Wi!j+fX9mpOZpym-BM$J~1UTli&wJ|X49hZQX?Lm*K_M1%bPjRRfX z+qbL;T&=#IB)*^KxijQALw*QA9|(XQmO31|X1fKuNd;F$OCp9AT?0-+QR|A?K#!BYuVZHT_9tgHLJyIVYf8(`aLFJRS0 zXtol1jI?sZV`7#A`Q}lw{Bl>ngQA-~Q3CMP#J?3X_E0u` zPGHOI7#Jt(hi$=k2F}DUnp9Dr`0O6xq-SIxhjxi@lA6G684!R9tv{&wApyM)%i#0&*;b@5)>426{-*m|uVk>c(EhXGtXEJaY+R6sA;bGr z-CG>m0l5C5GpVev?}Y#)f)8(3LVOnjp zl?8|2$RSeg+4-Cwzd2Rca5=i zcYU8RXbCI72`j&PK6Nlp8zuRywTk+l=to%4(wMTw@B1%h;r&a}pDOo=L+xS2Gch#u zgD)Bz3d2xF3X}1mV#NhLTI9Skge@^N~7!?Z&w(d5b zdHQ~P%b{4@^^ag<5rp9o9|o)J!yrY?cBy3$012x0`%wd-W>js30Nf2zwx1Df#M_fY zNrYPV+4(M_vd<;nK|=%agxTUoqb!eiad|OI(u85bh65i2iT$}g@J1l9Aa;e%R;t@9 z?dVwfMX!5`BO-(N6`M=P%eLuR+sYYuyT!&hfuA1VR8x&@bUgrvF?IO+#oU`~(QpIi zm6t|V?@k}8GZBFq2391*L0tw&_D}C?uMWU8G8E902hY$P--Jbtz7nZA#Y9@<9q!a> z_P97otmcQ5silLwtgMwV+*G8xn;%tV;Xl_PG&D?xOAb+&prr>-qZl--&^!-evAsog zBg78e+S!SgU4c>xeJA29!w3oK&QS1ltrnEu$Xs}qM-<)rRybu-a!Ih;4xa~5VZ@G}!3}-p zxXMr4@C_M4KL++L(7Qql23$xqU;t8dxB+99QlStq1Z^=yG$FKXc*-BHdSI=TfL>wG zPXW2z`x$gVxWaBO6F}1uy%7%&G9q*gAf>9>T5wEZ+(uDKp4QMHP@>2rgKf>J@J$z- zzJv%DJ-sw0u{1OOKRQSapA7JI2{!q23^fBAJ`D=j_~@vAjpZC@h{)UqI6)1`NaqeC zW<#kTHmc5Jj7~+#**#t|vVxucPBluDKnfK?LJHMe_?RKsqznz2%1TUYLqa<4_Z~2s z`7Uoa_5QhOK(WmWU5)~|;2rG1*u|EI#kTh~iqn&T>-JXY{7X3UM)=myHu9y1AWSQp zo10)fNrOon9tZG!-;CL#B&iXxuh!gSQ&UfyJwX%=eLkKT(Gd>J(iLrRc_*f&ZNLH? zs6~e58t8%FDk@FkI08li7!b%N0F{Sx2{`S_)>xi-l7zByG<5>hc(}P@^ek;{!MYL% zI%$~kK^y_I5Pg6>hzmhhix9aWRvmPQhhzc_Isn7mp&K~}RxhvJ1X9mu7wrC5`Y-I) zHK8xcTob|@W5Z1bhXulfq3{6~0o1A}sUR`_lhMUE=^VRyZBT-ZjE&uT^hOS{Ltsb+ zlQ04euJCH3ThW8^}`G*kDU!E_h*J83sHd z_@A3W`G#(OMwf{bNu1CT`d^TqBNG~>EA`Jy&6`!PT;B;GW^6E)#Z-Nxs`$HM;l#z2 zW4yLY%QzVpf$+b3_x1UnMzPwJv-8P)>?61d%-~wu+}X}}Ox$5x-AqU@c_T8_2Y#$ zJM65>NwDfOO{m*X$)GP9D*6hnpywuO78?0ON)D(=4EXH4P(*8D_|4^?3S1ZHBlcmK+OhX{Tfh*ys9j~#2hD_s;jn$q` zWC8A{XQc*4d2&Eo(dL4(77)gx-lu8cn0$(rDe+T$^Y6jl9xOZnee|dOLjZ#z)MxEM z7}N8NOZvs>M940v3XV0Nn-!AGoKS zk`g&--KOw@bC&f~Hi?3`Z69_rE9jCz-v~h)z?s3Kl2;XFMQM(LX&YbzgVzwMG;Gp~ zS{F4e!IX0_Vlu1Nf+=wWx@nMjKNR$!Lw*QMFP2F4iPnwMkh#tjqVWcB43;axp#wmj z5rV7$50fT|uC>^A;5n)2W8^fgPaW-RSHoLP_BfmIR7sMel zkYTCJUVa7?I*`EdA;A~bAF#G;0O%0Z6#%|vKGl+L5*~|xAp{%%AQ}Wv2L=L&3PI4a z3R}>;z@#igwCBFF-?VXTlvdg84vr^;9`uM7!r9=vg`{fYlz7Fb?64VXjpob0$JIRY;1DJ5<=GC(n8=G0o^%?JTV6!w(xt2Zo9t(|6<1+z5YbXp6nNONpi_14#K@j+bdUj) zKlk%TDUOV7LOYGoQB}eP725EG5#3wef0NVgOUR|m>cZwqCMy;l9f>E3f7#8@Ck}4X zX*dyv>Y6HN#Sd0-iHoZDGZ|I0?|0-cf<^f*+S*@&^042lxQ{AwE#S`SXIX`^3z#R| zJU}_ZTLSGgKsx|0&|nm)Ff1Qmz}25!UXBYESs30x4-W4vV%goW6(T7ZzzivBJP$Y# zh<89!8j=%eCT?HI`h17?aSd#Apne7a4;ZRp9y)|glCXnL==JOSQ)TgT6@V&3uM3%? z_@P~pXNwTwv3J)&-~2zk+9HbBxZy78EducOITLraiYutRg@Wo0$W6uU-F4g+ zShQL0H+x=RjUIBnzY{3t>auBj(6({f>_xGV9(DSl*g%`(u;>|n*rRB3M@E8BF{4IV zS-Hxl28sM~7#dkQ1b9CTTGFWh5SpSVI{xyIg6$<&S7qL7-q|HHCw(7Q&}NeHl%}z% zWoNRHqu(~SvY|<49hn~go(1Rkx#GGFk$^7Ga<@crA%>1B+Z*OT{?2#9BEB}X49%|+ zD06T))l`rEnEz0TLbn+*;{5()TOOOc>S~KJ_Rq-3NPx|0ii*~T0$>)kzvv@`*eiyl z{*H0^C!o%R_$LU{BeU8O%f!WwjQDO+kxz@Cj(_(f;>)kiO9p4^l^3N;vX0=2KAjlo zs@pe?jxezs{q1;VU0q!hqtuWuE!ncYcHPZy^M_lfz?*^Kwg6=U>n98@_OJ&7BaZm| zF*3ocEJX`jg3vC&tH4C{Ul#@RPjF1LKjr{sSq2IQVsdio_tMc4 z9(0lLR`*E<PlfowR)8RGID970SM#} z6dZzY68;`+2~e-$3q7?7!wpXx<$Wqgi*H*?2J<4=GHyRW=vP5U=F*6Of?wxcUkdal zob!FGZbB~1c_j9r4ImnXLafVBG4+ASop}w(d{iQ`c3D+b=y)OG1Ihy=1Ay*={vOqO z*7U*97za0d?NUz7wR=FVC2fs)r1#$wdYD##Hih*zh#nU{()8XLN4;DLieI@8piSns zwzLG8y?&Dj3KH^AVRMxj0#Hz1C=v*|18n2|J77BgG_dzu#&m!(<%DbI;MjnMJ58eRR{Rd6YYgD zT!D;}ENgDc3Qng-Q(P3%AtJ~DnZ04(Hu4IxQYIs?2h^;@Q;1cXkMdN|Yzb8huI|y1 z(pHhWz9D-?q{rwjk6Kw^J+j4dL7$;K9vV}n#CKEZ)74NK?;NJc@WYwE@SmwRy^a0`u!WW=wA_xvy+MN0*EwnFqrs3Y$9SW!Icik$Ji68|D#|UKjG<147xmb6M!%S#OApL+dN3SLBLV}$$N@A z+ylx1R8R0Lhu{F0u{ljmeW;?kwo}%MK%yHP-LGz2ns~mkS*A8^1EK#KGr_h44LZQHa1%=hj>8@?WVvN?3UGm+ zX@R*bt=*X2pmvT%pRt8yUL%}V+;58pWd;7!oI&_*vt`^THev1td#v?gU^L*Cfy^F( zhr?vS)9>YIorLK98w;tlo%+wrAleoE_U6vs4?=h);03`*%MJwH*##eEzZK;518Z+$=Nyh+M@&S2a9K2o#ee-TX}!JxwYN4 zM?|ZYZqbpT@KPD6-hPiEr11C8LnH3^cm-+keeWxbcj?%T{Q+IJcT_Xpr>9-!NwL>6 z-MRA$Y`)LNmtMY|CdE6|AD)Y~hFsq^JjD25ogqeq(=jHH9Ph1{cgt;BM7=W%_8dD&l>z*{6KY-eldMbc(fS#;E zUU#hthd*8f(eHb5sABIFqJNV%e5)wmI81d3H7ID=8*MZO;x=?`E5Xr!3{y<*=H3v93 zyw%W{1NxS0>~P^B$me>S?wNqV0MulV7y*f=T|UG6m8i$i!VeT zwWx42=EN0v9eJbE(^q{rEPTU~B|iEtVlXi%*Fda~t#ds9*G9M*wSU-#=&1nrx|(6? z%$^I}0N}v}uoYHDw85U6T~aU`wy!xzefobqy$3j#efvL-B&(8;QA$Y&SxFK?ii{|; zjO>|=P#T$ve*B0-Ou;`JC5ggp8J08yZZQC@9TV@=WCr) zl6k$Zr3M+K1}Ys$B_K)_E=8=n1qwh&L;)TNi;Hu|XSD@aT~tnI7s(MgUx}N*VQbS9 zDv}i}iXjxGs96f?44|Kny1y@aR$2J>c$&s>wJ*91U!46{$ZBnw=1%kZK>xZxZ)vue zolnM;QRL6E^P%j~81*lgD~v1u%>LZ{bFGoB zE4PY&5JUh#BJf=BR3gauwH!JVb%yhw({cMEfd*+`W7rO+sYx)SHhnh>K$(F+10x2g zAo;@*R(XdxF*se))Z8E5Qif|ENUTtlG8~);S%fJQCL9sH-wJa&Sm(3m4%GxM68XdD za0en12+}bKHqczCbO4yZQN!c}{t?~O!Luid{(r#v7OBv-ch{Qx8Tqb(93a(FXW2)R zNuq<#VoK)sQ_+VKvnJ3Kf+`r;+898L4Sp1$U0$;RhPNi#k7BodUBQ4?Bh(T+pJ0CixG+DW``fN1tF}{Ts(30gwBz~vr7A43>ncY z3nb*&nxc0%k5x?#%M{F|rFlpO*$!4ump^}O3(^tL2P7zv=dBC{oWOVMXdCpZ%l-7T zt49R&ZbWJ6MO@XaH5MCQy2H%=$K-f!%Y14uC3y+?#_i>G4#_f-_^n@KlFN%W#*ZI2 z2?%J6Ep@c@aCH|5Q(j28>KC(_7+J@-m_=e^Xd@DkoYvl+GKtKtOGg)XKXse6j=iop z+;U;5@b;P*4)@5b8guwQa*Ilu?%S6Qc7JE~e><;TzRGCmvB<)&(kyPP)s$|u{(Ict zfOP2`VK8{mU|MHYAo8U{PAX=QP)r1uuO68#_4Hb>-;7@DH&FJMRoBc}lML)HdGxj_ z^hCM&4Xdaf15&@n%9l@9UZ%UkpHy}5wg(b1~kh*N*F;!aU&!Gf6!IBLql!qz6(Vl7h2ki19HaS5X17Q)W z)kUVvinF~ zKpF&jLEwNGQM%)D3ktMfy4u(fm)yYSVgX@Tg5^!wT1hVI=&u;tnSe65y zLj}+TwyMEAIX54_6$?TUHSO2gjG0-FG=aIVMF-WL5$!xm?6JU2MjS!>E1&;R%sSO| z?d39s`vkG3V^4dhy^`L+d@nl3U>*dD`I+tI8~1oBb_kXCcYSApIdS9acz5rn0e6mjlPJV6yJ4N;B$r6$?a))ciT@%yOO*fGi3+%P})PP6z!L8*BK*b9| zRsjfpF7cyt%HjyeNIkoV!@;WYH9`!5rUF zjG9OTXT1fP!$|&Nws6BF0=?M!G!(@kR)}Ej3E?-jf!-0r8qI>xnxU;_m-cERY9SEo z`qX%@&*4ftA_X62ik)m3n}-ZkkxV$mEimpPW>K*i@)eBE1UOy3*|qf7w{zhypV_cgX>@S1w`5d-Y3L#y}j-f10O#M{2z*wPIk|_ zgY~%^)uSs|!Qnj3&p<6qx`#Fsj|?)is23KbUkr+zsSwErf~(t>2|+8}=K#nd3=k{; zGA%=(9W(nTC6NqTOXJ6n%=#^H?xuH%}7EK&31DpL=+%PNV|HLOhRY z;vHZPZwkyzgP3(IL43Azzs|{-ZF1A)V?ufgyyp1Z=UCyCVugG3&7}EP{mn1E*Z=uH zd{;eTddtXXqFa~C0>Tf&q~e13BBMxIb;PX%OgG<7sWTKhBYi2ZOYWo8gAU`pC$2tK zYLVymZdi1^sC6%$+cNyc$vvNrs_tz%AwZ7>qlVfS?7gLTs;ERZnLDdgo9Bl#o9gK5 zn%_3tp3&Vj(x(1rpzxC1N79(A%q3p3Gc0K|frjcbnmi11W}(#C5t}a!awlLh@-2*F zVXX>6l4MofH1`Kb^_t;@_8%RM{pJrM1|)yRd(WSs-L-qr`Lsi1Y})A3v+ukLbv2X8 zg3rYX&fBj+u|0~^$%7UG5yk&c+5xX*M)|U7qzpWb?@4ColvUQLx1kh$4}S*xN5H zZ$+Kc0x##+=Dn}n@?RvUr-x`R;EICwh_Jo_S8Tr_Nk@q~3OOKt2#5u6>x0<2Xi|ZD z6TSDZLQd)&|HMxs`B!;ovBL&Pw3VHm8Me{fyK}JpsDIAoo9g<2D50W9E+dN1ab1PO zVsxx+7y>-jrVEhA1&eMIG}&Jd{KGbgK1LIa&pZpJT@V>#v_c{m=*0#L&X9gIRDcCw zBSu*4CieUw!uABs=b1TLF{WVa(hKMxvBwLdfMMWZ?Cj>ZZao8pCF0YGmXql0iQN&v zqM#@g5f*l=lTq?H3ZaV3AsG<2rcBb%hZDU!)UbM4Xw)vQoH(zJsGwm$u^2s-l0LSy zsPa7K^l4wBVu;t~-0QB3I~C*R)|}xc4SGo|tb&C8&{*v9eg!&SrT{D#n6 zs7m!D4&9GttX%4w>n?MTs9FFK#Bd zGK_tQZ38YvEGPgJJwS3!Qxjrfs2_N`UXr+yV5VSUWlbzDzP4EwdB(U8j|t=g<`^j7 zDlynVhvQhP-I}MT@NvdEFum1Qol*)+J`_&a(EA7jBpQs5|BJb^P*w}lKZ8I`tZyR3 zhG@Q_4WYkkZ)Z1x6*Vd z)orXA;4}wSA{IqHL5o3jG-y~~OFn+0Sfk0u1U4irmkm`=gRN_L_6v$IIGvPTzBgq~L#xAecKapx&l=n8Ec`D~46mm&w7vc?%9PCY6d80L&`~T% z_R343yrTc*sx?FF_LT&*OqgzQM`7$B=F@yVKl#I8NgAE>ELqS9;N`>T#bF3(9ecei zU(lX`c7xb(d|sUpv1euNEdJ2~S1K+LT#VgRNB~ZrAqe`63?h-Ca0}TK4YW+|@0UwD zbI(`NeVcZH+N%{e{MSk`)^C$Vs^a^hEBtwXoUH8spGbbvkNmDC|GeuDnH#pZgq$N9 zngOm*D%6>vDR~XcOg9>by9s7oWSprTe$|7|9Cv~d7bamWs;a9VhIxV8|8Q?!4JpFL zG2fG28dUOzgcuExsSIj2MnrU`7J-D}6n`PSGUq0VGt(XYCY={;u<$!Z<~im>m|!m*Tv%D=}%pkIkvZd@p;p}e)OKedACj8-&=<=ESLe^+oP9Qk>%dyIDy*9fQ!m0xPOKm4X{jsZ&~X9LhYtnx2s&?UrhGu)X#4gZ zwNVi4JWo^djJz97EtCXv3$?m)9QwdVO@$R91w&pYs7BITvaq2yEsC>I^0ioLvl6XSWTZy(07v)6?N33140@WiGpF*`D1Y zD#jY9qN+-U4RMXw#usZbL|*}oDJ|G-3_4P4QzAH~BV(dmJLBND7T(7t*dY8C#?@@e^};2T-$imCr@UO-cHCU z%gd_<69FO+6Cxo%a&;}>jD9lEh|Zgy3g|xKpokw3T#arT&%Ua?sA;g_z7g!7x2xL=uFe_T1Hi-VFtdq2h0DVsKRJ5GV>n&5!`WYemdWSl7f_Mco|= z00#OLX!yp^>EaiEstW%;iMSMOg&RWIC$t}UBu>hevNvzud_mz(X#eltjmCj!9FaJ( z^YDBBt&^s7;r{)C8j7-;r{$*k*9H>QDFQFuBTwK>3*S}gdeXZ!^z!M};Y6*sh8dQJ zTlOUM_P4haYo5_Mpb9&}uJ`&CCP@fOaf+ei2df2XAvjqKr~n_Y4!N-5pP^GDl8(B& ziG7g7C5k=*v_CSCl)0Sh_%x#Wu@=_w-mKbb2fuj z|N40N*p+rsjR{eNW@ftVP-!;vJX3r1#SL*u3C<6DU+ZwU_q5BJd?d|VO%W*}i)2_h zk#3z)PPM0;JyppkZ9-zlh5A4>mHFifX5Ur1B<&L&?fs7$C*(Ch_mtr6yRiFUuHcz~ zALhfW;ThM99UuA(1gCRHGQQ3{n{u_ZSc4*9``^sNdQy$8_0~B?TFtR9xpWP56Lfe7 zGX&)hd~hVO*I)<>Q4n_ctja0N6_X&fKSe<2@ei*up6=bxBTM*iFnKtsbR}E0RSl7$ zA#0W1ifwzYULs|0);tl$TR8@w-yMm?u-Xf zD{l?1AFee1aFMRbSm3^!`x>Ml2QJy^J^$r5xhD9zzqX`HGzb_Vz+`lSrtlgPSSry4 z9+LmWPt0i;n+U1r?a3G93rH5|n+a@^&AH&ep*Gb@=7ZyeS1jspz~QLzw`fY?pGo32 z>rfyv@3z+I1S-d)frVoiE=IBNdmssRBB2^a?=DN0K|=O02M!6BgCf-E9}YOZ{-&n?2;9_R$#8W3X0kuzN@d+rx; zkrR={KLJw{uqo^wUar7`TVeNVJ=xTQjCDZuFv&n{pjek^bdkm?3bl*ysz7qpC`=&g5)w+VZfghV z*4P@yA#V(dX>`$`;2QIh5H55KDlkZG(D7i~1dvu>Ii1#?Hbd)TGE0xSM4oi*3n3Od z{`leO`ws{lWb;HPh`taVtpz82P2n8=FakLJ{hJqu%}DSQWRDR7`ozA8|8})u@g5`MP6pexQkL6TMS%0%I-a^WQtE)9=zF#}g{%f<;>C?nb1CR~v4(L!~M{cgk7jbPM zY{^qC|Ng!IM}v@5`peYhWF){QFnmE-)6Ut*EXU@wy;4U?TpY`hF8?0XF7VZ6TiAF; zVwvw%Dx|>kU)<0gb`mrIa(B6zrLRcETiDwNW4UB^v^NkWef_v8O1dT+L@Dq@8XY7O z0lBC{uy2k7=1@n+!`)$tPOr6;7X`ZFmzQ9CL4!yfIjj|go|(A0TgTl3;?+PyXJ%eh z^o6Vh=rrhY^xEJvl<_Y?WQsImu$k<^q3AvLCkpM@dpaJqjlve2^O)!#{`+Y&@sYLR z>E>#@Y&r*o`)onEVrS3W-i>B@bzVq4d-7x3J0H%Xv~>SOn{gRc_0#H%i_Sp@GJ=e4 zj>kouXzS>DTx+0vDP5yhP>VJ)ud4gO&|21*p2EL@a5b$hkA+q(o97_m@enZA6Kgl{ zM4kE;m48*nak5NI!B*T{4Xbaik1FHRXL285<>Y+ljxFCqON8=Js^ zMXg1@3?u}X5ALfwqkc~lun!OUvA`VAA`pKTvbiyWBPN$vH6|GRFdI7s>ZV;9cggQL z@npq<^YzA2=WYLwla27nE&B0BPqs2`-c0$k{3Yw#Cp*&in3A)nSB6_hj9B~8&My3R zXUeu9H_0fs@QAaX-#u(0Ql`KkB*XP@z?mECal5zkF%8~#})V~aNqd4eeyDcpl(xp7{b$r9116OxuHk^I{)1J9Z`+=;4uenTPqdfh=vqnxnNR~iWw-&QFIK=rhg_^XW4 zxNBY69UYwyYfZg=tfpKQVy$udng1>ND`&=fY`1BZd7g=IjP7-vpFfwGi>p;_uDKUJ zES)QQ@wu;Q%&DoR8GAhuCRR1j-0@LKH-j76-X`My&t8H_P@_OODf++|As6N#b zucY?ZO*ofOT+L*%{pRRkgObO%9j##ZONDpK#dTx)P41P;U?_<=KcEF=%R@9+vS;Qf z@ZJm%*PXvVNkLyDDvUrS9-#GT&=LJ}J70oBzUqVoAKpixJI{ZHai>sKhycSv@={+P zXOuFsQc*1EA8cF}AWfkO{Q$-VI?|&b`I%1u48Z#invCN|Pms~2g=nEwvL}fT$G-t4 z{olF>jv$JMIdQWrNWcRFgtLaKQ8g$C$JUm0P^oJzIZ!ohM zKYBraKM&_|avcv34`pagrwj_QOBe4F;p|3s75rf+&(0Dmob-cObV*NL&$3UnCTk!18fhc9$OEH0ftFx=zE#RL~OUsLOe&P5G(t;}K^&B8xu#>nrTR0(}>(1A-fN{F|~ zWq4K`SD$6{qk)--5Glv~{lfb@eP#`|3--soOkuH9zq-xny5FbcH9OCDefgK?GkbHp z;2-9bBz4rX+{-&i18t_)@*O*W$7g)o;oVzi`qe-!wF7o-n5+mxHFTO_E!6((8@k?V zo=13F^77=MfQA8L5_JKp*`-gYu9#?$4-;~Jz*(Xh_5-4w0SS*E8C4d2K)tDOPEpZk zoIRLh4@WdMkbQ&fGdjfq^dw#y3_~C=?_?i-$*63yCl%984h&L&8Zm6ZF$?qpj||99 z!%&|3zBMwz{|7|u4SlJnz+itSt)|k1TrEi2#F<)*>rCgX^Zd8+S;w>Ta{{`=es^_} z$yf_*D?h$+dgjob-b#(Lsxxbc+A}JQw@K-?HFv%)L$pSc4)?qKQWeo6IRQfqu`~gl z{+(Jk3meUa2~&z$9_{X3gO1`tn)i#~L_K9OH6Z zT;Gnu%I12rNxWuaQ5}Qw>Y7Lpeb6|al9S+T zq<^4=_2x*Y!ZGg_r;L29_g&=HqADi0ZwIXu-a*tVP`17jhoq7+M$He5_O`Zj%d>ld zfC3L13JsPfRMf&g8*ktG&2`DVv5b?@7f5WQBmzvZJd=%Wc5Pe84Wo3QS%HWcOnOgu z?FRG+duWNlOw@}H(%WTLon%OcMNmZAm1`);$nRH**mhy4B{&xh#)ywtpNl9rb#q%* z?oG}4;?lptcGLya&mAOQG?>oOTJqI38|PfSY>#E}1l#vWWy_d*cEbKsD3Q4q<` z-3Lx-2H%#7KZc+T*sw5=Vl&!L1gfLFLD@diqsmDy>A4yP!UeN?)xu=gYd$r8!7MFX zQ*v!E_~aizjzT&~K)X!g%&y4jgqy_4>58>NL4LmH%(uRS^dHlYDjI!FRer5Oq$mLV zghK}LMq~C{i}wG;!j+K-W9TI&f515ieMhKCy!Ym5*O`7ZB+HTw-z>Oholol$455R&ERAN7^uP??u%nyC@joNU2tO#C^>YiUD;L@F!fN3X!!BHR^20q6MGtQ(qPG~lStq%DG5 zLD6-8^=3TW-LHL?_nS|WP~GGhy_$8Ji^SxJ6(JoO*xFn|S%(j)h6rXsgi{N{VSoVW z-r%fxqj->#oRF@RuXbh=gGE^x`~Q|FBNhVEZ$Rn@(V?GWXmU;(xTnr4({&rPBY>h8 z^du-@7A@lk=`UwL-3a`77rOrF)%0{C$O@97VG;gy;~#eR_VZ}?@dF>NERElovLFU> zXzeh)BSf5tMx%gQJlV9ZveI{I|DJYI?{Ph<1x9#*1 zvLG4$9LMc3vpicOJ`9VK^=+xxV^=s9zd(Bn{2iJSSP>n;+~eE*b)C_@Z*EQ)e>~#?fSY#rucfqM&xR9J{U;$u)@t$s&0j^NuPT8DoN3xkld z{3q!7^!6DbG^pikwyWDRZU??xiI)ZQ6CzpQ0hSSEtsR@kif1?2ZT>F@ByJxkvu~eX zrCyf&Tc*gXasT4>{bPx$uY1)Kd5HB#T26N+@u#IF*MK&iRw&~5xc6?AM0QlpLu0?`xC87`cdCZwsI#W+`pR4*MnB|| zau%ub7#i7IJl>kzTDRXnJuMo|gb^=?#$*N^8r<+!mHIf|uS4OHH~!1pRM zx^a%9Esnc>R-8RJ!pIZr7=x^Z8{!%2L?*6Mmv>#dB6mb8dxijN}T8Xdj_ZZji$KvdB6g6in#{glfZ zTke6eX@2jg$rnz3=P|hSNf{<>L`AK{l&`P>{A;n4P3f>AUQlr4h@;@zs>=LRVqqJ$ zEvpR&q$Jd>ESgL`COahf)C@HZe#qdh z+q_TM1A z{xwM;{pEW(W;r@oqgHh--@qnlcsCVud{-i0WZu1?NY&J%YhThVct(F#Ki-Y1NANi7 zG2Zj`oEdtb&S{GL2r?Jz+|H433d6adLK13p)!@6YYK+;(DvHtO;+;U-V8Q%;EN;U4 zkCX*p?lF2QL|H7aPG;j@H!F;5Q%91o$J2Wgn@Bg_4aL@5{bH_jW+uL`wEDF4eS}s| zQ&I_%T4S{wUURI1-7Eo?h7|aM0)h#L&JeWLMuWxT?pjePwG70z5w0|-)S-lY1y)fT zo?rCeFT3XvLHl*n3%t8lMtJ<@zf?lP5^}do!BhW85`u@?0nG=+ftp851aka&s1AE+ zUrdO@{xY;gzzre&&@dSBL=x^S{c01OZuny$)L0%qxb+DwaQWs!b|Kbd+Vbxkex}TY zl)J%<>@s86fZ$Es+$i5#B5p-+Sv(`0qmgeX>HDy5JTaBnNJL1-5#OM(D!1(Y!~%;~ z!knN2kCIgLl!_;p%NP!Jz0J-%zgwllbf4dkn`5}P2t=3FC}0geAd2zlg+2%<)Vx=( z038YFnmj9_P_23?WDd`jBvv`<<@MbuBYc+esQ=5&|zY*Ld z^PKaZ@AEwe70%t6-r9I! zp&h68@`B{*+tarUB=wFjio8TN14g`aSleLQ6d=;LJl}1r#ma67Q724;WWGLq*O0=_ zM~4GyC47ve2e{OizP=_T!y_UFNbg0lvogHlXm{bd`RK7CEWOg8hX2j&vv~M5;+fZ; z91B<;!PMa0M&Cuu4$#lbmbmF75CAJ;h;>;uS5{~^#Y+PwtN#5#GM&KN=yPR4A5W{v zZ#9v6w6uE0Q;)fl7Izv=#m~9h(OHzoodE?mZ(}H}`nQ3tn#f<2P+s$6uvW zbMtz|$Nzb&nu3VxXni9qhvzcycE#uKis)65yRtU{p;Gy`*@J`j{B?ULR$!E`b6Lfj z#k}(*!`A|ei{5*XGcv?54H5H5FiR(gFnI^~&CDuR)JVn*D*e`>x11N|Qi^mB}rb_;qL+m%>D z<&hv5-lz>*DFUn_P@(&7?uJCR?vVo3*N^%F`1EyOe{ufL#}6R$98kt>U#{+0m1dyS zqbb?f(2aW+$RW@lLY3m~fOSlERnTE4cUVDJ*#e0c=NH{eA!)08Y5CI8|LqqmbQ&X~ zCy@?;5Qd9z{lU1Q-v#LcoaeZ_lQXN(_Cju(07;rM+hnmQi%@Pu`rdbdh7s|D-4XgxV=3OIixw8CqTYLzd*GHq_8Jj7 z1K@)o^ry==3PP+FO&AXa%_r;dC8m$a4&g=G!vB8?q6ubJ*24_cNFi?ZA^TqdFsy#E zFt;FyNPOE}?f8VThC${ny8>d)9U)eS;1xvcjWJb`n?a((;SeViDEs9x?@bHbdmJ-4 zh)~OY*3t|-IF`c92Su{BX)F!UeLP1K@uigTCsBOI{UP;cJ)~-LS zAkzx^9eXJ;xr0B+E?ZS{xk$;rv|T*S z6wvVD7w9wHSV6KG#1j$icXs(EYeZu$v7iM!AURFoL&{-yO0Bn8dH?z~VQ7LkiMTj` z<-#Tj+`{wGI98^^lWsz^rW=1;iNcs07?dj`Z7z92;#`dzZbcw1;1Q8C8QW%YB3#LF z6KaIn|3xOl3^QuKIcneHGpiu?_4jFHciP^h$G`m*~-`&Q48K7V1Vp2aPM*@UV|4Z;qJ?+9a3-;Th!%Mehm z{}|Xfu;Rfk!^9KR+Kr0{Cj`qP2Q2pYcUrhDJ)7+o_*)-={O^zLONO%t5Kiv!(9A z$;Yh%Q&NkHiqmyW+qgR1X-un14n8xyO47us`=~bLfxVV$=y_8vx+j$KQ}*8OTZ6la zD5bKsKW9>|HN|h~_dcItTQ`3*FasweGs!ch*O9vp9=MQ877-DF+UvHyEJW{Dqp>Yn zZK0`%iu^S*Err|0>Pcu$R}JaNeWUUKcCh&@VG3RUTfMuOs1Ey`7!bjDTTRJo?SADg^$44rzN{H|?9N)V0QKE-zL8&dc>Eb%vKVuL6p%G7+^JoviV({f3GhUBV)#8P<%HB>|=Ibp( zf*dFf^^efmu4Y8)F@Jh>* zNfD7ip6*Lau`dyOM&`Y>TcmqihtLeOC|EAG1VAX$;$r z`=k%C*wQLO93VdJc8e~W0Y^kZK zwOQv!W;XFEmZ^1X4bL(I6W_W+QxlSmTP`kjB+_~_v&lz8PT^04TU3UVK8MA{Ky64b zqrxnNAwS+*;T#Dy-E(1;2Qsw7wN)|9b##LJnDjRbz%>zie1nO9cQB-g0yfjLYJmnwdHrp;|q* zpjUIF;{i`(psuZNEtxV2g}ZKaJB5v6%o4lYyX~ZZ@0i(UW}CR1?ESLys=((o?Tjy@ zB9UaTXncMx-EeZ}6 z-)jeU>w}vrSE!rwEgyuQ;)n-ee@?I6wc;Q3qXRtKWkyQ&?b|0VE&UjZTplI|=i;1`#KJB;rtcApm;QIS`6UsLy%M}D7gtAt05kqw=rR;xS_(2*c=U6xo`!S`(4Ss~b`x*N1mbDRB02=!03u-{Q~Zd||JhgF z#6MH@@zs*gbY5f|mOp~n0{9&N%K15N`~d$&A#s`$Bz_=I9M##e^`DulR1al|EE{|8 zH6pH?*p^`knJYf7&Q^#S3koR^;%dSYI&Dqrj8wi8X z(UD`4r7d4+wzu`8R0>4w5j`||M78+-bjKxat6qsQZQ}!8kP#DJ1={Kg>5UHQK?J?s zuk>j?2tcvccu)D-kC|t!V-B}(KLiQ%N-HC$a7JoO+`MRXU^PDv6@?2PK+@wWAv6ho3}v7dObnL_Bf2%X~Vtetl_v zET>8SC5z?>nHx%<{*K8_@@(cwvIncQZY4A;=~sN;d8+SLbeI`&cgj9f;WPhy%6C&vrr8&2+Qm6qi8h&opnFiBKSh@pwRBDgjD-gmgX zvBwghKKFW^=4&$D7wUS)Ip~9ALL})(Eq~KaE9{N1*k@Uw_r1GEf%p0Q+~EK1^pN`ECW8kOfdt>g>03{3+C-%t-z#Pj||0<`83W(!g}0)*B; zh2Dq}Cp*({OMpFi7?)Ncqq7a$4~I||N^%_@teG+6Ix5LLHR}dq7g&=JYY=fsCTP6* zPSR?|7NAy2I@GGKsd-&re{c+UQ+8K1f?)n4{JCzGyrM!%*qHzx0SMU{4bnw9I4`-(&IWX4b?; z4u4g{;#uHex4gVslqJa{jkvFShD*HSaA$wqA@Dh zuU~)FJKghZm(&Z*n){bc)7%^#2^p0v9l1H3g0gl+^fr*$sG4mz3y3!eRiI9*gugH^ zz2>ENHm9O8*+@g^F%&=Uh(`Q3t>CfdtL@=ZKnog3LXNJ+##p9am(T02G2EQn_tp9& z%qdWkQx;xt`8GQ35~KJFi*isL;GWI5l`=@#amfg4Fe{)HBSh;Y6*Jyj?p!Altynn~ zWw8Spv-jqona!tG%P-^Ngna%v1*(^2(N-I^`XC^I3SR`g!HAD zI(-8J7WDLuB|BrC?p+y{qN6l|?b0^@gYGgS0?<~x;-+RRKtdZJjPC;j^_HT>PPJ~5 zWlM{RPDhi-4M3Q>P+Krke{8tcD!)ohwH%Lsq&Sb&{9nr7Q~&%37c3Y zZWFX#geL--bHoEA{3XiUtga)D($?OdheGn z{O%&BpW*OcH!v_3-!I$s-qrJK(Z!hAA1beMCcbYIA2=FG&P21tQ#n-3H5;oa*MG*e z+o3U?DQ>bQ}!1 zr(@$^5(7-B*X~DD@u-y5JTX(rl(NooefY9xN z&zr~ImFAgD6jbR&wrDbDnbTyMZ!-wqp|&eC_k1?rwbynv&PNrgI(Cths{MnaAzpXP7OCn_FuWD*AH$@Z^7SqOBqzhg2R|bc znJdvX+%09_Ml1EuYefGgmGeNuLdkW3B)u$Qu47gOWHY>io3jVE_Mj675>03aNNgC5 z9JJ@9BwolYVV(gpf_jWvAt)2qavDye;+e8)#8}W)%jD~s^(4ewdkvpL6i8mON|u(K zRD3{Uqdra`4!&;8lT#$Af0V)1o->;k9HM=-{?Ne?b z5z933!p!L9-e1=jXKEswO@#@BipZe#Di0>^>9MgfJ|P98HBbo1nz@Xo0kwJ%X1F{p zjW5?_h9`ghB1d0xnPEG=1Q_uQvb$W$i+%`rt&Hr0JrKniGLzh7(wy+PNguPWYU#&R zwEgH*(dqtNxXbeD`^-{z$@yuQTeq-T;GRN~Z)oUVXNfp>i|mfm$Nlfk&;K{6A_5gg za&&-Gx{96|n0{ds_*hgVD;!mWvS-&WuUc`tbKaN!gQ?O*r!FYX@d;2up5nb;Y&xY9 zIx*?JvCu^{WzdsEwT-1JQAmv4)$eMXT+lgegYoPrz2#=&FtEd04i2OpqEQBS`Iw5u zT2F-Ta#}oAG>Ui@=ubuqkq;Pn(0hH)hFAQ8P>2waAG{?sm>-F6B|$6W++a^#`mgF{ z3a3+~wNt^PC*K&)O0yVEDYO6GxWz)^0Z#0Li_QyEN2v?T`LE_BU))g_@7mtTYaBaC zF=jE>HLj%o(IH(c+%&_gpgUSe)HFKbht& z|5=+E+)dH;`+b|Gn4qR6v#XKP#s#WsK|%JQTP}|N==v(Y+_ts7X=LZQGgteOm5$Na ztAPuzuPc=I!h~L3w=Xgqe$;2FyF* zF1{hot{Z>6#A#C1qMepmTuREEZ#X7|GCqChv0)+Wd{%)IC!Q<6MvLYnn?O=7T~QIH z)zO|*!WV&PHR2|9<1@Dj=zZ@pJ#AJcxRaS;hro&Nb%VE<5iU>U6TsM@s@8g0!0<+$ zo#f#`L6GvHuhGnhs}v1M`ACqpTCHOkx|BFPNAI7A-EuNB%itK;NXkZNW{-^^QN#BxxvlH-<`;{p1&B*r5{+@zOv$iSq#ypGE(u6)6>(s zCIe@wd|1e_cZ0~b25g(Am4P}THkz>atA3s2#&@Z@`+GYk7*L6gbI-$2(G(cCx?v<( z(b>s}>WAxcws&CjTixb$inMI9#@Ko=nV1%aW9-W+@t)yZ!XRPic);}QKS)y+l}k%X z*72O~98f$$VMk0JZ8J+))KbIiy1WFeP3TCOR)*QOz!|3lsaC8geZ1k+Z{NQCn_;*? zO{6f+GsM5cUgp~Jt+jGYRYp!ud*ObK>MK3*YG!`~9uUN9aDU*aU@(1<$o;_rO?o}i zG7-N+slo0bg>4-Z|MY~%E2P4jM&nM3FjhyMLy=(G-MwwaOIy6M^Q zEkK)2KQ?n{%a(6g)5Mcy+me{dnkLn@vDK*$`Crq=YIuF_c8h#2+@bGc*H~7)J@ChW z{lu-|l!wXOG7JNXSDqw3xg{QWOpRU6$M0^IzgFqfZf9ymhCQ?obJoW9$P^ zZEc%&PG}w#JZUoVd(z1+Me0^}&AHrfHe&HfKck|faDlQuQD>k}o|EbRO=dcB zqqi+z(mK_7A~5aX=a4(R=dtz+{+;^uLtm{8pL$l7M!paYrE(}beZp3hT!+gcArXYWWnu1V$^g=*!u95=es)xM)s||{{k&K zoIMw~8D!CEK-tOSq)tcf<|#$Y7=Na*5jX+ZX1YeDo3O6nq{FcfpX=Wrd6>v;Dax8D zS#+8Ex`+qBLG<-$oz_SqB@kJN#Y5>o2HgCsFDCll4^s(tBoH{B?u5vMWQS04b#Y$a zeL$52&nz1{XwG z&*$jKOR^UzvIo|igf*JsKPf_&RHsW?hV{?AF)Nx6JCyiK_3(3<9GwR#R$|@c5~(+cdayitD_b05GeHjAYJ*xz8M+EfkPy9T6gzw z#;Fd2zvE^KK*huJVBYmuY;i3$y4tP6O_UYab%H^*+zYey)~yxkSyV5CAW*o4?D?f8 zy+Ih4L4vW}cj=6E?hx^HzA|w(M~4>rMPgJsL{|YU>-X(TT!EZU0J1OnKa}P8clWGw zv3}FoybV?M(zIdA@XqQAz)$$Page@!dy!>NX9T=~Fp3ijV)o!2fPqZ9ZtaWmHJd-v zto_dk-3*Wt1O}s_MPaqmIDv`?H??kR+jk|B%e|2_Jk-8w3f+831EePZ?pi!8;3j{c z)zEC?Gk0c1+{?~Zf^KY!d5*DhH7_sz%-Xy#59P5-%Unms&06`#0=${}Ye+_e4b8-- z*4J`}5o`Q^!%DwNO}P45?h1owIwNh7KJ%kp4M#ZW15E7P z**d!SXYU&LIaESxmMkmS&uGuzA+RwgW1`CQ-D4@b`Q-aG&#QVW%Cy@i-PgEnZDs#` z5>&a=rOXoaCB0Md&(d?Hn%N)rUP1DbySk6bJtH^D5#JN_^zA~(AsLqv$#%WPd znzP$T@8?|cWOF87Lq6TD1$jGk0?HqpU__mIBXhBi%S`PTvHL2f9_|m#~Qxsm?+tn zvM)12Hs^_@q<{ar;H1z3=Divt`r_AMNJtqPdWs3ggpX96yM=V&mdX4 z2Q&v(QpUu5Yg$b3GJPm0;83Iocw+ZzZ=4L;$|HD^kVt!8J2$VkL) zG}KMdy`mv=CZQmgq3fpC`zcjVamKq+;Ag=d$3Akd6KvZ~H5Z)nY~{VR^g+JH&W85b zm(r=z6J+%QMpIyYJ`UC$V4|7X9Q;vK_kgP5IL_-(@xVH3&MnHgyW4`ScYb!Z&QV&I zvYnZhU0iYSQm^Yx+WW6)TVzUwPo8E#=!sndDf5i|{L7=!k5scCyJYY7=6*6%ClN9s z${Acw#-U>LeKJ8eyYkCP&^g0h2bh?W>txDCT~C;0p2_ASeeijpCWkd!ruB9!WozLB*FW)u*IckWQBGvs{u z@CY0Un_I5!+Y%a`cT=VBNipw$?2+RNt#p$#fAny@F49>8MsRd)1ga3zKg;X$%cSDW z*h5m&^YuceY~yzIFXx{7Sftp0_;#t?Orak8MtOHHN39dAqDDCQ3+GH@I#D)4Q)_D933JTpjB)68r*kz07$yxluxY2of!yprZ~ zVb~A=`t1v|p^LPcE?BPntz&YFKxpJ3YQ#bp;!=LCQHjjPQ`<6G4;I{)Ho=F)#xR`&FkxNSz-p{#LqWhfX&n?L{`lfdM7Q0dgEb>?|s%);rZ?UikkLksz z4?Wje21>1b;p0`_9EO8OoXyx?d)o@tpiHOF@}{vJ~@xDt`nvfP1Q`_lej60xE(x zb<%KVn-{;k`IqCYLB?pm09FAFg2dFwNAN@`mT(d2grhnJ3R5XH-&9%^^dhXHDO5U` zq^L*j;y4}+2J^(~u7dJYA=S36CQ-vAHb4=mNbWGO`=k?>*t@d1^G17T&@4lbbWKAPd#$?fP zbC#9cqqOSpr5!;tCE6aX!+(Ug`bX?tPY1_*I(qZ}fg>^~Bk(I3TM6>t;u(A*UdMQES+p>>1ymzo`pP@RF~|$^_Em#Z|tvqAkzg(dc70(J}V?J_&T!o|f8*X-AZHIl5Ko2QAq)>>TWXSB~5+ zBpNxtqm<+F7T2#5dN>}H6f_+Qj2}S@L zS>iSTIi@@ZX}np>@;|%p2DV=Nlp%QCG$2;q0Zwmp#%R^Aftp4);h?1T;udHDrjJE^ z=h4fgKZ$Xtf~$)g01@D}WRjOSyG^>r56r@hZnJA7?A>)ID7`AkjC-;4ZvV8Fa=JE< z3jsQaJ@i?FYY%ZTVcYJDcUJsT8_*t{S1oIQQpVUh`qz3uPOhGtrpS+_6zVs)Y;oPA zQQv)A=hIMG+@KD-7VcyCiE!-!h0N$XuhuJ{^b#XII`k8kYFBOV_t&_-T{Djh9lT9w z!TpNuLpnQk$kePn{@9qTrm>xekaXtHyd|<0h)PAvSo4vI#d#xNR1i21=tAqqZO=|@ z9`EFR+Z=4og*FZS&cAF8x#b5zQPD=LR5UI5RpZaTyX`Uuw|?Ot(IAYPO&m!S#q;lUU_-NjMksoJN97na zj0^Db$!WX+Pdap~dT+4TP*wbQ>XfEUGA*m3QfU?!rz_C;7l=m9*}1eO%BS!3e*}Cu z4?O~K4jerIg|OW8`|lO$_R6DWA;(aS|3!!5R=7~oCbX7j{ttc``W*YNi4z5{Jfqs| zZb#EiEFR1+zt>!gyorCAUxAy-)mFawv90HN7O7RggC%66PZp}AZrd5ek|Am z6**CG-MzB<-E29_IGWWnQa3e)DD3k`CRezk^5a+{(zbZ9+4zS^UhAdsl}#CenaIb( zlUg^P3?^s_wUKyC!#743Cm#2opI?26`fC2QY(l~Fu0V}bC169IxTdNe8q7|h=)}O! zty;#&l8go5WSJ~56>K%dy=WrJPx-04Zu{PKkmoCvLF)>Dj>vm1MIZCROM5=xDk1Z2 z*iyH3>?lfUXWd>dq?#f+%2PDVQ*o<7@50>Q%{eB08K#8Kl|U+cU|j^ARqJ=%ukcoi zVp-z;;=zk`T{*pN6|8tLf&8c+@f9O!C-K(t;p1jI5|3^{%X|cM3NAQFjxz2y`}VqR zysH=;h|RWtiP>aiF4K1XPi^7cb}Og?QfMZeNXj(Gt=#A7A zCqPFANJC-%!imQFoQIBj9$cZ?e;Dom=-c$xU*{_?%K(>!UMrLg#N*djl=|#if$!vB zZ5Zx7q%a^qdN8?v6HF$_C z`3gnUYE`@==kdCKme-N_Mats>;FsD7nv=}p&Mn{Wn)ug?@g(Y-Xjwru;a0nO5dt$s zb9?8OQ=SkmNO4AL8i})KIP=JD{XRk3JUDLWG)yhNNKds^b)rD#xHkGplRUd#f!u4` zxcR_pLUhxTQNw6no6j?ra}8LGHb^k!36Y7~^<@ZOA zkF}L{2&a%!K!L(MG?lQJF4nrfbyb`U8-s8KlgpvjY|ZY&`Fq*GZS>A|EMo+E5rV-3 z5FZ|{rM#KH8={!0HhN@O6M1fNj9%&c)<+gT{0|nOyvIpWHQ1SJ{*7$ZbxNU3V*W`p zzFPn5XLE0+t6ax??(o&{a+B?W>9Hl=tq8MF(FLuzCyA;VT_&*Ppx`Sz*F@h0Mv zpNhundFIWVo4d0U_Dp(gP3WfkX473fy%ySMM5igmBs*+m!=qcATqMC`Y~oxh9k5fh=k6-fk!Bd`&~`CDc1O z$@BB21{;p5vwYk|x6;f8r3814wQd!e_2RcLG-Bm zUcFjfx#Yjq`T3B6lJz_w%H!I{l7$(ZUDMOjGS5hjqJj8mo^0{cZAE$6!|YHm-?%;l zOK=HlA4mu-`?=%P=*#V7+m1fop{0h`O*}A6{jykgQt+v{F*|e+@29XA zW^>&5{Jf-u9O6L}xcH))pHWgu?iWTrn4dn4frI3t8(J*H{ktBkw^3rP*EW$7wp^&S z`W6AX*^><=pmk&ssS$?y{!H{dam>(g9=@Z$E%^MX3WRP4_fOjk^sFb-6fxAEoA;}3 zb}#CmCK*^m@0&b}=SKE}`_1_Czi|24esJ4e=duKSLfaJdy*ZKX?P4(F`_qi* zQ>Kjjr^|+9Dv^<^nk=n+zM!jWN^?w|7~-!OR<6E1(BeozcYWWhEzh**tz{D%*M4(+ zOOcl-38z^yB%s$OI^5e>xUcKrFuk}$>oRfoO$YSQ9?67NWQ z#S}v?4Fw{~Bg1O1HVV$ zTaqvlc3a#`0vtC7qJQ|D*p&wUavL1CR2KJL>z3VG?cL`5>sm)KBJK!!a8E@tbBP{v zI;{D@qjeP^%#e4RN+e$K8>}R#C~TR^V!fFrZ0=)`yx3bBD&IDVqO^Gf>By76{KyK1#G{gVI&+!6^VmNnXRCj7+o$~ByAQ7* z$qYLJn4q!R zN+7&lZa=%1!dN0H!+B7h@p)K^qV40VmpUfU!$4v}hC7K|s=Z6R?WS{nMa@ayCfIxB zp`=H+CHY_!-K%am+x!n7miWK2Ri_p4xSP^zkEU%Nf zAiRGNIyraS!zB1^oOIl@2D3H}q;^f<6Z@?G6oII4Z+A}imXNL414sQzm0m9^*H0VF zX#I&@BXzBaWF*wTKs$_UKmPEQ$z%*HFuxSEG0LBkRI+ICePcE?dLB15ZbPu_@&+0b ziKp_bPD7PLR*~R(;@dW)>gAaJf|;gRJc?-^0(z`M+zp}m`4tryS3y?Q2_P%?^O3Rv zyHbWLGJ9XT6`k%&LW>7U#Eds@r~uLSs6~>+^>}M8Y%XkU^q1Js_^BveiRDf$D2h<{ z#t_j2_?S%9RSuQcL=b-9s<%7S!dUTealk88@V$X5@AdqAaOObA(aGbEv|i*)zt0of zO8yIdQAoF+xTSTB#ZFyqx7$r9c!2@!kdbTrD|-4kzTa;aZgWI%W)96{ndC`Iq%ZOI zb6;^&=!sAPt7#{zCXuKvb+=6SZrqV#Gx|q^$`Q*Yo)GAWYu!^V9V-?SUkFgb4+%Pk8Sq2jQQ-u z(J8U%Pwxkq3cVRQ$MlvW0#+yk5p?7tQ|)t8x!?`6=I!gQ% z(@rt1Zuz(?QWJ=7i)w~hp5(L zRU8N&p3~0lRjV7WOmV;<91tpk>0M1kCLmufyc5h@Zqi>At54pHdGq>QUEtPUdBhT= zz z{7#B_Iev>GJOFfFq>`dvN)j6Xfvb$H6;ADhv#KaXE8ulawM*)D0!9szOMbFMr{Bv# z=#|PL9EId*Xx}+eudr)XiRNBBS-D=Vd>vz$!Fd4IBSRG6quFDq2>`9uL*S1LSEsH7%9J=>C=MBSJ zTFW>&ecR#XkSob8xI|bNn#dODeF!(l40G$d$l|52}@{;4T{v?fp&qoT+M&wK<2?w7H*JM1U77RJ;=kxd; zalP2}IIsK(nQpnX9L!bcqM^49t_vScdIWJCIz4nlD=Yby7}wGo(JO4<3HxGB@H$ia zG&K76A3#GhWmPoQPnfi4Jo|N9s_0-dN>y}2GzZ2O58iC3T4B*L>z;ZB(K%|AlFG^m zBoZve+$}7f)4K<3MTVH$?ez4gb{MG=s4HYL;mf)?ze8#3w;TYw}ihC7nBybHWl zXNzIuBFixW9(e2%6UaBo6S%GOGGW1dvL*0Mi5FW~pN;zwsMLUB(Q6qKcS+YT>(K?6j9l~S&I!e8RU zgu#qH8~yV#e&n!;RrKqXOJi>YH7Sf8#FoRM}Idqxk*hkvW5(+H+S`RyVaG$vLO((dNcrbX?6uv&4lEabMf#UP-nC zdUi+nh_X~C=hNZy>aFZccnH}HHe`iN+?<5&rMru#NtJP=6+E2;HsDvJ6h4b209Kf4 zNr7eMUC`;7p<-9Ka*JzYJFBVQmzmI4|3|3&-6Lq*E6*96@|wfAL6uPD%CUNeBfRKq zYu!e$Utu_aM=p^mb_7VVY}3BzdnvNu@<5B-ntAK|I;EBKSC?cOVckZ5<<<-U6iP=t z8zg_NZm@6)#EM6~8~4x`W7BMee$Ea0eOUu7kCG}mm3p0VcRiDkS=I#2IAO+j!}JLb#vQU;sc(f{9p>(!wD+)c3A_p!SBoK0W^amtn@y11C-;| zAtp`Tbm7h;BlWT!QJO+=!rc|tb;Y%f7jQN*qa8teVq3QGC?-^(exg!!%v5n}lRTUz z){`$fspl(dT1sWFN;G5}6lIB{SBn=0TTX@CFrG!kY{|)$s%Ks_U>GTj=1~j2Vthis zMGM`ZoRN2E7RS|BD3BWrcEp^?NIWY&)HD1P!sV#QY z{^#B~+rSCC(#5Xx=Mw;V`zyzqONMtl*(L0Gc!@hwGdXYr$nnGO=SdxxLRTxN7^vp5 z4bg{y8Y>-mVo(uQRQ}l=rbP{KJI}|NYtwx=RbRCK52cL^ zx<(jjDwKWGskhBZ8yEM(!y-UOiTwnK29MNbqRlSUy|P{3ni*m>lh9d(kgm#KDXDfE zC(JZ&@456Jxm?K9#+5B$YNCt1Q{GUcM18fIR};Mjh=sD{U&%HgmcYG(TdF^1u*TeAiC`-tX26Eo2~qSC-#NX{eEWXOQzjo_X37wOZzTtyG6Kcll0Yx-_E!J3ellsq z{Q2%%9mA)!jJY(rRTl^N-6}vmlP?~FU-($I7r%r!vF%(S7>D~IEe*55ep6~|M1A!Xu zTr@eodte2@ebD>a(m~T}*fsDHh33rcjGCFFll(oWD~d*@1(wvt!L7Sd&I|C-L&jse zcL&p2z~nvePR)gY0UdwJC|WbT2D_H^@||G)ct&&|(XV#UQKOzNZlm_UMatf)B11Ja zLjqhskdy2f$*Ou}?ZfExsc)@IL6mHH&-e+*EA4NftSS;EdKRBTB*KZA-a?r{Ex=n+Edm zFS+X|E3UMjK3MVDU4vbVoRsx1Q>Wl~y=DD1#ldv@J4@eH!UC85Y5+z0Fiq(;A&=y0Q)u5VkW{o-A=A2}!h&^Dn31oi=Rt)f=zGCKm_$i~Zrx0ny++Hs)u zPlV3l!h5u<>k{p<0Df@&lFc3D-nPx~-LOX$AO6zTp#S`S-mo;<@{_-U&JL|X-vn0( zL9%8Ftdp_^3pIE~(a)%(lLa4m%y{w!|5dhix46ot!sxU_(Q74R#XfIQ2P4rY$+|F4Jt4?mON>$zIvfNwAVlvmx?XW$EuD3ULJs zL^1{`QIrkv)fBzD!@h+=xsHFAMYw>Kb-q`f>vmh}IfPMc*To^2jh#ZEBpRP6rP-lEa zM8vMx2#PEvtNDY$igc8kx|#=ATafleO@VK`9;vVDb-n+@3iBdv*t)T~{iHM=qie$1 z6(g38JbR^dXvn?Ek{;0OfMZ1WH^^n8xdC;Az!wA}^ah=ExOgRfMkfOc1-*Quk5UT~ z?4!?@zp>jfc^`EcPMz>3LHq}ZR8|`T0tdLpLz3Ft^&kndkxc;vkNR=oivmv!m=Lly z;7Pc_(Q!FUchv@6fY*d}ha7N_bNy&A!_G43avaJc5i)psYkZRK6(gGotTKS+I1A$J z2XZVCk!ow2)NW6BDk7!4-s^t}DwH=i-@FvTYHC-1uFyS#mQwVB2Lv-PhYiRsZ``=# z$7ZEZAMaiXt~dnJk)fA5G-QP+IHiWc!FvY9pXtwhDc9eW8Vx)47=Ee$_%sAT?{mit zxc)Zm{Y+LYw33}@IG=Q z_u$Zg@9Ifb22l2I-zYs~dC!{O1$8-{e3AOXw&9FZ1?pyf((kN>w*D7*B5X~`p~Iw? z)F@k0s;W^eESRW2(mg9xK~gZPexY7y(&S&H#v)9;5y;Ny3*`#hrj0S_AZy0ub;6%7 zjwSxreDZ;r#sgsQo_v9xs90?N?Hoi8zSL3&jt7@)zRFc%Z z*a;#VZb7Y^t4DS6txM~C?YT3pSa6S#zsl6!YB?rV7ENmWzxYc`ewfI0|6#Wik*YG* zP0yhBoqMHm;i;Ry?SvxFNOgU5`KJC8r!i(>L3#bPyK$+#F~Wd%@_fp|XJ&JKjG0e< z)<}kakN%8&L`N5=N&l~fNl8mIq2w7euYrCJW7xfA*FzIDsc*`h6OPdwZWaJ3gR9OA zyn}1eSo)4@lmhfZ>Vk|!DRzeFKO|xA-!^=Z{(isg3wNYxkp#A8Gm50(2Of)H-SqlXh56}5o@U#9K;pLR z+6aG{?iJBzkJ&*$Tg&qRNCDto%IfAf?4txzb(r%#kSc)in3tc(8qnNFI_Yj`%|BaN z_Pf!XhM;~p=7r<~GE4Mm^l&?Ptm4n;3l=BYXUXGhgPuR6?Q_P_^3b!7CHlH+=aIDjz zZb}YE1$YGr>3VaN;9ERaeU5-M8sdhj4i%{Cuu^a+(r zXHAe<#bI5=&+@U`!>*VOud)A${41%*yjBUC3c3u7Bm_*r#N@UJtuZ{(R;A*?dd=s$ zs;{k|-}f7$4j_rBjtTILRElg+t68-ojs=1PsPCRiu;u=EEpfd5Sox8Mc2H%YN!GxF zFPe7!A{6r*)h;}7x@|EnBnz?s@2V5~nA}D|{GCl`8&x~N-UyRk;GdadVya>H;}gWm zUsnHk_)rTxxRLq1md31qVSJKnVuI6XM`DSUu4nzK-(xEiN=EOak4)6c213P;-e|S~ zOhTlXd{Gj2CRtW4&Po9GJgZ*I?+T3R8-w?6dN$bTgtdjQ#2G#UVP{lu0?wi2gQ@gv zELzuWWuCaXs^3v^BAs?BAFSvZNS$qWyLnNfAB_vj3o@}Qb=UG)>=v4?{agQWrLp*( zWh8DB6g1qDz26{0vgNR@$velJSvO$T!O;n~DFp#FXs-!7N9&f2KxjfC?$YRIdUj~1 zzUXo7LpA&(ZPUukG*mfN&!NfzcfPmggZx$?7S0-uvfMP|hhIP6PQAjh7Wc@cP4@ou zGL#?(4U8#v#YSWDxvQwHGx5VTmn31ddMU5^%Q1uAWEx_M(E_jK+Ai6pZ=K(j`+WU% zc;N;|dxb5Bvk~WR%dUr;SS$c)ZX4!iI`cpWYim$9S5@5OCvq?acQmq7fc(h>I4WcH zpq2#$fx9if?R(fiJ&QTE$PO;&FOLz{?fCc;1ET;zL)?OeTS>`iNP1|^rSI~d$dt3L z_e8VyN9y1uv_jX_zuptBpJ3`~FnnYZCrpp~JM8)gF=hv(GdZy8I#?;lL|>2yIcHX3 zID@1(w5>=<0;nc*`$pkb=&(RO;K!xaNZhWs*E_JQHS|Hjo6!JeerzHDlX#1`a$U_> zvuO=WwS;-?(iv6U1Lc^)L=L{zggbg@P~FT7Au_my!EjpPV)#|lHN~$svAbQiU`b$H zGUg!KSS`KXr~188FAW&TIuyuX_p)^4c?rWmgq;}R8`AK8+vvi_oGZuHzO_r_%|DpV zsIJ&fQ4EbFm@;s8X@}A~FmMEdMl2It(4bAAY$RFSL5Ba!ABh5V`Vy_q)cA0Mbd+-b z*^a?gSv^0L*N+|G13YYd3Rw^bh9yroyj$+Thu1*LUt-#N%JGSON^v8tCGAXQx1e$1YjlFzk73rd_(Za5xN2F}X5ugY@!+ml9AGST)E`CD6+9smgK`W%xV2zs3Q-L% zspKcjTob38hxA?KIJ*AN?zDdbnLUoGCW|&-zho-U8j>ZRbYHEq-Tc{H8O1poRwIkz zEO8(N@8n}B6kh&5P{Nb9WS~LMy{PDa$W16eg*Rr=&7~mo^$l``j4J? zL#?6L@OWtO(ttyH(dk}!l$H1a3`Y*PnDSh^=Pg1pizS8z?ZYvC%8R)@%OK7OiO6Q9 zIzGuosgcJJO3R;Avof6%NJ`O%Mjdr%uhSzL9owqmxrhDJaJb4jjA&r~;Jc+&e=zO% zIIy!g2Q1n~c2L+`IEdOc(^-Dlr4aI}UG)l21iEjKLg=gcyFLJ21hVoG#{VmUKhw^XXB;iNl)8%;u7kr-!Q#l=J?tEhFg2Yx8RaW@;VABgE5B zrQa+*{7U!W2mi>ztkfMf{s@)7H(L6($a_)79y@a0ZR`5EpfF8R#L42}jNuuL)Xu^u zbl~)gx*NXu)T-QzKuFtt2Uyry}5S!m!A>)b?z;wus=v;mpHlUcs75NX$fT2YHwz) zh-o{2@y~I0Qzwli9pMaK8Yq-61zrjX45}x&#fuA#EbeBFf-Cmo${LGUZY~!S?K`H? zhq4q2ZP#ShsMS;t@Krd|#B)O~zzx(vuw53z3z|Y+o#E%Crik?6lQYvA%Wqt=o_eWi ztXV(j*rNE$FTlR)_vdWeqOu)0#=#OH)HJf&shMf+@!WO+KVRRrH*JVbqdK#Tl9;o2 zSC}4q6bCK=p#%+F&F^cQ&mx~6q$uPjg(uouvTF)f;}+Ma0CA>t<*;wu(6O&L+2YRLI7cUx-fdB-I+sBJn;HYjYWV2|=V6Jyi z(tUE0Qp2U32TM~=^I*&lej%k@?az<1Py;)I5C^x#$9hbOi-p${JF}yN&h*@tjL+}8 zCOuX!DW`V616JL@-DZV&nxToG<2OBnPEw>BIwv06%EQKWzs(M9Cfdm%7Z0ws_BhX1 zP=cLmi{ zl^J|wVCb=$iB0>Ph_mvQ?;NL)nUWiZejg15)Zozf@ydNBG64_8OXK4u-AJ%s;QgQA@gFSFY~>Gd*fqX~N=`zG}j=gE6E*?jMKzvZSYy;H~RrbN>3 zZ^QJ@b{9742-|Qw>?0j{Wd!-FjdCxyQ3Lrq~{Vf=}gdhXO=YGmkq_x9*;4G0tqT$gsI ze0%ADQDF^aBmw#%va2^vdo2d7p|z@-0LxQ~H_TyGrw2>yKEVhBAflL}1@sF~%&A2K z;tilQ-qnB9PQ?@y-Ss?qwPx4eUQyL3T8+Jl41go|_WtF2@@l9^JIUVRd@i)YZ{JF~ zdB5d~3ce0Jq1)--@yDs1kAin~z08@ziCj|*F>r8Pi=gyAjf|7{<%vxyrZ%C;Kd^ML z(QzS>4K({)dw9F-WKms*!9czKdta~2SyAarcU>-pRzb*s-H(Ncx)C$78vp_5eR(&r z>~|QtF0>wJq$0r875BSPvD|gO6eJP%k=t|?2@J4(qSM84b}ePkPPCNdNO{>9LD^y$ zbJeC3WCh63)J?^ZN5DtRPsOCvEc|%49?$%ID)4yL-t?~B2y8}h5nScmf@~V{w{=EP z=pu8&W|4)WrTv3j`v*^@r)U2~)X6z}B_$2dHm7{`7J)rBf$0Ur-h041a9p-NsWwl-sb!*CgX9B*g{(E>6}PKfA%`@x<=HW*pL^Em&-W2<{L2?}h%$0)vj z2|vhq>+g&IQbV3o6xMAX|G{pyL*^Pp*2b|u5yhHaoS?_4X0JTYHyAHJdaaGrL9s82O+v)g)75oNdN=yrgTnMUtg{QPu` z>d$LXWC^RrYjV8^K~w=0(TfB3bVX|>}gD+NER5({MJ=qLcG3G1E; z9<&-vtaF}9A!R9Vl27sE?%1o#%J52v;d<7qJ1!(nx7^Qp z%+j_ptXv@Ap@)ME-P~8|vz(T3vc(XnIatb3f(%U_e%7ETb=P+M=)D}vy<#}G(4sSO znV2O~>{CeO9^Q|Zf}E%U4;)&f9NM^_em1x)^fhrvUIiX+UA6%ld}p6 zJ@JgQE{22FE4$=0FJ`3x7D=YYbVZJsQJ(zrRdX? zn0JUinvd%d!;^r44QMrdH^5d&agi5VP4YYqzBJKie9m5Y^EXD`WVK4)m>stOSwWJ} z_A%HXo@8RS16vF^Af#Z=fq)lX-j9wFdO}3ow#A>!n7~FuuL9-2{-Bd$THu{a0wE3A ze|ckDv6w^jMVn^R1n97u@#~<6g27iZdyvy3nk+F5cQM_LwS%QJ7cXO4wHvBZvt8aj* z@6=W_3xj9yr@ZgO)J$v%Q`GpXMi=N<2m^xj7yIKsU%fhcQ)uI?O4e7p#!ME8lP4#i z9ZJsoCsf2`=jd(wW;XhQ=9hgCv4zT-DgRTg%YOkl71$6DkKP^+J4r7_BZvW#yBz3f zFfo#ixyP_wKmM^l3H}uMecEeNjgfqmR>?GbZ+DEB&aeJS*3Z?~`;Z^>awy=+Kko6P zzL3NtSt!0O+s*dKS}DYFu##fwGQTB`E0B9xvNx7%KGmGE;IS)&3K$4Alrv|mdiw0? zBSoY~_6Rw_9xp7@@*K#7PjtU{l5nKiak@~1 zBsbJAFn3$zkaDj+a^?YGAUE>RHzwFf%NS)31fC1Xd6kLr&XpON;7O3bU~HorFN`XR zd`gcSRll;4(TQ)C*tw$l%Ca^=|F2)o1B2A$W12?aE*{`(oLerN;E=ZXdY@|6R`O>X z`x?>?JKis?tRz!3E?qfl9w)iI?dlW1z@PmHUE-oU_VY;d$J~m{>`Vm3rl)NN_AY*} zU1OJdr)zUGUKpGaiDQyWR_fM~hhXXZ&O@L^6_sBvzqML7iY#hx`Bn39i26U&tN%M2 zx4zJmMC)XZ5fFp(lOqJ$*j?5r-!FOJI#Cum;7@ZyRWhyl_omd_X*0gG^oQLus%c#x zC+etf^54jGh+Js?KZ+OlJnmkM}ydFc}u&Zo^OF+1m06 zvs9CwQHF?!64N`Mbe1^_v2T+x=!~E_>|2rRWhj&rRr)d7;>WJg8V$AfkK*i1Hp=PJ zd{w`e2X7omiG5L|5ig8O8fyV14li$tDg`D}p~yHRb*1yypUhx!o0T|GqMP!nN4zjF z>EuLOoZiVd=NLH-DSXPdev&U?E38<~y}BH~DONnQ8fQY`$^0i!rMKvVd`wBZI99nh zd+6|7tG}`%PyYM6vwmCKnbKZMx+v|ED;y?>aW*ZV-V98b{c%?yMm^&=2BD7>_OctX zP(!6aR-?^p_kX|hVI*YtTH3P~c)`eFHD_M;&i`>yOas~^ny{UY+ExEugsT|NDYBmC z#?k84jCFp@7ne&9KC~;ij`8t0bqc+aSilJ+{g2CRdLTg)j45s<;B5)YRnE7bADfR_ z^10g>s8LmH_xdIa^6N{O|B~e&iC|Y3umt+TuFM zcHS$J65IX{KU6KdVw&;>88|Zduhl3)fzcl?a;6*1&Pz(O? z>y&-r026@?2oY-49P5uv>mAEZb$IfS-ra9)3rTfrBs|V%&`N2P-@4)-cr7$jx?qlx zGBiYhn!;$umZ&V%{;fKnTHcJ_-afyMVg-94L+bvU3ogZGson;?k~^mcfJzY>tlphy ze7n3GYaEIYG#4&I5rnAKO+#LzUU`7N+|&1lo#NS)5_N?q+<_m}S4^~hw6;ZFU@q(vR{J-=viD| z+6w7W^K~!?BTEKW?;Qu2q}Fb=j)q{tsS0)N8V^C6&8QnsOwosP!mX6SaNnrC?cEC( zjy^yd9k>JU>KL@%zweK%vy^{Dq7VQbv^hX=ZGZGs72T7Y^-x|yj2NXo#FI1LS8qG* z92#svnhPp&I2sP{Wg&~QWi`L{>TyJ?z} z!V4l-@`$mo7hktfbr!t+J}oTE4Jm`)}5l2d6(44QAPjbQJiH|@(xCirp~hEnuZ`d&RD7V$$|q)eqjy;_9YWcR5a&E8@DqSBplayIe+KSBWuF;lrcMEy+CnL z=h^LKWK$))v5Q`~NGR4;m*mlM%1rp@jQ+5~bVADKg&$R~a*%%wWa{fwg4q1JKQd2K zDs;1cVI~(jd9Y=iL+JKnk?k4IX99y~uUC1>O@0!ew~Dgn0{G1YMSGKJid1x{r;pMD zm((PCPCtHG{({-9GDd>t_c|VaWy#OK7##PCRKdiuMSsVZ(KhPEDw?L}t9-s0*GZAh zKIi3mfSq?VU#F#w+^5UySlr*f`P+z9+>n$m**@>11Tj~qL$AZ@BLXbW#Q21OvVmt5 zd#+T`JZL+%NaK9vgv1V988qzkwnqJ4kMrM{cPhjf=UT)q{>mGQb97$+6X-CaoqDy_ z?eQ>H(dejc%SHe6^E6@_@8u0d#d_TsF9@U@-Acr8xYyPDOJ*kxwZY(nKyU z{Yb`tq^Xkt?()*Pf# z!l2vhnR2Vlnv3aEp{azvUxS72Vr{?X$OJZmey=7%q?uf6Js$|ui?^}IwhsKM%~Kg( zz7Kl_y4m?og<(`BAaHVQJE+>x9iS<|xzY6X;%%Sz#hoGwy8iEEKp8@o3FsF7LVd#s zg6H|W@Uti1HElWOc6702f~VlE1dVJrw%CtNwxLAYBsi2XejN3>`kG5eHm$o&MM55; z_8rJ$+~10(XpDLs;QO|*ao@QWqUM$#HOxjUq8T4)K1vFU=@>?i^PK&8tz!XcXUVQR zI{&tRaPZ%vTYd^4_%pM(`Dr=KV<_l@#QR_JDBHk&qHON)b82HES2Of^P(y>{Nhs)+ zpGgaReiHEw8ntn>1kbCM;`x+K@;_2JXT?$@({2h^|CiXT)~clbJJ*vfyJ`6uDXERg zFuo2eD<}p9lAvn+KpTBNGHgVT>y%zo6~8v~*;3z8!mvx)DDQ*}_c1OO7oPD#tD)SF z#9|u8eO1&3y_wb1=TrWx!AK*y#FhDLK-E|E*X)Z2m9?7cE8flmg{v7j1GW1t`9y@jTrIfi@r@n0m)ziocwJ*p@GHB zW@&2YD9;rB!??7F+C+c9mND1yyQDa!jQ%N49IRX!9aIG7J-MnQf^B=Crp&SL3=__l zo5a<^6GLWyy{p}*vS$7EdH$hhM?r~;7dnTQ=*yvL)FykQD0SnLO6PX*M5Dh3TY#Dk zdOU{KvtsqZq&3)0V18j@_X>Sb*%_uZsfY}5Rkdi<+=U^y?g0COD%2zRy9=B*QrVat4&Ux6&yT<6M-!yS#EAKDY!ARrhF^Jsx;JSh8M~(KD z1A2e)&vlV}Yn`By>5(K%k3NMAv=|&5+Q@O_9lo_x4V`wU1L&4EQCQ%HJRlEkA-8_f zg;#r*KV2E>DUZwh3>@f?n4`$`)=}#ga#RUGYGpTGdBkrPNmroYhPvnjoG%_JkmC%{HCxjdSNI7=KX5$i!1CtN{maZ#CDs* zUa6O`U04qyYdMyhytLVeUHeXR{`_4h!I9A7z^AHQ+ zwX(GL@82x9THf(88RzxEPr-Saomyi!{mWcTa2F+=0+UOL5)bl+SGgvIZ!nTZDVN@l zd(cs`L>@_TPI_(^wqU{WF~@SBCIKNH;y374sB}bGKeXtXWuOCYx*SbnVheX}oJiQt zL@f|SX=+w-@NV4&@u3B0ZJM_3P7YZ{y8% zg&~- z0atVcWig*>gm)|3Q0W)_b1x^e?>xL!gIso{k_hP84ZC5yFs@GIC%ahnt^12PKj{fL z1&-dPdyf9G(9=bj6M;@Iu70}x&V2K;VbWAUrQlRM4JCy`(fE63;Smw|Y0nlTJ5gq2 ztZ2AQQfJu2%*^4(E4dL=1<2tC;tdrdd1wOFV&?j;;cy(hr~~0_hlJI+!-V&U&~|o) zEx=u(TSr~=wR68y{Of3k+=GAt?teeOY*_&6pGZ)0T8o=$X0^#APm-03!(d&TK1S+K zw=bQRj^_V2yGa0gM$UUyu zGPjIss2)|0+r?bbRkuZkUv88GWK&hjO9#U1vIfNW1Bjubz8mr+{bBLJx`Z{;Od~jr zB1-3JFTTlqSG5?tU>S2*_a0JX&}chsdsDf;jkVK34x+bfOCE1ha z=6QaZmaAIfV>DP1pNcrFb_sJ-XNgA_^2Hp1ion&1I2;S350wMI$?rDX;du!af)U=z%?>QV7**cZ@pfXlY4rBM@YbeN zJ}!&gRy;_6r;E#s67avY{C4y<$7Ob!wa?1o0XHp?wCZq=26J@OgN37#^FGi79N;@u z%AVs~*LUUlzOsR6nQ8P~LrXP7(dL5{P}n(_M>^hIyl-Ll( z)rlUmuX6C3`6ry~U|~_4MW-wq$uhRXk&|gI**Lmj1>qN5Y^2ly*8O0}0Z`)5BGe0S zagUc3N?U;F2@+sCiWM1*8nr#o8{Tls;*s{I(e{`l0A;qvw!#EuPOs9n#Plz?ivLSW zC}p1NH?$>DKHmteE0p{)@ZmkDMkdR&YCauVZHB_Iu znd1yqF5#lV=mS-wc=hdC+d(aX6K@F)63^%w*fr(px94i|pcYo+74-Oaw6m=F`Jm=7 zjaqd7*Y~YC71>AAB3vIn%IFNWmu#2yv~*niYPfhjJ_?O3*;x}W=70L<+B6DrkuIP= zRAy=D*AyZcT-Bq>(KtTCC)x28*LhnZ+JI?AicrA`ZPY~kGP z-4rwJ5&OUBi}?I=PeIyy*XxyAB+Dp8+oCr>m$QURy;%rcj5)EHF391Dv+v@h`e=D| zg%L#tT|iOhko&{_8TB-YWS4tp`K|j}K!cx}A^8Q|v|ce>-1_vBx_c~ET=eb7cJUwg zgbGkH?mKch8W)#NGaEAvS8=>b#@5PLrZG+O`W>cTnO<(C@uTKSw*U%gW^HdVmz}M@ zcG*1?YHO-;fac#W=`mbqrqrarHu&XBttj`rQNuap1CxWVsj@)ccizACodEg($oz{Jy8A0fNVbz>@?=w<$vpMdrBGwxVjG3q*Y*V76!D)Nux8Sf|z&%xIz##P;jw(C1MF4V+vrnO5P-0mZdG=7U9hPhT z#Uw62|Mbk#F+_N(s)&tD$P*vc<~#G?Jl%VBe1EiVYXGoRr0t@01kO1XqvAPagh(Rt z@!aeD@3=H8s%Q#EAF+c7$8ql+@w(MCG<%rY>UMWVetyTbt~@P3%G?JG1}D>xn|!Sh zu;7wS7hZg8KOTYv%d^Ep!hS24u5c!ixS4svt$T|n*5xluB9N%K&EJ2ImAJ0mo(`iE zb)r?O9tt8Qv+?@bM-x6Y@;Bvm>$S#Zip$*2qa4wrKl;JwI_>a<$3ez_AsHm=q!C00 z8(GY;+8UkVdo4Rt3KZ@4-XMM*mH1JcU6DDB9t0QIXZLoVug`KvWo2}`BGN-O zMIyM0=)vJWIDjz8p#Q5EX5Dt5ck};}XgxbK`>n0P)<+=gvPDau7Wa!Bjo*GHHDxz# zO0K0SHmwe9kr>;nce=ye{ps(6oS7a5O;*HaC;9LqUKTC-c%3zOjxx_8Y|R~y%LW>i zX07>46v~sgG~W!i&KR1?7@8#>2^Wa_kmmKnG$m_jO7fYHFUK7X?UnGMrZ8_)lHOPb ztVr@qIG8*S?Mx;j6(0u%zo$lN$AO49HXc<Obo2W!Vb5?7w10RV+@Cy}RPoUhy6WmgYdxw2e{_ zerT&xU}0vKGvv!@+H-%rF2_|_?tK!XgAKWEg~g+T%#hL?Wu6vEsz;@Opk-+ z3A`dwWR=T`j$I+aP{i~cI2?H^$n*Tk3O*$J=V5l_|D)=!qpDn^ zu5ozN-3>}8CDJWjA}vw^(p@4Yp-6W~w}7;?fS^cADAFJxASF@)(p|r`&-1>|`+Z~Z z#~Eknmc93Vt!u40=b95lUNWERxPavcT^n6VIij@bz|}#1l!R?(3}=m`FTqMLb-hL^ zSuj*Pi3%Z*Sr9_+&uQP)V91r_$|$|^jIO+k|EVCY+I*@l)mXFabaPjLpVFN`>*Me< z@ZW@Kv}eN`;TyBh9|Qn=v>Rj z%PQx0h9bc}3g9faMyHn(V%xzW-#db^!&HxjxU2!2{`Lf0AL&15UmArA9I*lbyRq4^ zlf1@ACkFR3)l~d5G!RNaXWo6T{x}~3rSwAn*LtOw%58GswVG051mw6~wn$oO-T6_j zi;VaHl!Mn})`GFBvJ+wnfM)eS?c2w=t6SI4zQfz-PsUpO9ZC5DqFij=4i?2MB)5#K z8D%mw_^1zn&z%pfGX2}>k7B2aS8P!-Q$I+j@5Ij4i1afaCWz^=jQLuCQ7{tX9_KQX z6DX5`R8&#);G?~z3)97gt#GFU@862I3x;qe?hVN%auReYF{6@Ex+`Zn;*o*o=h#~U z`{XiSlAcccsF(l;<;}%*mj-ZU|!nlr~Uhpld~# z**Fb?7!rPB#uc*k>6zO$y!HdkV3SiU+a}An#N@+&mINT(jahHlG^BUXRtrE$d83`* zjzgXFM-~1MKW|v4%WlK=lb*lKPbYxY7!U*qqbDD(R~S$lLWa{&KLHnUU};v z`@73oh;lzMNw#kzcz?PCBu?O_7wakYO-&V2?*5a6*qHf@NnZcDjG2z09`&^s@xPH0 zkTkc+KYYS%8TOi~7m+x@bW``L4sHM#?%;tzTT2^wPL%QXZNu)VFH|THzNz_zpW#&( zsMgAZzh34+@6$~SuttGl4-_O<;=Lrpzrg25N7s7jEe})Rr@uFpOhWX>nCnpj?CY^W zocoIe_5S2o2piY+s)gK-oaN~n@BY@R~F+> zootj?DZt8~eJ0!qswkEwS?SXW)cws30t11}S#tPR%89M%A%X+lg_cI;0m}_XK}70D*D~y)fy{rn9p- z|Bc1&IO%+dHOU@WIP`hMP6?(fpp${f&kK}8!<%8|DT$KFpVIT_s0klM+K;?!s7?)>f(vU+*B4;{z5rP#5Jb+v zVV{-MRh%;k_mrz0MT~32@Sp}p|&(D^G-wiokldviPtqM^q4)+5zaHNBa*ct1ZGr%dq3r5r>t@{v}!AU0C2q z5QP9O{vruyZ|@iyWA+iCzzL8qDdalHZ4m(}sAZ+0!5uxS4b& znwpqxx0}AXY)7mat0T5(+v!`r=LtRR^KlHH3ukaRi5b;i6zPl(npOh^65tHZ9W5pw z`3y_rc61S4wa-~^d&}rNBGVxCC%G@5esVH_eSaDU6=1E|y)`pP zEnxnHF%#huJJnjo5U&IFJ8&g6uoSLKtkFyQ?ERsAcTrSP4tjbJE&-ZbMdLW?-|L<5 zuWn2xe)6P*j{@vKK;!i1%bUv>e97Jii+K|icTp+4cY&0llWAa+?OQF5|> z-0y+Rfpr62HiX>=x&(!CJ^X-1ed#9~YxnUw$^tJKgmK% zJ;XYH{Fs00|51Q#VlMrE?kJ!HvEL%b&DZBJ^LmLlVn$3=Qj#9S242orF4!6MxAtbT zh~-c&e0@W%ysh|>2hI(QXR&3tD7#>(xO0R!&LXlxI%6-ER8TCNo`AqNx{?c|`FiFB9(euc}b2&5z{)L@22`@SLZY z3gBbO1MRf&8K;5*x_6$!?w+FgZF7Da`N@N(*c6QDMX4BB;&O`dLeANQUyW)mXO)PvE{}3u|rTws9+%0=`o9Hr|RN;qTq2xIWbpn^_5%HQJY&&ir zgFT!9-CofEGZn}(($P`pKYGhJ^JlI(PTe8gMNWn zEu~!i>m5G(JB{)yPx?rmMPjvWS&&PN|G5^vkA2)KotO%X`c14{0Xz#CF!KozFr$g6 zydQRD=0UD%6~8Z^4&SEp&F>LZ2RS^HXPb%Mc{cSi5QgA@4R=#&db8=YAs=Nlm~B8= zt*xn7JJ0x87myOs7@MKK@NQ^To|E!P=}p+R20I3Tg2#5QMq_5bT?nT2P02j-d!w9a z^-?3=Dct>)4307XZ%9RlhJv&7`;c*28Au(uh43%55=&ucetmUJpqCfF-8_>zQUR8$ zEB*3jSR&s%ws;~=_Vez~%bZY*x2#`eZFtjyd#X-C>8?k<{O^XYe|y9eBOeKRXa_g9 zw+hnx3QQ{VC)X_?XYB6FgkI~Kb32A9U;1YcHHPi#d3DLDdpg%i9WpWR>ypHF6F=-C z!Np*5UEvS22Uk(c2HsGBf8r(ReVt{anm)uMR6BoegC40@=IE4?bNn6@UUU6PG!*Qx zAnXTUcD$|aK8H05o1Xa`Z1s?)X2RC(;S1=IDmatpLw4~c*zh(w&bM$E9e9tGJKcQjgn^qh9@FACtjE?;i z{>3RNLR>5joB}+X22>P%h+qF~VWxXq_803Zz4{o~kRZ)>!4D^(CaF{{%(_d?6V-=k zmg@BUTP{EXw#wA4Pa`A2y6&f9E|$qZRHeNbad6!Q{hLhobi`|I-4wp~w7`Evvz|Yw zdPSqs$0W?uzLLIGeUM*DFGNJqN`*LT(c|J!TTCwKSGn)BJYtqGG{t$C@fD3~S4 zd<=-amE3rn?X&8JhF5t69$acoM>4y=BN7dKj@YD80i70U^bbsss=^ah6P~?~c!kB+ z?jz97Q~Juz`S{d#Sa5)Kk{SB|zdk1xmeNJ=R}w7v?wAGkb+MVa+OJ@l)Z$S#?J@}c zuOZh^(*g!OjgW^H30;O-kL8aIAvHG32vp)|1;~nm|0x7JWX+QIWSho%oTQ$7*Z=%1 z_7PctIW5?bKxygIB(vsbqa5tzkXB#iaaV_%3|^)Sn5>&AH!g zh^Zl9`#aE#xOUR99&JoUsCr(P^`-f|0z`rVy$Qvu!Q8#}C2Ta(wS`aoYN7BY-qA?3 zkODz9>_68Evwk2+;#{~*jNOh-xnilkb~Y=t2OhOxlvFYn$cQa`n~xr!@krQ||N34} zxADwttSxN2Hv=|mD*+ElhZWOg9!;_)zGw&{c!u1AAZuvR=+m8(~b7xOB#8uQtBAqh?^@7CgD|JV>uAo`t}%Waa$n zWYSHo9Y`>Da-zeg+I#vsyXk`(Hlt#ir2gV-M?@1lQfP z`$ZGhae<=8X92J~po@Tx{oXyHY7%C`bOBJem)g&0^aP}>0BG5dlcM?Q#yjE9x1}me zpqSz7*xnyX``}s7Dj$g{H8nV79>mBi&}*&BDu_iB2D(PHw)tnON01)g$xAKZW$@)X z8c|Of$(dOAmKp!aw@%c+N)BqGl{y-*AI_{Yz`{=b6N2{_6u*{Ejp_^klQObOIE6IM z>@h3_-=&znWtOv9ZhZCdc`zo*u%Hd_KRfpSIyH5#IO&c6!TB4r^!i1Sx9ehBz0CO| z*v%#xHLznwtR|yNz7`f}#vb8)3nh2{S*1qX@OTNcGV~N+o2=HEm_&?$lE{d_+ZnUy zJzFq9G>6rEQJ*ILXN*fqeE#~z_v~Ve59T!Zn5unlZ9f_cY6k#V-nFV_e-%=6lPfCT zI<9;0$eTAujW^@h*7UoFNdl(;*nr>Pt%Ua}ru$~T5b&vHR6;W)kG6AhOh#-?jd^$6 zQ>?kKHU^o-jq*l|&g*6!Glk4k`LF4M>gkTrm{cyRQ5;?ZITceo8LgcPKy@2;U{BtI>k9&2W3U z;!nv~YTq1(r)7dJ??3X%6s?fmM^^1A{qU)ltmS7+U0s@VWy=i25{Oa(Bno)G>h3dM z&uOWrP0>?(ukTcVkCWj$^8bE~sJulE>Rj zPm{>rI>sfS_AaX46@+}qhv&RmPkDyQ!GXz#vv^Q^j8Qd9pPX`&bSz|YDezgx&-c@_ z@42EH59^E4Hh)^hOU;4f%YRGU@OOpnF&46&Act6gvC+tiBH zU4`D!^L;E{nmC%i%_`Z=2f(fa45h=-Eu)juGP~{p6lunYO#{-i_$= zn&6gQagb6-<&9VuR@Z6WPACkuO?d0ZPb#Dij>r&N04qE-q|7(o^$!UV(HvZ&zte1N z73h$&WP_Lym>xkIYq)-B+!og!;@Jca_sG0&*aCvtuO>WFQq_!}r+24F2Y<&56@>xa zgKVuQ_!Y1&pf5M6_Oib&;8UXgEqDxjzjR4A5lKW$#lnGq`~L09A97uJ0f3H;zHoeQ zK)3t$UdA)9g@Uf>TdmXixp7YnnPxR4PyI9$I>PS^fcU!N%QP*51@vm~FfmUR|+3)^;sghW0Qd(`UtTv@zl*#Xdx$~10gt7Sg!u~kZpjBzotIHx*x)Z+T z>XT(PSM6xn*jQIQx7fe5{oC8NqW z>pJhFKRB4P+~0wD6QWHo#kHCWcH$0y)_O{TFWWxV&BD#y7t>o>#=)A@i&aB3?-=;n zOAVj1-?~CQZPMa5EvA}rxEb}ZjXO3md`cv^p^Pt=!-Za2Nb^KctOPx+L$uvTZm(Hn z@yNdC6tB>xd^@-rzz)Gmj38|?lN%FS3nP5mp~9y=#($gn9_CM)J6%CKx)i|Nbz3B4 zpzN*!&j1sqhq38<>E;UNvySPZ8gpASW;Jw>u7*kwhZL`;b0REz7Wgbz<}{%O4=Na?1vV^ z&Q4D6h5yV9^-dTaiO-VJwn2r;P~+dy6ic0)0ZrWI#XBOg^8@+UmS+Zu%vl;``Rr=` z8G{+qpeF%G5@WjDi$l#u@s#iT0emfSGMyb}2!zw%^P}Z(B@NMSlA7>>5q1#ip%tCj za-rmd9CgYmH6=j&`HN?tDX&^VL86uqkRzXXoK6vNC z{K7~L>WB0J+lgN`>BRjkRku+CyMqXngll-)Ugo}Bbw2-pn!I11@UWZA_#$upPQVsc zVL@*;(dmQ0#^!b_!Jr3;#BprzKeokX&q~Iy;&P1Bo=NrvtV1fb^wr62Fh;V}_(hcz z%OipZxF3Mc3M9OoX7K^~ox@aTcKqOjs_@A0vqJN>dZj%r(0=ug1i7?{I)_1Fp>x0c z?c{^%8Q_fSztgadVMJ?(YKtayFl>s4>B#V8uy$Ps5RqH1gTR$^Uk z^Nq@XI@H9V$QCft9~ z%$yCr7}fPHz(PT1^5I`&!|z;_zSd~{c?j=XuM_`zBlaA)SbV&+`l&R`Fs<737;^jO z-AP5rQIdiy$P$0adOrr@a|px1?S&WL(q24){sQzN?%4v3C&T+x^NP*pw=y{PhP28Q zm||Tm9L4Xlz&;IZYGvHvlstd)D#FU^4TZed$ep&K=b_pHvrD@mA-a{I^j>J$ia)Sn z?K+>C`{!ipW(1?5uAzX<>j#r8hIYJM4jA;JnCBml(fTmx?3^;ATY{TdJeH(oynnI& zpRnByVXRsz*x?0#DGhjzMJ4aI>L_rMgu|fCn$_Xue<*1pc}?@+*+WKEQuK5%XU1;_ zkk!f6-<0^Hy!`vxu(Ibq)9 zN0lG~<8bFSrzGW~%D?~yRK(b@Iqm0I*%i(bNM9)`>SA?s9=5yvz>IAuteJ;#ze?7O z8D(C=JxRqn+l&Y0g^tt!nyy58E&d<3pwAwJ=yT$S8l{!MzJt=;k~N{Hq>jknxzd0w ze$eqNY|p&ucPK!r<_0Z!%S*1eW0e zOLn>(?)_J|_uO`7SBC!3)nYagUNIK?6CMN=Ia?d}zlf;$+suj@d`H<@Anx~ITD$R_ z!c&8`&!x8l0v15|3}R|nO7@m;-k3-CCB#GnP@I)!!KpJG5%ZYl$0HV`%L~5x>PvQ6 z&>9<91d5;(`7Jlo!}<+<9Pl=fH(QOeDY&Avr1yv%$g87|JSf=4^{mX4AHZ61r=Yc6 z;FCQ*0hoonHGb}|^k6zer^pkiO{CLDtfEupUi>It`59mJn5to4W^qlS#Lb8M{+yJ+ zcv`nN)dkrDzcA$_M~u#jc7LDB|3)vI@leNCt9dKs*7NFGVi2%HqrrjKskPxv5@ZKn zKetE;J6HGR##U0pTp8^iqLPK4Oi!QPeBo4k-GY{|9YA9$AF2Ln)AD~^mk30h99dB& z3OD}!R^$X*lM979fNMfEokW=A|xWmt%=JDMOSlE55$zksQjA-aw^5Tl9 z4YISZvEbA7J!;V90s+bIF@PHMd?0|G7QY{Ki7;q!9+GDBZM>Pz>QkA0jM6HB{mtd zWco{eg*aCE1owu7nQh2Y+{wPF^}n-j-!k^l+IFj8R#vO?Oj#URb=JO;(z3sIDV~zM zztvn3$7$(R_1CgbWj=eWA?DHjw+uvLJG}%~uS|nv6RS3`(NTezdUIo_iSPc_U={|c zzQ$5!5AS@Hg!mNB)m|hSYD{(_9udyyJu*)8)G>ka(%b)T3|Y-JsA>P~y(kjS_bafc z1tMBNuaJXWs-ttG5+2n*ZjFvBQG@(vLo8%<6n%7_f&(MjP2|g!vMb-OQ(& z%!hvP#_mDO6f1|;ieetb0ac?mqFx5chB_So+zI}bb_5n*0!uFgF8c1S${#ymE zTwLh2e7D5M9Tx|y5}=F#sKUt%Uo@%=4p zhlbBiicltH!sb`#7#&b!(FS{}bhYA7pFV%NKD|EkUlM`*!y`ia+Zh8EQe$uJI+R@?89 z&yZ-|PZzpteV)i{;KqDIQ;sDo%v^>TW2S`)T_#zfVV5nSyAj8r8`Xrxe<9h5(S{)7 zH`k2XtHA*tBK*kwZ;1OQwn?^%yPq=;#OE8(&30L8G#Y-W(_PH0V4;4E;5ubNV0`E( zah1PTY}3x~2MByA690|&LORyL$&qL3!G7+8r%h3=U;B)SssCER+W5;oEqaOb*CGM= zNBLKOt#rotE=1jGOR_h;*zj^%gVPg4G8|qxn`QT~yb?LQgIZ)Ku|vwLVad6gZZ!V* z&7`8tU+_z}-re>7#X;r8{KI=+v`o(cgWCV!DqK<68e zEWV|~7z~>q`cChGLoKYR0E~t(ecd?2(TnzC?ulb#uTXosDVeBs*@>%EwgwV~FESCN zt*|0ub^4iRE310*XH&NUeHGoA$!*;^&uk)>?Odn92rwbO;rB6u}^N2(KCl#h8$ff=+JcR!$k5Ii*e}li;Ovc z(%|NbRHRgV;(bqcKbivE4<2z+{1+9L&LMEI8_odm5o|w!1#3_Tu}u(8htYdUs;6YQ zq49%-BM!px-wSvDOle=NOty7+&HINt38Te52x5;AF}eE;^#eZpqVXqXzeQDcoMjXS zu=l3MhoQk76+8jZkvYxl*mwbvR(Gj)?x<)|P%Q6J_+2eivHHu5(s`K+%pQoKVp|!s z+B6)pK!`g?)1Bn~JUzn}UA$vm2ZN)3u!0)%*?em^gd9J8F$iOKEvKm^h1iTkhH$m^ z-@r4rKuZnzp75Nz%ASQIcEEw~5-aJB7ft^_XFvCq0u%{$h>*^G5J6*ow(ud(6O~Ql zeF|30V`T&}waSuLhT@vMv?I0?vpX9CUumg`@}z-zViO#Tc6a&yXPqbld_DeKS~gc5 z-oYVZ8*?|H<3bx{Ks{g{_LRy6v>W1m1O_I-^4?}*<;Ig{y}uyzga}e(;1R5Hd{BUg z0WD8YGTPo5eDo(1Lw&Vk(qDhB>V!R1j$|Ht<4&w~vN77w0Pj{VK)NtP6Syc_wjI6$u`+@6+qz{}(Y=M0a_LQOf%|D(AVdsdA$ zX@&{Rir;}ruBh+J5Qm~5^R~DVmw6YoO0$+(4x!SedJDL-%eO&uHD|qkgx7S;@_G~PwM0Ef5K0CPM8_1~D$ocx= zkc+Pex;*jw*1BLTsc;!s$apW9`SmY(iwzl737hx+8H-glmH+wtwRr3KVRcPi3tH|F zmU6PQv8p(VC7X8YJo>3`Yf;fBqWV*|;fnd~rSbB|C+n-ZAc!4V_XKNCkh^KJ{{gEG zVsuwm^@$Z`5c~tjkfH$+_Ql+*^;{BM!|S8V<9SP1htH^~{2Si)K|L+y&i>{s4~t#r z5x5c{Gt^)KDdj7KlS7ZsDeMHPv0zaQK6(%(3RbWFC*l6>u$Te-SL^8t9jyLy3DrDl z$TPw`6PwAT4)ir>+5b5-%MfWUNgoIM4?CSi(hJ~`8fFgppfJZlTo1nulQ9;N!c%AG z-vBW{pja0y!hsMJwsUqK`yW0=hKn30!*u7QWs$}0NXOQhip8pTI2(?Te^5XI<|Ggc z=?<3iP%n`HK&myUebAvBz66Oe_z-|~KbTkihP*0)x#rXBy5n4Rx0}kTyuQv3mAdwo z&+~8-5!inz#{@1bwtm89*;Uvj&c5o=*y}CF{XwU=H5;!ary%AJ9LW=gMH7b747l_$ z&EG0G0uZuCNho*aBP+hYTvGJ@#31eGdsDBRA~-mhnw~yPjkVnDnf7?#&({$dCB9R~ zsWMwP84a<$k{kNIvUj5 ztL*Xoxvq|`4qBI6;|<45ef7Z*nQJ%$nRt7gTV5TZhK z%cyDHXy%l!=eQxo$DX>#MEAh+wbgS!+<;yCx13YliBaz+-aU4*EE9?@QVh7b+;fb# zx)~v%$)&t+xh;9+OFCZw0B7HFP=}cecbYg#Olj#I``(m?7v_ydM=cU2_gSb!{7G>_ zYIlA=Pt*=v5*zy@^%t&>9}oWf`AUcL`(YtnR1qpb|6nJwv(tg*R8e_L_gkmMN2VJ) zo!g$B4&V~6bBiXrb7Pm0GB&@d0L|Fgm`8}mr~I{j4R&&0yh>rb3c3=ClBrHbFEd*r zxpzmV-nZrX4U6Bi#AM7})0}B2vZ#xp1)NFQ=rorq6fu+n{i*jWDyl90JSjU|s4ojT z?Y8~~sO8BtYKDA$6|>xUucDgsc9Ke7TN74VammQUG;WI?R%yssNf9QK-17y+{?>BV zUYP*C>bqxEVsrb!2Q1(wm712ec<7y{$uTlI8r9Ju>*3`kU!)}`w@LoS=%Y!=*M(t5 zfZ~phkKTW50wDTzO%30{(NSw*(+LNsx9c5GAwYa1tZ)_cz%nEcLNbX?5*2_0` zyt2DV8GRp=rNaL8nVY&<*9=X{3-;%%|A~!|h_kAyD(KVR&up!&ugiLQiS*mJhxP~r z-Uc^h0Lk?Y4TEO3dcY9n1|b$LEiLs%LfRk3;n!Har$cZY>Ymve@5d3mAT4lz`I7GL z-Me5w3NQ7^bBh)e6SGWjA9UBL0qME9Utz};&bt1s{F0KAe4`w!%aijz9SrmytCP2D z;wfA&EcBtZP>%--%JV%lX*4-C0xV7gl3(Ah-qg z?!$FBtT(s32EJE$&OMTY(pcA00=BNYpq#kyyY)noU=ILCkjiE~H0gOzao^-AJ&x$| z^Ue9}I8Gg7(~H#~GO0>r<4$~21yBwF)ibXPEVlTSaZ#*gWk}j1--T-8+#u7= z@CozYEjxP`CuU~EaQNtde)?v`@67Y4GHHLy8{07Br(N_ACBY6Q#zU_W7ROQ+j?4K+ zFDN9`+43fwT-RrpWm=Qi;2NoW?IZ%7(J$ahFa#>w;P+_ zAjWcwa<2(r>108VI}Ns*kPmYu7uU}DMSNeOor8mnzbQjzR@TFRu|bB2O1``Ww(XFv8)pYFDKEYzwqz)Him8NG~?Cnyp2&_^ZISJB+YLzP3 z+OicF7Y`2)x6>Z)1Y~QJ$Uk_16+l)w2uBHaL`1VSer_G5(T+uCC`!1;Op34)JmOQ; ztElE8RGVL>)nO-xy1e%9A2K%y>`cJI>cxu}!!t8@5J_Dp=w)VxfSpxF$?8(0Zx!Rh*Z!DmabMe#YqV9feB932S<&BL8XOP6ix>ng!{g(j4GqGel)$7P z76U&fJ0~YAPsn$Yg^ikJx4hEQNItq#8ynwF2|un8iAP$$ONP_6Bp!k+ihzK??&(w5 ze81115i+*k_2UQm^z`)Gv2_kwF49kqbyK|j{6SEGfsnk?fDZryX)vOV@xMoJ(d6oo z3&?_NJQN+rl|yYrbyxds``siXd=%Zn$w9QV-$DSaz$%q~9H!yJW_%eT95RbL(RaPx zl^Vcu*nrh3YutGIHbc`RMrEYbv`JGN#R0!I3XF@gDtSopo)j-LD z(SsI83+%x2nOvw=Ni1y(L4^ZkwU4F?}&?NoP{!Kh7M+Ai0@+* z@G0F@xDl2Ndpe{UMzk#COljDfl&bOh*eKRY-+3;Ka2S&Vzu?UqqM}%%e8ZC=lp&EZ zAV$ar@f#Ott{1pBp|Il-|6PNt2xSQl-2eQf1#_0FVYZA!%w74tt2gxU@U-ypp@CRx z?3?tKcM{}&ZOFfCxe3)s& zqvCzGNu!q|EzeCNZ|{H$+bVqmL&O9pBNL-h8;`3jth~_;6OKwXF;x<&WWPu2{rDYr zADvzgPo;}x%Xi_tN(SLdQx12-taG?YwXIkmxbM)`pDBDaM0_v06+neQP9+-x5l?&f z_iqQA#8p*s!>PFV`?$>_u+*E-dsx{h-za+g&O|ze0Nwnu$t2{8y?GPDi2Yul6O=EU zYk%k%qgLM>PzlizAm>y}Oqb>F6v&INWK6d<@RLvBF^eKYb;rvb^bViR?l`_RLufb* z4GobCUp4wJ+jA{ZEBX@AnUkNG0}@qE#KpvT#l)iSKCWuF;?FK)8LU?3GgHfrw&v{e zUoAmIkc!$0(!vD=jZU5>JFkF1=l8+&=Mn-soHR0ki%0Sc3U+03j4Ys7?g|Y{RW(e^ zcfTl~@YN_7dE3^8R272tBN!2>u^IJ$pb~IccDrY33#Zc3&5cxBTidDiVUuaikwbkK z0m|cbk4(Os${*8AkEL0?S)>Y}^FkAcj1p)i-`CXz&(6-`+PDgZRT^<41Ej%h4bi^3 zFI%Zsx6+CkoX0Al&q<|CAh=Sb=^(`QlB%H++%>^-3KELu{m!|7^Mq>!{$&z;%#4G0 z@7&Q$?NTT>xX495IN0MaMt>ZC3B{wPrVbc)u*Ns2vBD?%Hfo^ixKYB}bp$c@j5i2j zYXKJPz#`84>C@O=u81uHzWBozlJG7msi+{J4H^UFp6a***ek=D+}$$At_1;JN2yyT-n_vN#8Yl8YAKmwiI^urg{ zqcFw<1pDLnukRZzmub2|lXsK1>i-meey6X5XA&d*1nA|B7ZB!WdWaFx?HGU^&D zdAJ)6a(5U9;j^Y@V0fUdJ*LWuMgPq^N!F`IM?ow}@m7KilPM6YVdp;yl2ICepBF#b z{i!Tpq{g~0`SUS%8=0*pzEZ^DR9Cx^ySo6l@#hd7u~_L>rx+{#$Kssaocy!xBMBtF zE*oh02gk6-_y)ar996yQK;y>R{%0Qv?=N+=?AYXv>n(SOmGSq0Xh0GUgoKctxHOn8 zu5V&u6T7XbsHkt&m-giuj4t4@iOe&8{FtiBv~7@-ejLGa)q?Zkcd+4=5IVVDQo%b6 z!b|;^Sa}FMKO_x}EVzN<4VkIb>6&=Nf9gx;$7$q; zat|Isr2T7s&K}wiV1#A#*#if9N{Uq#?led}`kF27wF5qXu&LgBeRaOJy&bMn^kRL^ zJC$$f){6Dr!OS>@==D3!e%)=)R8{fNXpxc4Jzu|?*BfTc-Kp^dV|aSW z7a`(a|KLz9z);u~ibn-Udy1CHB_1ode5-zJ@R`H#{kQWEW%ok-o#C$iKXz|B&#sS< zk=hmc7FJg1V%h(S6ki?SgG>x&83=NJ&C_;~SYtK+a$EA^Y_iR!e_>4Ug(J#dm&eM` zqSsVKjHy4^RzN8n%8~56J~O?>gBTAueE{>U{rxKkvhs+dKFaNdWMTwa1rH|l#ESHrG$(WdO?xq zfx^0k>euf)E2UQ?My9wElwfVK=JV$$cyFY~|7PWRseN5zS=7``y&uKC4K=Dlgpj$U zky-)rH#0NieYHvRho44kk+=5z{5`o!d>>1EFS?Q{DfWG0eBa+AY2QWHt5C^JbZ&nC zZms0{g}16baNRv`uW#ECWuxH#cOrW*z-V$SLB~!8+)zH$*LN(tnfvmDbkA& zl6Fo`L^nOpRb|hzu+7R$97|)2grjx%BLQH#z8Jdhg470rMkCB9aMq+j2ZtfzGpaz1 zqPYwgR=cYPSxZ-haz~~P2Uz?=sq2Pk+>AG4=WwfSq2uzLH(l-IPtrq|{T}rL53k39 zVPzKu0XzA-rb5H7QD3#HWnrzIRLyCXey}mytD4}rj$zkic{&K4csLP*1Df6{ZBd>-owfSj66myFDSUvq6Y|w6r)ibGDSFwD28x`?8rqfPD@d8 zbPQ+b=Z6Zd=%suk{4Xc{??aI2LipoZf|L#@(HrSkJzCj zppSytZOQcd&=eBnTo=D!7&W?KY;A3o%%xHPDO9vS?le40OUo13^4ncbGev$&(4WIhNs&mN{OKKLdi3P{!;YiqS6twF8r_YWt?^ax zjr7^t?O)A4WPsjmo?l1_WT<`eSSNj>!3Il;&hxFYDJc|Ss01@OE0w!mJ$*HoUuM-& zoRD`GGUWyO8R$tsA+vw#a`;!*sM!NWUS8hL{%LTBneU?uR+(E$nwVzwQ!e|L$0M^- zkty96{SvRD#+PmvCgS`=N8yho=f`2>!ikqNL-3h=z)VO*$ukN=XHojjCS5X#T`zIX zPeeH>3!N!i&;OkR8LIyf?{9L3%5~hZ0^5<-uL(i9ligaLGTv&xs>_=4#Y)iJ#fA8K z`TEp9eqb5VdO^fSu!0_m4#iKnoB}?e_vu^}Ouu}B4(kFo7-;(^aAUB)A=7lkZc@|H zh3aqw&f0{75%7-#!O!AN8bNxp2$dqLGbf|>jMxjeH zq#l5ExVd9lQxhHH{f7@Bkeze`7PjE~f_E(soq`U>cw==2?Ht5HV3O}AvV9=*QQXSX z7kGxoyRxbUAljqqorlEGRbW(oc3YlXlQ5G-qnQ;NnZcv+u|UoBTt6|Szt9v zKvYC7ARvIeNT5ezWo3mJD$J6xUWAn2RryqvLjYe}LznxbXqGc=eRr5d0quah9pV@K zqv0?C(j*Hj%AjAZo@`@YmQzM=ntkmnMf7oo05aP1@|a*`w}4ZlSWv@JkZI~TZl!sm zkPl$4VnL~$vtHlTW%?BZizb+u>~>%=04`$r>Qy%1m~vvo@$uT(x)-pLX1r!EUeJDY zo<&{&PQr9h-W?0sQa4I%{JU4jAKuq0G2)ib(|il#Jr$3M0+@nA0v32qz%^a&OIHRd4;gWN5r(9sBv6TPf4-k`;!(!Wt}iKL3HIyvS-hKW#7za$JOTmL z2Pxt)EC?KN3euHoqc1y<|-t$_jx20f)-nkecTO#hG z+<2j4(erFcO2hJEm-8_UgK1+pp+>J)ido<3IEdcxq$W`OR>YJ1%LL_D@#LP2%6|-S z^)Si*?1|{spUjb)9e-xbq264Wd;|E!!-qrxWHuKtZT$Py2xilG@Bsptaf6;dzqAww z`6^bye*UC}&X1;Pmy#g?+ zFA+UkQg4(B+&95S+>f98`8lXbo*9hP_#@04_7cF&Cj)YaQHD90ga9K;B_E>30Xwo za>2vH1DukYmi7y@*_L+uj0ZjeBCc{(6GMZe_x#d=KYW>)o=!K}85|@8Gd-A{Xs~&l ze>|w=L54cd%mizdA`usOCnFORJ^H;8GGDhx4968b{K%v41Dpd!hnQ8Zj>=KEjB>2O zaPtA+H0OW)3NDQs3=B|kgO#`9tw`pH8#LM5w~v8y!E^pd2hyrszq314#!X=`1>o8U zU&nZRItb})HKnqYO{gV1g%8+t!tV>CGbJS@7+ARcm-c)T!f|QBpV76r$dn`XDhjfX z;2StNJnXO&w6M3wfnX1oShwBNOYH-mlS4509T^+zJX7W5=C<&9MxT@09V&-nTpOnRd(4B4En|o`1b$4>Fg}kk>p(4qVwstli3G}Wa_E0LHAJy${r1U6M66^5 zB*3Q#T@KLDtax%}bN>?_o>Xyi=Y4*cJG)6V{8jk2U?9cEXDi+X!V6#lIB$v%9*oS- z6NPtn9Ed-Bf;ArGi;4|ybI=q5GKcWZ?Si5PGd7GE@KjQm&29V~etem2STs_9MAq`U z9c^^L4^ALxBaq7K;KGCi61~5JBKp4Ld3xp04lW*_Lyt5-D&@fiMH6P^ZVPzGYlFH^ zgq?ntBPc9hK48QZ3c2O-Fi&$~s?HW^k}WJELc=a4ArS-g(T9&8>%ONN4hg6AA)QI! zsRQ%i7F!tRX0{Yzd{($+ZkShp^gZtRVDxjNJG%($Q4ypVAJ!S zd1ARQ4aqh@)wankOF4Rc-ke$NT#1?7mA=dpGv|4Ku>2y1!|oj)2aEnMXAz(o3~B=k zNl&cS;j@B=8)VVL)6-E%s^jpGuU!ZK&6v^7>ix?7LQQs=k}~VDFrt^8{wWeq#Hjnhj9CK)xa_Ya*68O~8BH2GMVD9dY?DmkH1sv4xJhW}Q zy`y7JeKWt@tLX$Zo530l*!SVNIl@w%7rz}}5Y~M9gdVAbD;xjC*b~+PsVs{&N(VbX)^Y&EmCy*YXp^P$@jn2T$I=M<{kepXmWB_ zEZG5tU0R5EU9e=8Gj-a4AaxMe#pJmOV6o(o>8Fx{eVcoX;a*_;olopZQd=96A3rX} zM+UOxME0gX`J&vLEyo>b#Co2CwwoWwz##Z$RdVf_whI{WA=@-F-V?3xJvabvjTiZ{ zk;OJR|FT?~%K}|W>}mDRUzx~(`AI=_bzGn#%*Y^;0_W*ZE{mvP;o*Shl?gjk90|32 zG^`8*@(;4+;S)!)iVJT5R*w6MM5KTMncTShx%XN#^@op&*3kZqu1K7-OzP<$*?xel zI)BVcu>g$i%c2XAhXQZkrE+`KA9AIrKw}LD2`V42v^27XLEt;}+SCDX6;ppV)yey& z;-$~(!{(faXz`~nSEsfCj$c|@g45=Gb#bpL4fu~=pIi$#?qUSztW`fC*q!06b4QHI!AogVZ7D_u<3K3&iMv2?UxQPC@H~$UK!Rrc=+l|4W@hq zdCHA#>xCG(??^uzmBYW_Ajf4Dfgu|5Xck>Wfs`gl>%*uwG^QBNt5#aLk<;@q2TiLc-&OHh?mq8U;y(GbfZ4hgk0U1CUjRBJ#(AHn- zY=_bZChP=}Q(k8{k*kYK05Eq(&ECi+pu)$x@|BEx2bxd)N-(M0Z-IByhGcbvj)6hr zgL8FGrj-sju3F$7@fJ#^y&nTTJ(4`4jSb6w26&^szCIL5IZMmi$aZpm{+d*uQ)=kp zMgk*d(omAbyX6NHd+KGg;w%H*SCa-f^bp1f016xuh?q5Zc7DC38>EsU z5s~Pm#AcjtnNi&CGwO0OYE#B@;eAW%V^3CLr^IEajABoDNV`a4<|`*!93d;}wY=z4 zR$jKXIw`4IwiUX+=~bh6o~7}rx$oq&-Y?F%^YJoUhwhis-HPMS+d&Qj_~X*GrTpfv zU6gj8+Ous`!754_y}Lu=TrTA+`U#e5{c>*Uc%i6hizhxyvd|Lk-lt z{(G-AqD5kzZ2C1dzfVE)fM zJ&qLk%oVh?$u{P=uu(}PyHwBKjtAMg?rgh=x?G+;2Y@jpMVu^NKC>3)Fc`1ERo|ih z|KsVs8?%B_qtQbr{!4XH>d zJ0gC^+57YTy&w1E{-bv{*Y$dx=W`s-<2atF`VT`le0y>?+xKHn7t3-{kk(t#$YjsD zu#?5lJ|pWn9$Ur>M(eJcErIdGECT&Ji zT5a+VC*A8A7((Y|tYf*t^2FW$7l-@xKz%fQ2ps3mozr5cM3+v zXD!Bm#g6lD+H_1ge2!D8?Y4{fgTwTN_LvP|^#bWOn8p5MbQ>~={B}q`uZHEg?V5Q` z!(Cx<<&D(I+$KNuUK8e9pFbbP0Hyr=|MUmFHiPF=8{hR)Peqvsm~982F$xQ&3b%$H zFzDjWXZV#bX5_A*y09owV&!jQ*{PIYHQ2+cFE|mljRJh&`}jC^1U91%{Q2?8YJ3K) zTT4mdC-(vO;*s~HFzijiFf01ObEtpa{R3)dkAbB4d%fg z<$|Liq&ZYm5|kv`j*DP++{!Zd*wmbK!jjqFR=TndTZX*@5OPdg0IGSBLVjFeMl= zWkssK*pd|f{M+=FuhUwM{LfquGSSxj+T>Rwnc}9QT}hwTJ2csPakA!1?NG`*MbdZc z%#h&tb9Tf3f3scG3l&TnDEnm!0xvN0*0Ovz zGyG-BYI-2rGRi_{?P-WNz&5Bi-9CXGup=N}B5-z-ekP{3VHICPKOW5UiK51YoZWIdG(30-v zUY45O8e+;FZz^){A3G@GoLZaOgM)$6-M4Zw*;S9$!lNG-T=@_(G#V9Th9JxMo0(cE z_U?mkPO@B__j^jWemFhft>u~<>n*q4p{iLrzm1H$5KA!VI((?WypS3&5y-)IGDe^T z?ig6u*#h*WrF&gQ^gzcdd_$zrg90I|MBEiNb-bx5X1G528w0ZC3(o~6&+1I`+-Qb{ zDmW=vqApdZahe+H@}|IC63QC*B&0-^$bIzU;4-rQB` z1>ak37SJq^g(T7$PFYV{N0|;%k(uu`xzUHljhjg(jCpXoH%|3{*AD{&bWVV6@sXb0 z#m-VvE|%5WUs&tY-xjiA$&N=tq_^t1l8~4mm9`vXK{R&deIAY5^ZxEFH4)|Xo*2OL zEa|VJKFbdc4Pn&?2CY`*NBoo3%cI*@80PC~v%cMNBJdzCJpjCryigo!2hS$JzSbA==X7Jc9!Bt^@9pA;p`wG|I@|6$2GVhdS6|(r4_4|cBy~+FA zEj(20E$qtPZ7=+PHTLXewxAdNTGQb54XwgF=RNsYRY14dETzm0rW4hXSq5IRyNcdIyL0cx(u1 zqy||Q`E7l~6LO_8Ft3MZZDCM@`ZF!oN5JTi2IB%%*6WBT=*p(;5l`2a=i4jKtu2Iq z^X*k#zgsv(o#qJA=q?up$HHhS+DMp7H5A8MG)*Bs?MmT zV@785DP_p8#Bw|D_LXAypb1Yp>7l+`RMTh=Q(P~6D&@3etfiQxqASNXZ}7S(yQtg4 z`i@iOug|FkrO;nhOW*&mTVR z(_B(&tkml26_*W%(xgt;`3UfbyBVDqIL^~wiNH1_4s4Q-K|8sS5;zo!-irG2+QZmog_Zu2cPCZBZ8s{Q9x2dgvv!>|WEU1~WiA zd;$W1v+z$7CbSgL%F78q9Z3TS&(Up~rJRw6R?ifrA34{JG8#pI^DitF178Ng6vT=C z8|sI|QA%t#UhEG1P*iC<*MZkKYfL*=wX`7ydc_OrS-lPi{z3FMWgA zXF3~6$9yw;TKn%c*xUsdU*tF-)JT3PHqPFEPQ$J;J7Cxort@NzIQ?bL)lszE*PaCd zDPfeIkam(hG{m1>`tICq%diWTZw{x5(7vwdlTK?!oWN5cZlc$t+fClq5O zv_1-(&qS7JUrBMZNbHZbwd7$MPKiZ?{f8#U(n#?}d=m>i0t(wNSnduTkL}do@2pfe zf8J?pL*|p@5#8$-vP|J2L9Lf*>%l0m|Iq!W@59`0*)#X;SG9l89J1rSr>kFrfmrw6 zh>fR_Msc`$qX2R_SEK~}M2Ul&#&RWioJZmCj0L||K8@U9{e{~S&Jr{Sanupxk%V0$ z&kLxoh1!!5#v2Q}OdM4El-{K++2#1bS>z}T;VNx_H1cKUL%niN?e*KYmvQ`2LN(p_ z)^{V{b?ym^x9tggGp%O2CigL$iS1?%&OMk>BM(w(Y?##QXI8VwD+K$Udf zmXZ`~e|pC@Hpv5KsqGH$BIxtD=0^aP03d2=Y6`#XCe8Z{Q4euUYHNN)xXE2mlhA5W zy}gqa3>zQ(C~hd4_Z4m0(J>|}_yeaB050&;R*hp7)=iQ_^-i?4BdHA@ez!PMI)<&| zRB%mv>2IZ!m~KJmKmbcT=Q(7WRp={m!lI(qVCYiL!n+(YmLtRjdR{YND{v*~el)sI z71zHUeC3CG$!HYwfrXwH(+?izE@;jimmZFTZJf zddfMbb#}m`7ehb1*#_TjXsD2+;1Qq5l=Y1dwbmwo;KbhX6Z&$+4I_Lc9d^!$VY{2+q^1Tv(ZayJr=!OD0?urP5fK^O@d zkC)D=EwC&i-5iuE-)H|M<#e{IZE#=Uq$+C$rGL#fqm^f8lCQ>QL*S2A!9nfDQzFM@ z6VC9*8!&t|>tk+tNUtZxxy8vqi(=5o$&xEP)wnU|%vKO7MbGSD2@bTSF=g@*+Mu&z zeaL;v@hINj!|z_b>09G+aJvzsSiAvq&Y2xKW@7XOoZAXGb)V3TZ`uTq^NKh&=Q#+UVe@-bXB)I()~gKD4VQp;6O zSdrKOg{;`HUFmUdj$-3pr|Phv)?YizYai!yxSpL*b}&30TWeFSRg;M6j#)wR#KXq& zgXETeSCpu{pA{fGaQgoS4zi1V|8_PtNzf-Rm|**1)FHP)=Qdh<)(3O;LDrZ`sayT zRHNQM97c$*YELodnvH~QZ>9MSYD$Y!tb#^pOv&rxsB^ICif>d7 zYhC_rxX1<{-?b0GE6OYgDW0BuSW#D+`u6E);`MGfMcv(I*x=Ydeii%YfciIosb5~! zfOHAcP6Z-r--)6C83MsrG&r@2rHkBdx7%1?SXJmBR%~AYfYK~ZgqB%sJSA` zqGO9Ob5aUp=nGfpO)scB{uez)pI{>%rw^qlX3v=B-@ku9v!WudOu$t$wavNdCZ~$~ zrA>A7iW`iLz{?ABkY~bvNRl^jtE<%1)U+XK-_6^`pk$xz#8%78wDB{IFN+ z$uR0b2lc8pdbRMW4HQE=2q+PyARG_h8*inF^){r0h6Alodbb;-A%Ft#Dcs+bm+wxt%G(w3&!^%3rn__9|2Q4XbVP1ee!=0(V*MM&*XWK5^Q5I&n|@d z9S%>*E+MTTyA4sg@MKCBr7bIAUdnRP6OTiqa4c#C@kWZ1>)fXM54??yYhGMyKLdqF zrP^2ZKn1xQds_G)xdhb$|Gv>2f=z!LH*TyO_u6iJjG7wv1eg#jy~P%8=`yXl)j`bX zloJia9{6MSyO<^_gJrb*6FSqb6@3t)5ZoA}klU4&31S@3Dz#lrj8_+mPOy5olp2sw zsoQF0pgwW-{JC?NF>i&Y0*pZMgSWffte*x-*4`#IVWbR#6dool>KSAAPwq3O?ak2#z4|ufFq=BJ< zIuHqWA8uN!ap8;*^TyOtl!QxGsU|iD<7Y%axY-;Q-Lv-rrc2ux10)k@DdN?g5Q~AJ zs(dIuSx7M9cUF z=ek*~Km58+GxX=OzpBT@<8N8+m>b-IEUr@bxRTAC1cN&kl3UDQ#C?>AU8nqm;YqT- zS$x$Bvpny96YYp^m!B`cc_*A!3qlJX==|U1q#;AtgtF5!${rlN{55I5BJg3s%thh7 z6E2V}7DX?KY~y5$HdESMvbDT+rd}eaee_{%$)gGzkGe%B^%lJ`x|oJnU^>a#Jr1p@ z(KufDuFy=S)X=-&|24Lr?9v!XJeOEvx~uW*zsKvG(>UfHZ}?fY@6n0}*Wn!-*6Wsj ze$lww$jdr2hDmeht7OghQw!>tk}uCUYyQ)wT3T8HrQ$yv$H)9Qd+EX20YNqIHt83G zvDq&|Hokp(W#dVfXv|$4jS+}=oepHSsJtBfM!B=`2A_O`?`BF2?YjSD{}YhhzDrdV zqXnv3Ew`3?r45Wu6;)Im-P~9}zk_(_SUIbD|IFiox7I?mK?lLFCwyVd4heA@WFquM zd1Z#VDQ>wemKFRZZEc`LYg8#Gu&{j7r`Ss;2;O> zr3B%moIlS4wv6<1gIu$*h0$|rWD=#KvVBf+gq_P<|JX>w?b}XdGI@rDo*2bo4*EcV z`COQ8HqW%q89w^&uWU$txz0Aj8QjT5^K7(x-eES-NgvU>Vo;Nh)OxRZ#8)C== zh=BF|B@6Z$#kyq1peRLqHUafI5Fw?qb4NvGOhD_yl|))J7p3v8HW1=vD0ZUL>qzOn zi=rB|-Ejrlk6TB)5LWPR;j@+aJ@dQ{4-X`>e492k;ykPE+=-#Qz5efMi#f@*Lzvrx zUN$s5te~QD4Zj{ux;{0*z@ltjoAdTd-F3g$tlN5&O!4n$Y^~B}HKS!7u@&90FDwQ> z9z(y1JX^DZc!hTO072+U#5}KG9{`e8k5*Xm`{1u9sg`p-G>#uXVSbMamo)0&G!cC( zBCB|T)`N(-pw1De2e-PDY)YJ&g(#6#CJusSkuAC$4o1UrZDOtwZ){^qZZuL`YqMA= z<*NbpC#R-rLvxBGWKrFC$RMoV-r!EgLxZgV=`LJYclPXAA{~W-&#^gH4nmkLvjQsy zRx#fNdU5*~GD$B}8e(;`kCrQZoqqj(YMHyu5lJ7cQlxP74Az_y5d74>Ts#7DW$|u- zk(ExhbrQ9OWu@+}8WBDGeZ%IGSN{I>BU1K&qIH{jt#8{}fqqQ{8?gO@q4psgw^K5wJMY9n)Qz0BJeaZYZV z4+k1a24p3r@7tEHEzQ5LCYmmX_Nye%Iq_BZ8CS8i$P3r(+E^-c^pfN1>Raqjt2mw3 z?=n)}a9@)7>zi$F-PYJ%*JYi(K|PfzD4VoqeH0643O74_{0lJ_xBWwGH(47aR!rz3 z7yMceu^~~xv*XL;mu3u1sbS8ATe8l!AXn-0f)5otJEP8gFIQE^wsQBS1c_Ayb!i@v z#x6)zRaFNbZ}N4l22L>d`QK92Viqo(8mNqSkIDY%#Ck-ESG>Q?&=t0!G~?9ZSP%s< z9KlRi13Yaa>$nPzJM(^pXYTyte5`LthTwt2DX$W#|&!@dNroi~MgQ7w-0g7&xCF@JE7(GO!tiO!mO?0CyLZ zM#tf)RUfKV8Qagu`fPgdMtMiLOb~ZZdQ)zm6ZV95lV&G_(A&^veCaS6JMkc^NX6$1 zo3~=wg(|LpoGpJY7T(xAI z-t>ljr+GtYUhKQvTrt8@f-}QNU*EWwW$+!dg3PYtM-}-T9$FoJkQ}q$g*`&&z!sh? zvvm5oiy;D%cZ(wfrFIJkjp@v#-@Otj`9@lFAUau>zRpZvBcYu`BWaHZy${dc*CHTo)XL1++1b!K=pqn<*=eDbWjWAXn(y|< zJ?E0~s5|03h%`+A+tI4hDQuk(o0Dqe*`-3ek2xBy6)1+~c5R6D6ndag%4{&LRi{p~ z27J)666yV)TSdW|{+DHvfTtEgx-G6?=F9-1kiZY!m9HR|&wssbRNv7bN7 zXDdPPKBdZv`76S&LA&dbXfIis;ibo>!r`3zeN(oK?@m1&8-*n;M#HhR8*I38I9gP? zvVF4s5IjK800Zp?q#~H2%KOlS)SFg5&0hcAZ1qjyiNL@R67aAb@31BUrRkOi%GTIx zLdFMat?&E@(GsWnb6yIc<0_F#HKDz~Md)jgwBI;R9e)NL}jL5(!`-URM)&(6?Jtz{|*kXeOj(WR61A zfiVfHauTpoj80YAdb9zsK~dsdJ>Nh}aUR7&_lg*FU=SuIbaCC;tDHe`rCqz=Y%f}^ zT|=Vj+^r!~7#%wOef5eR6lMOj#NNkUl46B4PxI50zKRHdR{=y6lzS5A!Q91GxC)(f z-3N|sX!!t*nt0#dVPOmL7`9eJr30Lifz+D9V9!Tbc*$Q8KPM^o>)D|l921@o`w43b zFWXC2Sy{P!R>p3-OP|-I-M8FROwT{|_0_kwvVxO?oq$$8nhOQylQ2(!7R%zC>4TfHRdTN#MscYGKPG`2ProGLfxn#$NF;_f`(tm0f<$E;)@7}e%e_t^xtAN9+ znr_>|Z)x)&-;1>2wHfihDx-=NZL+5`O258CzdJRxO+eE>5{VR^yhHi1>X$)9$7xBB zrC3ex#R?g{)$xypFPVjYTb{4f(U2I|u}N#VlV3=&lTZg_|Ifq`(>lVf0i{TK!H8Md zKr2SnT&a3iIqcBjZ0n(LQ+uIz66$fO%O?4q=;kPacwj_t)JU{Z6@8Ll1CQSw{XaX8 z=AD~#;=`F6*t#c{0#;V;y*t0!>mY~rcgl_5qNe?A-#eYy?bhtszAY+sc=_(PCG zo0L08XODY&?gJ4<=h@m@)^Q-sf{=%*2YcIQxWg>;Xks66DbmPukHr|#*sq6-nBOs$ zR-3wxMk3Nia?RQ++OT3lj3$!*k&${3oJbJ~wPo-Zx3-GH9UlgpINpADMkp@J^VWwa zL0jGVq?e7f4w99zEl$w}`+L{zyS7hNRUNhIHSGc?qkWPc;*@wT`WmN*I(n8{q1Jik zlKh6@a$-5dQcSey)RFz?=H|dYj5L>IK%0a@4uxeT)X0#3K=_5Sfv5hXYq8bo*vout zFa@iqsK5btiKJ4u9ympP*e}KRL)|cZqmN{E>$fu)a-h_Pn#3V!O_@Y!*WOy-if_M) zrx=w}LWA|)-swiNr>@{PVeo^%h4=`~KIV;(^bxrULN=>vUTuBHK_!01j~WxKF&@gR z@mGPpJ*dIQI#>J8-57EHFvRuCloeLEuwz`qvTx z0Ok)0JDJ8d-wX28HIq$BxzD8F#+(VlC?VgY>?ES!ckf;VKCy|^T|QeAvzeg*tq4E@ zD|`E9oMbp`;`KEcy!UA{uIOv!WNNsWOM!b4_RW@09iw#xgBz+*1Qn~;2p1*J(JP$c z=pRt(M;>qjLj35Nio3{8t1aBgOLT4PT5Jfb&BKE=E-sEZI(#_kV#bzVl5Z2TUV8l3 zFGp}GF+C=7Mq)G?7i3o86sytDkX^{0DkZ6(H;X~Jb!QREa!lFsVp>MU-e?T)x5RT} zHJNnZzCWWjC5eAEO2tz4=i}6o6*c$wjqG^%@S!7>8eBF9GnB@Kri`e{bK?uY4scbD zkDqX^26+yA*5oCWeooBFv3$4BTI8B#*~)HDKOO76Sy^V6iOs6P!1Pke?X%6eng48? z_7rt(I~CooOYMr?6w&+zXh*SPhNcK;?@}HlEx2S`HR->9Z2tJ?o%^3a*ZvVxS*g^t zB~LV?%S~s`9=e?w-X#XKXVJ+N*S78tvz*iY)Xh|o0MuhA3f8=fv3))A^vE!#aB zIkQh+Dw$%1ZUnP0R#sLAh=tHJ;03mNaX8qPjHRxUnt!5C=>XbgdFW8t{ETm3!?|uk!Bpf^c`Ck+@@|>BsA4sb4?3ick>U(bJmlIS_GLMneko7?dZ5nRoBrCAkGoO#pg|w@S5~7&-SJ z%Rubioe2gCRrj2>S-&1I&F#vRrsSG&qg(xgY`rIZ!6OX}2V1 z_566#qSCS~ zN;pFIDI@RQ!f(f>;=v}b!MyZAZ(xpt&=jD9-UC4y$Vn4K{#-n0;^F8o8(3DnRq9>txLPctanC7Z`_eDd8|S2Go`3nAt!=?+d#A9J%7Nd*d+=> z3yNN&<-m=e0!s^JY<3C`zNs}rg66y|47^(oIN;M0acS^rOnE8NOopPI?DRnjoIpQ- z=EFr~wLFtA`X4z4m&a$H(q)O#K%8Zr&CkLJ49xu^G}u-H;}{S@@MR< zHVuKf)pkMZ(A$fa>hta~?Fw z?t0oc5NxzLVCz6;-cH~0;8owZ&TmaHfSSliFp96K;UbVtBh78;`}Zu+#*16}+S?0y zd3oLY@4pwpe6(ZOX+`V@Q1LSwSvsm((#?Ih=Hem*u#AA^9r)!|+p?fgLSYV!lUmQw z=83xJTULW`-eUF?H8vE|)mHtlL3aMj*tTnKr?1aox07A#%3K9V=9rzJlBeGd7t(qN zRt)o?OD60xOgRwl2tOZ)V2aE@N(l9VNbLg@b9DhHPpr*pe1RNg#xcD0=s@sNE zQylZJK0Df^CQ_F!DFDkG%pRY1GD~u#E^32wCcvlk{1#jg$h;2KLX3e4C%hjiN^P@ z{~p+(VSn`#Oxd7dL8D&r!VO6^YS} z1ko^PWwFtmBJYz5UO)JNc_G!vGKK1Q9{V^sUDh8nb@fyV2)e7!YRXYGkLeyUHu$^v z8)mM6uhAd@!=nn-AOd?FFP~KxNlW$y5f-Cg<+La<-{)Sh&qqHQ-jH~JQx8Ox#r@Md zb1`4tzk7&Jq{jyO*JdcN>L-CrwE>tGuolAp#uah5OuQ++Js#Q)Ci;6|cP;+@MHJjf z!YC{LN6$Pq=2>_OpVsI>*pevK?qF~NUnu^vns>g$CVUj_?P(_F3*CnW7`G~^l?rBA!##sNnD)*;Y%2P7o=s=tgnYcv4n> z&gp3i^JC{TwST@Yv-`LZvGEc!eX%afatj)YOw)qs_HQxQo065`bEgG*vD&--*Kd16 zKi(3+Q~+T=qxVnt9`DBjV?W2i@4V5{6rGc*ouzsp%V9Ls_^shwWcMLFJeZ44!lMJ) z40*;PQ1+o8G<*Op3*&b)YBJ}}ul+mI_ly71@t6E7>sirIBecs!_!jYS5*6%|Ep#>z zj~lZ+U1bYq%N`_S82ey*h}E|`yoQPtOk#+XK5X|#|8&FK7JvFlDTaQ|dTk8vSh58g;&z{kK|otaqJ^d%|Bd2Wk;8quJ{mo|M9)Gg~;$f^3`r93zkc9mo?}FMtkz{``6M`gJ{J z$A5<;+tx6KwC264A~X&z)#gj?6jay~g9>kSN=p^=a|mn|E-$=@w-a zA1M~txKaM_ui1+VJ9f12U80WbeYBifBkq$<^_Nro=g?Tu5QW*IgDd#4$DW#h(3Yka zstGwB-s#(Far#x?9xakV!C2uJy6Elw zeC&{+;Y-7)6t}iRXiVUy&%;4Kgm+E`;qo1yPu<&o^Q$l*Vo*`&*b7qN>PVG7ZxC)a zEo0z3sT^s4$hVQJ#VA@<<8Neg8R}R}JrR+|JmW6Y(AvNTybJZU(M`2CQ8A_p#jZPOg z_J|E0u#Trj*-jk>J%-dB_jx)}+nu&W7HqoFEOpW5)u&9S7(~eRMG!utxKg^Zal-~j z;{zjp?rr?zNf<=~H$nk3h!dKel2Q+GGazH=Ypr7=IENeZuJ08l6JFkk)~2|IwIyt{ zuSQyh^_k1vsVS^~gtl@_iOf4`1XboNjA4(e2LX+{+@QqMhQ8CW*o;$xGi(6XO<>rd z&2agx>t!w7EPB^Wc%&5A=gSpg7q(BSl1Jg!oE1~C& zFExPwC!CZWxz7Et_oVdZd$S^-dd9spl}xnPtG)UBVnVo%-sF>Z&5`{e{bJ(c#e49k zPRl7bqbeYI5bShEc8z;g6h1;R$QxmP_~4SiXxkDL$E_V5Uts!*{&$~RIykL+VBd%9 ziDuxyVNCTY#1Ig?`B|d`G6Rgelf?v^p7_} zB`}+VWE~ZVbImN81e7~gm11S73+_HWYX;|^i0|M3W_u-jwpVJM`a`s$TakTL(h`Q8ZQ8yl~RuT$GO_DVl6L&VwW+C1LR zzwzbDQpQS%hjPRX&1F8c2P=WMZrv&jRQMGCty$x;JB>ECYEGwXx6vpbzN(rUwRi;I ziclSSBR-FG=9BNNk#X(WX9o{nlmfj;h#keNRTO+1jE&uB8uB;A_-5{j+(-S)A#zQz z>W+Hf$%kK{(E&tK>`J0E(0Gou*NBN2%wRq@MQuRda%?p_E#Dd<2f1`dhGsLd=vc)j zFaRb31i>OAA|x0QGb-h@)4*UL9KjF+B*?mvbLDkFx3WMvz%l13wvjwi+$d0xXJRv2 z6<)avaM3ZwM_nNAg6_pkq$fzw02l>f3Iv--OtYL_T!>2(EcYOaBlcLt#uTrSf8IW- zVBZS%??TBu*zZ|OW!f3v_|JS&6S-aSNRU6YRQA@1;>q~bIOgo z50)rdx~GTzmg`ewN!}&E)*m67t5wfUY089U^Hp%M@#O(mqY%3X&Mc&AMTbfUiMO%FI{gvt-OPQ=2350EnC)TXJQKYj#jXOWTS{}}ds116(bkd$3i6p`SD zg#h!;C%Oz?_&D4M$a^fl*>jIx(l5k)nzI;gipeoGc%e%9`BN7fq09D4{8p?U4!o`-HC@9 zz=@vGMjRp14i3JemdQ8eLlOo@4-iyR;HRSMVvu;ghpH_N0Qv z=ZE4En6J^7Bj9(sxcs{@WMXQ=8JGOxJqQ9R#cXVKmeUdqt&ePkBE9c=x1B|)2b&J$ z1@RNR_0LfvU(3a{^rp5I5q8EGE8`Tbi5pWVstEpZa_;(uv`D4<8FoODfl-URU7|eV%u) zma%;HZKjmK4Vc^z{T1F0z#yP^M6F4375N1Z|3wIL`EZ6oJaGRLME?NI5k3d$_lZT~ z{`}Xyy+l+AbvPYbOj3*dwq~avk~5{PfF0H*!o@prOj*lT#zHFVu>0Dg1!}xvj&45A zG0MYZHFOL2z?T+}W5y>SXAG4u8gSB$5Q8sxj-x5)DYb8IOH;vcp|#Mdfg*Cm5F}c3 z>VP7FdApnFDw-`x z2Xw8S77uJ@tM}ForsywR(&vBEDRC+;`P1812ifT@InY(&l@b_|lL>rOe7O1V**7L8 zn*|+Dor<;>1M>gbz4l@$(7*ccfC~e;bVeX;GPQrL=KhOHOd7n7{U{750;4mf3f$Q_|sF)xZ z31icM#fJeAI8a7LMgvpdUe5m+EuCEav?73Z+|i5⪼#YUom~sg>9in<64~VRaRah z-hcM~3u1V5sFo%p?3ZW-eJ5y;Fu+vk^WEjY#D_K=G3?R#QC=`#`RGEs+1n1w9C_{* zs4KHCV%6@2szifa@RkX*j+&+v%iJI>t|R#l3P9rb0r6S41gTH zGg7ew&L5tiHp(3TzoYhF5D&b6J^4){#L~3p%60*D??B>?3EM}t^y^C3Ki8`(n8xdg zp8Eas$kOuf+Ga#B@cCYKc81h0R@Xku&+sQKWk93}^zdCD@=(KE%r;k(P#U7fMO$YmOH<_c#3cIrA`-XD32N zU^2P`l%~GR3&W2BRy1%@8-lA$G#2QQsxV}4B3^x(D+?XOG8H!vosE=;#9X1b9H&+# zY#oSMI?rIcrmhoNO$tzFa7bO&_Ro< zIw{rzfbWH$@9S$<7Hhwt0Rj3(NK!;rpQhpoN;Rn-O)@kZ3ABc61#=ph2;u*NyHr%d zT<0H7l`EY6O#mWA7*=6`<*5L8Yp(PjxtT9?)Eg@hSmdrI`jV80<2O!T>Aki;IiKi@H| z8x<@xCm^(uub$yM#f%AA@+TcZ_2@%wAE$djQcgB`k&!|@yl;BH@p^snyeCgKAsjNC zdZR*xmXVM$2y&~eOf2zM{@AZb-9_05DbsWcEpN#cl*FiC}Vx)Zh1xUr_LxO-U1)6*@ggz95)5HU3TsXSJMO zQEvRH;q6If7&L1WkH#d*wNq11&hT^Yo}%67uh8LpENd@?p4pHW6A6^7n9pwiB!xA* zAi0x6PGGi)&wChe$CcEgp;-QAzsx``9H^XDUHPcqU0j9@{nxCtLf(V-K0&epiJxdA z-~lq(B9SqGzw}eaTl>rL(oSWCh-ur>Rb2=T7@v}$NT4<6n{B}b-Z-z zqCA#n(Z3H;5K_&(ib-r!A*pD*|6$p^dk}H`^Oq6yo8iE9CL}x@4&TYfb@P9J1#~$5 z_}+TEa#r@aapn5gQySYnB^rA47Sn$F`Ph#gdEYt8I-B_nD$6X9U*@w0?4%$T5b=Dh4H*pq9ap&w|lWX;np{-EZqw zT8(**5dWMGgIK=%{-L`$QOBb%`=CtLY*QN2yGa9m$uqCMaS#mQ~y z_Uq%gA?TbN6*=jGD7eSi3n_U&q+s(pB@a=Vqi?#nUk;O$3UBNA8!Pi{9v&X>W+y%N zJeFb}#+U_#?m&IWsz-i{%9#5QCCvtvlmG0TVU-t`#UUZmF#XJZIBd4NF>u8?vz*U- z;P-9qEQdcKIa$_{2?MhiPXp)TWCQ94_649F^u9*ZH~*`gPOUfxSvx2AL&PWfDd!Q4 z3=z})gY1_E*MXwvWRy-y99V98d-IXgPF`iVQK;ueF~>`RIjP znkNWhvs6wB0yhSX_y=hXh@Jc6=P#WnSoajBBB{1|$;in)bC4gvVV&*K)*<{*SOg>*l^h!_5)*fClhQO9{J3FhdB9K2Uo%$2 z9RmY&tXR7QEZ_!eMo=i{w*NSR)e>Mlz-l06PUS%m0H?kSGx~Q}R42tJI3r3V1VZ4R33|kG!7YQo}FOk{d(M zUM7a`hmjo~3_b%C%qiydvo=Bn+^0XS+072;$}+e=lcF0J6MH!K;Kh>zY~(H?i9(il?f4Is2KP{tku-_P1dQjC46;{(k9L>tFNS zQbk1tX`T+fAP{$@WLcPrrx+PsznuI5AAiJb1MAhK_LJp7gl0-CzY&43^^gjyq1r!P zrDSOWtc3|IFjF3?4Gf zeq9G~Om6NKi)+z)55hO&T_;co3=;{t)>zVK)6xZoV$12B?hAA1z|h9Sv;HciN-&{H zkUGTYqrEX=#g?z>{|#rtV+J`5t|)G+HB&M52J);BQ&1zt5MsX!JT2^f| z-kpM#LwZZQcC(+tRew>1aX6`8M(tPDV|olzcLEDx>Vf$e5cM$Ze~>?7d1k6;2d}!8 z^%|=?%5s$(iz~`sEe%5%3!4n31Pi~@ zW1@-@zl1UX=m4UCkxSpVGjQ~Uzc8d=+e_YKF4TSOmPY8em3+;=%&`9k!LJE*y~gsq zW7B;f*hylL^OSEH>88G+Veb{)ZT5|)QvFm<__rIJ>?&lr!#Ja#YnCU|4|i|$FsTnQ z7Q!wzEjW1iL^gk6&7q}azXsHPpln@%{#z8{%jn6tz>-3Y{@11vI01|*#ODjYJ~rYn z9JWWbB7lP9RZq{M13&Cu%68FmwXZfvXEe3AWa1|7q@330Yh7Xq?h_ju016O!tzQ|r z*kP=J)g(vy7k)#s9eH}Dah<&b3R2(=^8+DlR{XyKL{-d+RuNxqR6ChCT3*$Eb7#+g zT)gyQv-3*Wr)zV!Vfp}`Yn!uUtoGZD@<}hD56ncZfV1M-^+w~o>P9&+Zxksg`%f>< zogn=jS`Q#z1d<>>7=awS{P@rUVz8%;scTUvAtK>_SB#4j?-w#o+34fH3Jfv@N(5s$!4&25NiBseAbb?CUd8+LGp;TVFE^ewj% z(mGNgpyekW0r72wPSUUyzW`fpK?ZX;e?CD!Bqn~nm~i22+nu3~Lm#L0)thTBJQWBQ zqC5>NR*3k$-+y^9BQP~g2-(Rf1^R2;X-Kg53LlL+i@6GLD!%8p^hB`_H<_Mk;fT{{ zLH!3f$dFxzy0jxCegyn=Col(O7PGnttt3~$u#qr&&=EhVX)w+-=?}=au)d|lHf&w( z+eNQ*NOa|%=@xiAlqu~sQ{H=X^BNyv<(oQhywfH}ee5BUvJT*ektJa2mq~KlM=ESC z-TQx*xsNy8=lgbs=86+#`CIj)MW4#xBEZ@<^Aga>w0nCCL5$BA^xRaym^c`>Fu=xI+?dg609{w!# z*z$1dOVb*>ZBpIfK<$Rt2}n$I-C+lwg~*h~s;bJV&Poa$ReAttU?<|oN5$Z)>>R)dx-`abh7`P zJ2hr5J|VM7f-vDS0uTIxlC5|K>P}w7LYT}PeRmsU{m5O`QVs=`J$4L28f@$V?^4B^ zZq+;BE*ukrvq>YMro;B}(a2Fo7c4Mx1ix2!Apd$VmU}!yBZm^e@zd<=?B?|SUkLv$ zC5489CVCK+Hy=O$Zp1Ez)r%H&6VsHY{I)$x?7LZ;*iCh`wger3UP57|(nba(ofKyU zrE?%C0~`dDU9v^##$Msb6piiM>0lm600tQA6AL@wMu34|j=jUcoHQz!O*Ul~H%$ce zyS%fm+pO>^v}L~s6%a87v^X#GfBl=(&#I-PSO?1^QVDuJs3jy*r#A@-ej!NzT)!t- zUV|I$J5j%iq&$?CWSQsq!%y%=$wF!*coQyB#cV^oy3B!#-OWC|<(09{mECfh_CU+L zs?#kJz?p)?Vsp~VEWq*q(|O>`6!+c6lsjrsucE?MR)mk0&=Uz_j`R$o$^?392hb%j z0mT#jS8btr1CBvpID{j@NqA6`c&@#FCZYWzBmLv(@!OZ(puqxN4U8x0*!qLjxWCBZp$hf6YE z<37E=^7|BOth4^P6j9Hffpa8O){t>5DPTukY9wZe7=V^fNB)#aYa`1_NUI3+2M*C7 zqXe;O%u`S;V7yLLRa0tsQ4OF?yYm?spX!)u?ifA$B>cuj8$kwtKOhr{fq7TG%z2u( zyXjA-F1^L;OEj18p)2HjjIIpR(JYY5W)5OThN}q}f*7j9Esx-c0LI8yDju|1v!Ubu zv13~7D_l%_hiJaUW$4@a8kcjsSlCRsh$ubTzCH>Rc_JB>=Yxrbld%J0C*T>dwCO4M z5y6DW%_q!0;HP)EL%n>1hk zyZUc==u#JL)0W|AL&ne6HhXNl>7P`vR+UGxv*_^#nr#m8UE(VX-Bf>$dAv|i)~R)r zQ;d_DXx1=pFfxI^L!F26c8QRiR~~NlUpc56UD&c~qJE142PA;j*$D{oh#AnOW6#za ztgpeO2rM}2p9EhAKg&~#YSX6#?p1fIvG4q1kQ+C{ZcsaQq`zH#c&3QO6{+GAPZDpcSVPI4`Z)VKcwETvan?eMrw!k<266 zueC}n=_uG$K-548%cLUc?Cb;qg+vHUzlkjz5+L^TXy=+K)Xf85MYj*OP;n5O>s}4N zKiniapt1#hjljU`xo#b*{n?zz!MVx_**Ia4lVZJv`~NJ$k+8s58o(?Ys|Sj;olr!Q z9^_i|dT2ySAfsCi*Cf9WXkQ^&gf@wo^Pph^1r03Qi&DMkJnX?fYX%ryv*T3SxACP52} z(Hq$zBjqFE@Wc4lHP16AI2>9GiQ@%!t9EC?1q$^Gk6Yz>GQvzSKrAIfW#Fttav`)Q zpa(kw0s;h)+rY3T#|Te6)2!eg$o8OU0f{A57KGh@|Nh0q4)cE=<9z|G3u>in27

eVdrwgCK#dNk<#1rEjQ*Ppop98;_Z}3FLtrIO1%I;Ht#Q$EN{$tZ+Rawc{cL=VBRzJ?2EXA`08VY0#r=GN`YufMR+#E85 zgZJTDJSC)l%wfPWzxVYFmVjVNfkZ%|^xQr246^WIOLvC28RNUzf^MsdW)BK&r7`f0 zp>G5c?cW&uDA;GXb4cyS&T6|yEWtZ16eqpujNrzN4KSlm`T7baHaVP@Mf~pRgSTz| z3e5L@eyb#Q^Ky_1xTp|2$m|1*AW?gzgKlzpnO_OKv(Tz8n3H6uuHcqIx{-o?|hT9IluQMDJgR=}2+zFD9JDuOZ zfA5sL3-=NH!@J*a9X52+-q>2ZhP}}8-oc`0@(l7h7W_aV0pb9CgbWMbC%4TdVQB{^ zl0(nUqNjgOFHDdfeRzHd^$nMPJ-G&?1{fDP{^;t-IEVb<9C;lr>&<(+h1Fs z^-a}1Ug^VK3nqd^{L=r&(|3Sl-S+R_W=IGXDr6@mLPbVM_D*OCkUn?v=Xri0#z;35yZ@sFA}CDO zkz)&;p25-&>{q#DGEo25d4jq|gjuK@%>#;Yq&8un22ekY*AJdJapKTUgO9XfD~rK$ z_x9*y-tY9jUK~i_f-@)BMDiXmT?5YrA72$)ynfDp!M%sp2og*b8GVaQUk8Fh@vN+cR`_!bHYpzpMvrt^ z8rV0z^5Cv7Zw{Q+gBFh{gE8v`ROGlW zAj8myN9Q=Bj*79%e;DUeSX=8cT*bqIhX>UY77j#y6As)HM_q`cJe=?l9D%C9 zTMXpbzDof7@kj{+q|#$}8Ys-T79Q_0J z512^+71O{n3=}nr6bxoay=0t6#!eU~+Z6+>s#^G=fUgX@Ap(4_8*f4MMQZK5);;P{ zCDbvM!@*W8VDekMYNIeyp0!wtzKw%JsQ*uqn9%vvK;2L#gVmtRz9p??m&29^e+a-x zas}px%F2-lXNdh6EPVkH$hoT7T0QNRy)ET@Ijd^WiNDL;C4CN6+k`6-nt*FMWofZ% zgLDG+B*G%j#-S^Kad71%BqRt5k8YyyB>cU0V%`Md0Ru=n_!9K@dMDgOx{M~C>eER0 ze*3$Sv3w8YWk$y9myz9o7ZS&HTouh-fXHyR@M$IezbFfHk@D7hk;X@-((#$Z*uQL4+eDFf*hsT2s_oleTiwi)K+wE);>Vc+DVwZ%fJh$1 zxO(+3DM3)1=&wHBvby5-AFuM?U-C-~-+YyZ#Tbk^q1412mYSklikwCWK}d&ev{cA@ z!X`xE zLM`+O@q#3v8<$Zdz}3QhIu%nUJoB7aI+Q&0y&zwKObny61o{CKDj1IjqTi@z*tdO> zbN9GH0r%&E@7{+O_Bbuici~=S;R|)R|nccyfVPm;D!2=NdVr=)tbS(l(3eCDLL5@N4ofqq(^MYl}J@TpRXvP z2_#BbEV)S34MORIJgfrEo0oc%4~lEdAOM9HgpfHceQ7>T#LlPjMCQzxd(*;l#X~>^eV+E=;ieC6JImmeKe*HpDb2Fl!OVFxbcU z)tQ4NNhBNeZPYIqW8h`KOj!OW&f-E-NKnF^WD(&Lr$fEBJMNDJ-}Wzl(C?^d0I~tv zTm&=FeKO0-*8!g;^%WQf7!NqPC&03-w6rEaTGO`=ex)&uMESg7$5B!P!JY#(7z~`= z1DF~>TqWEZ`6BPnKhG4Ew+&D2b9>NIn>D<1$+%Ti|# zMZEbcf0=Pl@}$BFjgp$o7q+hDV=cW_;%pzT*Wb=hs^QR^lt z##zo?=QE!$PS9_)Jy-41mZ8_|j_oM8CfhEgB_{e0{0x5egd>FtNj5!|V*D3*L-PGcpB$43Q!*m1?vPIv93Mw7upSsHIxUXHIu)4oING4@U8T zsUW(rL^a!;T;_s>;G?1Hf)&w_0zx^y71*swsfhdt`J)lay1il>}g z6yl4GZydO!8Ib|31?d*q0zyfs_b`0Mf86&B&Tz@wE0Ur7F?HS!C$-{<8^-V-j&II@@!urmEum&tKC*`a_fQ@3N?h+D3tJ+=R*G z6NFB?XeLyB$j}o{P}t+!a_xeba*F;gN-U44@umHVy7l+Ix+dH!W)i7r?D{o*8m0?! z$(YuXg+h(C@L&KeXK`sC^-+9Pd|`Cds4JiWO?J}0T4yZ<2}{oNHvt~!tdCWGuSlim zY|j_xx1fl^nqV6Yv5 z8Cf@Dz>7&^8`Gy6)N7AtJB${j`W7>t4NcotJcgs57*vVXN62OZQGO8Hd6uC^r80rP zD!$aeo!xlsFC5EZx4X;D7Q2MNw?@9R@tX1zIFVsA_SDyLztXW}5P@N5-8M=@Z#oiK z)Bv1_+)eN(v9lO+3p_GZJtgMhvML>8e{^4U<87d{&@;+yvnc&MEW`Hw%$&vNX#-~O z)R|{4tf&S7M6d)02rnZ{IPn*BjX|YMb`%sz#=k*rSGYA56PQYN_#orl;2h#Yo7=QI zHXij!Su)Jaux$Eq{8Vbog9{W?w}4v{e(T632l6u%?k&MLz%idTY23XUuC27x%y)Nl zF(Ye{eo8!+v{ZoC#bGZpoIIm&;#5i{Q|PtG1@})Mpwh#9267#;CJ>mO@r`^vP+;); zb#mwf_Jc7*$Q`-*Ym)OytZ?V1pVdZC3jVb1(fj-9Oi$@_{aU0i6j&u~jl64VEHVuF z*+Yq?vhwF#2DUJpjmusgGLL=F{%;Z8s}oXI5&^n40jEA)`54mu{&6MEWtkuqBM|3l zlAGv`4A9nlZr=Htu0m^g^0zG;-6B{PMsbTe`& z{?1eJIr--mC~?a9xKPO zPS9RoY(jy_$466j_>BBuNA-tNp0W2zTW%&$TlWB-3yNJoZKWlb3{!q!(AYUmh+%r^ zr^pFg&!Iaeu|6?KgjIj4&Q z$3xxiNsngvBNK9p!-06v^p9kzA zX|PgS)xwjr>+pD+sm;2s?bSL%Zo zH!*OD#2rG1h1-m9mExJ%hi2^CYp}i*ZOWNMf(f zkowx`sH@68ELyBUQ6nAh{Zct8YexIiIo1A5Wz*imY(4FtI)!&(3QsN5pON)^|E&7> z7HfgF+w36+{W?&7p>?b4`CJ^qDp5e^bMC>lCuZ~cdv@+|@?9Tx0N5PH3wHKmI|bcV zD;vlJ(>`UJQ<>GXECiwt6af8N_}Uc{*UwHxQ;vS}vKhKU?5LFA2DP?0tW2eg($(#o zdqu;BSOU)!G+(+wcg>~+r>2X{wZGm77hdnw{TlFPokM-pB z&NvkFFp%eGyK8mh`nL16jJ15PTfI7_|HyDtl|7t`fDxb#ea!bT*GLr~k|yW2*; zB4?yohm1-!TG=AtJOi`*HebZGr*q2b=52?eUjk0+{$r{r&3+wQi5%+;x zV2_x!!P@)lA~c9}HLOnm*jVvrwTebs{qoZ2*|2=!RgJ7b>Jh3)_b@&rtW`S`IN$4aV3 zuiBTkp|b?AfG>xahB&{@XM^&ia`WMzs@opLWd+Yk@VmK!v~o!37UvL0zBl#XGon9z z8Wc^Wul;3!{*<0;Wz&$1V}yLozok&i;s>9=YX0T{`R@Vtt}LtSeZFl!bNWoQ>W-~6 zsyr7W`Cg6nHhiTD?WUA#`~6;(s*C|Pnglcyx;hV0*&_$y0TSMHN=hIaFN{C8NqTam zobU+RkyfI3Zg=P5SQqzoamKQ2u`Nm4IN>%b4)PS>HIa4jHiCsK1-e}z|lM$04^D+9lc$(Z+XXTPfu077{a5u+zD{A0Q zl>qrS7@46kmfl%qdH%rI&?||={OsJzJ#6uNjGstTkbH0rhTT^M>?gDgOaMU`$Juv2 zLq|=8CIaqRWZy%%CFI~Ws3)vTOiy!#QJucfR>o)J)4V$TI!zLa7y!|b=OA-|u7w}_M9tYca)>PcPQi@AuCG-~;M#}N-d2YT_J4?!&8MO- zPcmWuR)(n&aPFCC<2=}?!wx$p^eRA1EMq2@>z`4P* zhvPOT{&wdVMH16SVlCK|w@vvB?UzX{(tMiI?)?^~${J^Iy1^#_#{kVbd6+O9K@EgC z5CXgt7rw=RrtGkvBu<_HVMGQ||8Z{{b8Sw0Bz)op&H9cHM;3bo8zb=5(V%xu>Sq}4 z>}H`pnE74|+gR}$5fiJ&V~_5z_iDo`2WL4N3X!{Qdj|g#$MUD&FDW*;RWKfVeRyiS zK25jQQ>d+9LU0`_QhB@uex9U*1M*mErv=f3v)=ovCR=Hw1@t8Z=0z(HT|}a7%;Uj6 zi|H8~Q;E>DCJPFW?8DXc0Vn_pOExyyNGIA#iySYGPYJ#yrY91ES%;TI-w(O-A?H@V+p81#r;JI`M_()F`XUWH48(a*Jj9gYUZQM6J)(Q(s^;o41Fh?b zfcpzNh;$3U0by~}4DLC+uF=EAZa|K$g{J;Gir)8L6^K6_)3jzzaT3{}UcfZ&U z131sqI40->bzs$iySp7`vOXy9!=#P=36!lyc5>vx>x6=``^js zh|q3ir49#hgzSKDO{lW4!~)N$$n1@I1cpS2R=|wvF;c+fA0HSGYDFXIM@n2^v6+%< zQk#WN;fmho`yEvqurL(^Ze&-CoXF4)a|+}e3_9UT!>q|R)|5)8U8N_QY3aAsPA`f^ zI7$=25DW$~@dA8}jTK=VBr)^nKwQV54GLKMqyPZvgb7Czp9aQ)p%^WNxDbG~P987T zu#|QaZa!Jn$q$Qx%3A5+M6VG&@rpBkWjyy)beqAogx>=$cnvycZ|~c})@UdR(uKhX znhFr{b1rL5>yAGF4b&@9Sh9V(?NaI$SiT(>z!d}^>v_QrnUE|eYv(- z0o_~B&67^w=g3&~0Lm>wD z0NQc1-RCB^pc4k?4w75$v2PN+zaF|yA3yLkfR&(-=RwON(Fq)H{3qyemC_>pUt;nF z{u==eoG6dME(elAFcesJf%h|U0LT(fHO4a!`!z@A%IdG5+vR_W=aWfOf7o+4*%G=Z zRzeg1hOh&~Y7^KX@)&Li;Yao~<82X%7E#8a=!Ybgo^}VUh@pr?&5w`;aEahW;A3`| z!$H^depv0-!jbJ!zHOJxx6SiET*<0?jt|w{ZGqQ`p&GIGHkYu5{u6Zvvy2i{mcZu8 zONYNLqE!y-Q~Y&!m_Wh+7#nah@D75nk2?_x-WemS<9gE-mK}|~A0l&ww|tX#pN~R2 ziq}f;c3|D`8^)9X*Bh1Q3q%{8m$)+ccN7Z59uWNbcXxMR7r9jykKa!=xf9wySU12u z$%HUbH~hWE$ffe2OXoIv=N;03Y|e z{j|*g1iBRLjNt+-i&P0#H7;6^cJ@nr4KxVA+%LfH&GRev)zZuFqX!T?5kEK^5bAKB_$PV~0&|Tl$!ydPOSZep9 z>#?$u)DCpakgtw9UNv!5s(zeQqk2jcua}^DMDK|;i%Cwg~Sf4~xzP>9;1b>Cglk)OZB+eWvP!dUq zLLacNkUWA6az9Zc!nqFhrbv^D{!^@QKobB87e5lQKT5f#$8&bvKiirXZREc#%A$ot zLAW?s!%BWWkQIFFV7x=M+_sZYlM)UO!Ud$oiE@Gyd#SnZZru=jvuDB$Suf;H2)J|) zG$i&Z_)$|UiN!q#S00jAa8yopDVF0|gSht3^O6h-0eygP7~wkMgKXflICT&J?XD}P z-!3?RteQoM0_NV@ye5*}I{8P_fs-v;5 zRb2sPcdG08@;V${Oa*Jf7DgWQng6;0eAxIBwd5ud{2TH}{<-FcL&Ei&Y__85EwFr{=WuGjherZC_~jH`raBf4rEiK2x0i^;L&B3J}^lXllqTn52#| zpAh3Tzto5rNW9*`8t=a6SqalktYe}_=;P``dI`_NmYe>&FGuZO=~LhEJ)M5wX?^1c z#I8S{n=uzAk=Q_a=^92!0Idn_6hl#b?>PuHce}B$nP5XE*fIfBrWF%d83A;ZSbvC- z%81xY01W|?@Ym|r`s;npuPg z5UnDy_r{7-Hj{JUYv8luDB$`owM4e_z*M7zTo46{x=h>B47Iz`KkfAb$ zIPihn$@d!*3PQVR<3p$U-?+0Lj0Duw`5oeIjWAFEJrD+>SRRL8O#&`}*)=xvLYE%d zUV7A}{4lMjQO>Y6%TSE4Rh}>YT7A6IGZ2G0BCG_v3(1|_E5bg-PKx|t>yi%{rBOl# znrB~}eMGv9Cpma&DCL|LS(&vh^7dK14VdKHwdI3@a_goj1A{6o539vQm=L8=nIJiS zx%_-#Ghl1bwWpv1CHzOsx(h8GAZo(X$AIW0vzq`H+;sr(##Ll|hwQAHC*b>^zwo3{ zI`#1qyYd~5JS?vRXTusYV_4>6_Edw3Qq{_`7y3~`$0s~XBp<+?WTgX=$Gt-=XxKhnW1J+4z(V){MH>{N+kILUr z-xq3Lcum^*d`hKXUZPa^!uEG>=r-9uk8FM9B*TMZ9U37%WN51WY&a_B+*W9y{)6eH z6R(L~N8<(4GpnyoKQEa>GJUP)B<=}ni3coQ-l2-V<|cw%t@^ioIvizlwz!&}Usme7 zpZDGXj}1yxveU$-+gZ+{@fkk@T7Ggih1kPKwd6C6*B^Y;@|SCW31{JVPMNiB;Xejp z(@qHC82rI_flxg`ITT24A`z2RXg2wV_O<~pU}xDV{ehPM-BR0FtvvtI3-D&lk1l$< zI!fguXZ)jVfBnZ*YzQ~{g z$X@qhKmrTOx>)V65&Y;Mq^h-h5~g$*ZaGMD(98_h1e3UmAK09#7wfgR6< zCQos;P-Db!rnA5K;@4tO68BV*HFf`i!p~@)C>!#v{%0~_Sll)Bxo$NX-lA>+Jp*(u zWF3s@oS(xf(rzHngR|JCuxkvKf9Qx3_2p#s1ZFI9v-EP)mu&(}QpPC`HSD{7lH7$f z4U!ZpM~lgXmJwp)MkEVpq>*v3z{USXR*Aj}e5j&RGlB7j(UOD7 zQKK&MBJ;JP+rK#r_4Q}k1}nuL8<`L~r_*>2oL68=?(@HdiDDU9M1}JJk=DSn24fxM zplY1RDMkzYd z*;(k*Ea;eX&_2Waj2b6~Fxe5%(MA$+JLJ#E)C?5jlmc%rBxZR?hT{%RGF+_|qPokR z!hQ|t0m_26%9+LbO5cqbYYe_#o|;K*uE!h=)V)FIf!zOmUq|^wRMhB4N&kj*RiE%% zNz5}Vs7u^sk4Fx40rZa#KAFQ;y-%$B1sWG!>7T3`{if9Upl0JfcZY!SNIEySf}DnqEsj=AcW?6{F+5v27EyVtg+nB zW`2U{SEX2Y-J7*OXR9A4OX@Z)Aqm5LmPq~cg_nGk?;U#<1gZi8!e@L1vNk^3m?%g| z)Iu)-uS`kfX9+8pL6!n*4z})CQvD(EoLusA^EemQoj)S_zeSuFV6$c85swr9b6 z(xPMX*gWrH-)V)#<#T5Tdp8bzN1z}qDVN+B)lqXQ|1i-4!!mV{IbC`AL zCg0ahSD59lnu@6Wt)r>Kk0V(W1qE^JP|cvgp&Bg?4jG6b74B2ic>M@~2mpkwMAU@v zVHqSk0FW?Y%R-n9@U;dC2y0Qi4H?r24MFf9Fe61|P^5Zdrs;HpyxsW}S$#4=TIyef}l11)j0_L)u|_ykj@Q`4@4FX;&RFG>@O z*B|nsl|Y$^fh3rl@V$e6!GZ%a<+sCO)Lf~J7dQ*1Y~G%HL@!%w8mcZppart_b1vqddaj{f}{g zIt`Bpiy5#9EGIy#a2s`*yN03Y_AimL2m4%<9hwnR@c~i%Pkry$M${OR$15lllG%YX z1cPVax(V+V3@dbykG8cZCIAOf8x#H7_doJv`3!hbSdszH z5wNex_k0f14Wd*9XkrZ#FUAua7cm{^8t_P){}LmIH-pI!id13>fs2Gv01`?fEF-MoJ7NTiAl2%tFDRp7 zghn{G1B*=qpU4Zu%Oo#QN{R|JE4xw*wuxmKiX)KI5p>PU)p-hrIE>Y_^Z2H+DfNpa zoZ)E=;%gN;hDHB2T}NOIY`*XoN6Y)q8D+ld9Pt<#zWm+-X$!atk=06G#}9{vds&^w z{B_UD=Hal}Y2^;3al6_16_eX4vChPL0(Tk)0>IVbsS*KcB<4!QPzN`DJQeWR6xe)3 zWJ5U6M0N!ZHjzQ{JqJk%jkCk4m?F^!Zy|v~>5JukEKP?*`+5up)m(n@&2=@nMTIxQ zZH*AzaYGO^ATT9<=IA2<5}-H(hymCR^>{Vk^5iN!pv5)QCb_w}WY#?}Iz10ry+w3l zejG4vl*|RcUXM%%M;Euw|2?WyX?iZj&$=g!R4DjV$n87#>l)TZEv;4Blz1iR8k=LpP61#c`{Y8cc!-tC#WTYrmH;WcCX zV4DxjVWNJ^8T{6N_kY{&w#P;LZsLz?l>ImNi^NyTnoB5(-TfHxItEYZ0`yei5aJ;7 zUS!A%UqB@V*(mf@WRg4newJ}Z$P*1cQPTVae#G$u%!=X}ue<(ZR?bfEPG0vu<|b!3 z8&G`6RcvTz$gsP_C!UZspIPkzbQ9kJf7u=4S)ae7qC^>n1BLK&4ON(mHD&;~ydZQE zqbqHS$3r%{qx;0BGg1V2od=)wn|uiZXq3|hQ4KM?!xMV(Vn6UCu%Sw%dy(C6`u(+% zZYx}70lyl($lLkXw$ko17zWqslBN zw$#775TULVWTP*!ru8GdB1kcU;+8bC$hQbm=vY9U-Ctye|BeRN0*4$$w;#M*(HwR= z*CVoHYGFR|%dRvO8sdYIyl7vo5Q0&0#j15W$}aW|ENupWnPDhKNTxX!Fk$vbfWmVJ z1LlFf3L|G#)TdmgxsX$xr)5~AxHtUUu>$9YHCSbeGeLAoSQSG22+@Gyo}p484+9u0 zyjjt&NjDASmjja~lgU{y#Bgs>SCCQ_Js^Z0{xF`#?2*84NC{}>_FNifCOq2Vx7<+i zJ*;wP8#a-N_`H9sPZfeT_%JaCQIYEg*+Q#3(ww4Jd7NxlK)go@J&8a8i?01_wBRR^ zDh~F!S4dk@Zdr#YibzK^kY(54?_kZtvvImliJ9bBm*l9xHN<0Ms2;ldlzQJ88Jp^bNOnO{At6AeB zGXf01k%yp*G{9&n zeX5ZE(TSp>1#I_^tyckt%;+?128ivMu&`L8F8_sReL;W$^cuk#MHVL!p{}k@?d!eT zkOBC|AxI#Ee(3%-yTBUzN@rxuMwEKqDyjIaz!6_q6=2$yX<78rvHbIRcPV~Fuzqe0 z-Xjnb@R<_VU&uBlgibW8tlg);X+o)&C5|`T%_ER9LqZNx3W^9w(8Ciq!*~In2d=yWoyb=}}csZ9ilRg_;Q2ru} zhM!k`I(o}W8K)T1G##FYy=PE1fB>M;L(I1Tl@{Dao3AUL3zP=m0@0yx)E0*rW+%9; zC<$oxvk^N*QvQJy1^OkryF%3i(6KMg<;j*d8VJvvgAhq6ja)gh^r)(;*?9@Us`>Wb zntTDD<#~IVWIfdBc#hN*0A09cRPZ767P3AZv*|T31EhQSqLBIs0r0l6FE4a?&MY8D zo=5MCSr$<>;maL>9_x_7P_M6euW;;u;E@wWW)^px01A>&V^;8=zNQ*{FE|F^{3Bg& zxh{Y&jbAz4qTjP=;S%cuwKB7;&@uy~lU+37UYY+g0n0`eHcmswru%CQ(n~fTaFz`( zy0|%_)1Ur!y1(VmYp;F=cG(9RZP~P%=W_IBezz%9DNyei6`7G&Kx#;5=Wx1RE-Ho_ z<`L9@uK>R!1Gv8SM~a$R>Dd^d0PuX)rvV8A%paT1-`%1Qy8|5RE!7E<+?h4l^-5Gi zDA6FhZ?Mx7eNun+l2&jbDkAg)Btq1?0g>4|q!JMs36(prvfEPoL5RRv2Xu&UYvXCC z@yO&$+GWLxZ2jFU2eNxnwcuRgj!@Mjj3H86IT5NAkW6?2Q!(S%;f{la9{ygdsr2r6 zoVg)>J%R;H(+Kw%)_siBP*Uu&Z-(7FQGB7@ep|9VRvSPYfH~$5C6+}nDv;3hiT^cs zmd9~%-;}O~^^j5MW>*nx4<=rbu#H8Ti06-^{K31Zu+R$83W%hA^KG*033qO2MD4w8ZVE{pbU}<+P zJ`Tih;hvQ@kQuOp8;B{z=HhuRotxDBSZtr7PeyxS(e5;Rh;{@o1>HVQ7z$KW_h3ch zOKy9V)xxh*c4Ty@w=hqCCh~I6#t8Z&2H z-J9)sIYovlvNt9LT&a5ulM&E#zZ%Elj%aEii0>;Dt^v`&+bHK96gbQE1easah1E?W!yv111;elw37GV*2E8%%U z6o|YiGB7Du{pNzb%I=5UQXQq;5;&Wf#FQ?ew?)H)0jS@buVk?SH0&r_&D)*>ss;*A z3KDQgki<}GV;}`mH8_V?asWR(*oh-b-abYG#3dd#i&BmA0Xz};7y<%f!;066SvLNN z98kd$vT>K_Irp@s4|z;iS9OJI9S735SX5k0b|->A$b|z2_XcDPklss=;dTfQy2@_` z2%0GO9M%^0f|Q33v2+Os);zWYfQWg(c5R+ih08ZeR?uX?Uk90wfp zCf$1f_})<=?h7A16+%-)2TGt{EKM3ejK#y0Q-HtGPFz@C^guBf_ZU4eF8!X%KQ`H{ zj9lD{<`r*H<3ajZrVksQKIuqdU4w7_!LrCy9N-$X8&@$yL`4Cv?lc{k2s9Jh*RMvo zIKA|&kt3yDS@B*5ukd4(Lbwfh>G)Idohi76wA#SiQGyXK79>)@Vn|k`0S1mCL8VQqdMGki1%pXHN2FQ)n$mpERUElQg^Y#W{u>p#>`Ijlq zS044V_YH^pR+?;5w-;eO8*Av34t?@0oymV)@6we25lH_S^7R;fX%SPT2>qA)Z0HefbIg+ zmu`$VGFOo8eID)NV+rR+^$J-_d-2uWo;4-i1d>kHC!qL6>L3JObpaw>7%1*=WL6ix zAIv3C%M>del+`42YCm6^I41=^O4xzT`d62VZU$se*S)wzw!>nbI8L`D9yMu9kNa=}2 zf^6dQAS;sob)9d8*{!SB}5D zHsC9B!j$oU{@NJAqV&dp0~(dvvj`&hngr2-G-?=*)m{CH2SFULfyIU&!`hYiz+`uc zSmk1*qn?czhJA@p1SC|=;5I_SR;q)-7TKO`WNI^sg|#dW6Cd9z$X(Hw)K2!?D(S`@!mUtT<4xV*xGtVX7KUM#h9yxiP)J}{^zlUta$PXePu zPk}I4?~*0X-1;;7xq__vgx!~Cbg%c-Twlgqml*cazissa?t+O2{uF)|Sszv+l#jUy zG6sQ0NrjAh4`lPkN^D|RTce%#Ab4B{AU658$iBphnatxzXn*-OGD^mw4- zRYW3fE#pf3(@B|%ygNhu>vvBwzXIowzQLX_*_vh53 ze*_xP2yr^<)jJ%^akpRM>!5K=XjUj5)LF=kNr{*H@!fXBV`F`(;?}i~Q9ywx1LP{x ztUyX{S%sgH+ZKwC4d|70C+MO8#1&rs@wqMxiJG7@eSHUjBIlVBaRu5?EE?^3N>Ic55KAj8#GEqk@*AYj0Qu$`lz~ zVXjdB{Ku!44;YbF4bKt&pG;4VHalygsweg?aJIv7?X=n*tBrkwe2xtbCpd~6fF7eB zfHaUSVbbW2`xNK}Ei*#OpPZefQOzyiQG+&cXu)0HQm&Djq2n!VQII8wI3e@UYl zky!X^-k^+dJH#?*+>l2g8Y6SCxhWfRA~AdeDoHR_lPA%R^x18JdL6r z*TT$Us><(&g2}rZAuqDMqK0oh@(^`!?D@ZDOlkhKn)6}9rU~mW{l~^%UtwteX2qj> zQmG)Q>8^^3A%9AFO}?2*5vRV8*84n(piP8u{H(88yPsjxpzn>V79dn%rYRM~zn5`w zux)F);&-<8Q5U48!fUa9N$AGwtGB$0*`#&xRu)SxKLhc78;Ie0V=Q{VZNDeyvjUFH zFc#CQc3sS}?Meq>mCI8-(cs>G!GOyrIZ*`RX^gUDHJPW6Zsjmwt1grzP`xsGk{8yptgeZVZy+wyk~8 z1EC9tlpDVUBg-4<=sQtg!io$3+wE+}xQh4wchk@M15hWSzCsg+%YvaliXmqoFg8&r zfz5+(3V<8>FK&g{*EW2pMB!Wy88t98oL@h5SHta_!EGH(<$@=KBK4wh-!4f2Z0x*9O_wscNj|{Qlo{# zv3GLR(t9TM0o*L-EAMYlMpU^6g>r^~jj4thf*zepx7_jov@PLM7-!Ee09Rx{bGV-k z5_;0x!A_GK6<+uiO`Zp+5;050;ejHLL()CK<7Jq~uXm6$@?!jw-R@ z^jGmaWCY+JKCe5^-+a9jjUzq{z`-_7+^}%jEK_k-;pI7%8;;7zB-V#{I8hOsN5`Y3*Etle zoixugMQ{KO6$H>kv)x50xZL#=*+gAbH-%dTy4#;!{z)ihcrRd?I^4Md-yPy`eHc2J zwo&gd%+YabtFKmTC&5cp=MzTd(sCOc85(RKsPV6wsD$GlnnQZ;(LbK(PC)E3(^9XZ zmORwH=B~iaxPw*q(%sP>d>a(nIIdwjwe(QW2+bLT4 z{8olewGVJfbPzzY(ceM!EQQ@8JSOmiwfT=%Oa?>K<)|P*+#B8o$QGMmdkr4G0dw&6 zChGeQH(I&1oKidU_!-cbzm4b5aRtrXGt2uNar8lzg317mJ+e3sIKB5-XJ;!^Q8-*s zJ6Gc(B(7NOi0|%!g7K}JYfsn^Yd-GJjT@@PU8II3MI*+Ncn`0Ib|5rB>&_Ln8`gGq zwX_1!>o4N7gLMX93L&Qa`cGZ!sN%do2T}C3t<1#N#p$-dKJfMRe8JOwj8`d0!~pvr zR-qXq1vchKw$gw|f_&$KeXCJOBa&kqBAA&8#j0+)Ovdjmb0w>i;LA!fLb!!ICV;pw zNQo3;)Id-RU?)U5RSg7Uyx&3c*BIpHyh*z}&l(Sed3!xLR(o0>>#m%$t~WrAgnsQk z13($5f+@f7pSg5$gwo=PFW30av66`7J5k8w=UizjUC2Rc5dC`h zrAUfCvLIhl@qe7#xDS_}_2EqFUId~+z9C?={ivmz>}rSw_h$rngfqNRGV}-LrNldb z-1wzR<#BtrYQ+E9=PQb2fBOM^OL(egT(z@h{ zG*1L#THyuBwZ>WecYlXPDmHXt84jwG&YL$DLjYOR&g8p?!!*z3ZkcYea-mfb4)uIXo7Q#pP5wUBmg_sk^Tj%P*kXS@Vh5338$FNI zzB~_xfu=*AJIS8qC9@sz7JDy>YJ4`bl3IC+O{ZAshHr0~I7iJ^Q#Ad!q<(A=3 zuC}9w7`c$v&We$ahxUUDwXVF>=Kf(7kr`&b$80xU$fsX~R5{Z)kC<*2e(XCf10C*{ zw~4zDD+)i#{c{%EfS3qe2rW9su29UnUJwxtGQYhqp}BN{veV2C17rx6RMt7%ifYr= zPk4X&8n}MKhuc$9q$g0bg-^-u+0#HdV*PpTLhz<8eF^)EaLic;NGRqLkrsf5h=p)z z(7AkAVz1WSTokIcKYT5i^gM=eGnZ?r{rn~1B(;)<24C#2bzukS`G5TQA&}NmTJ8T@ z0kO!&3CRhev|a=bt>J_10|SvLFG;bB4-BZU!!g!DG5RAt6}`~L>amTjrD!Bb12Q%G zZ^t2`Au(JAdz0Rdo!{Wa({5)Cl)ZSv|B?1FvUzx(4Mi3R)D@fLU%*S=6fMh_C*SYsPcYXlEvrJd-dZx1iLFJ)YLu zK~3W^AMaTHnkNq>wIGVsZf8)qAC&8}%c4jI_ebj&5F6Z7qyqr+ai)nFBT494j&btG zYG?0GFx@w)x)77Uk63ebIO01YDMIn_`e_T+Cj%VBvxL2~T2rpNku6zkd#A(k1@Z~B z?p8_Ts|PHOG5vKaw?y+}wxm)$iS{Pe$?dl&q zU;T5oROJw?IjR#3UQTK0QgeyDKk&;4JODUKm)y%+TL8HZJO={egHDuHA>^Ypw)y`3k0+iPkPm<= zaP!#tOhrYy#0%$=#+mV5?hteL)~yWYHrtTuilNC zKyhgEGcqFLBxX;*YzRK(b#-y;a+17MP4)~i;GS^X)qAS6dlKUzAQ=MSKo6fq2tkPj zK`{P3wgp1BB+`~OaTa^&tItBmvy+Rf(SMwdm1}xLNK0yM31Gzs8m~>??;q8arJ`I6NE0?Vs1vVy$ zq(=kNhI4}f$=Xw=`FPOvyMZF~(`0fT)h(ACb=Uy%#xSrSh|)R;h#QyLZ3VV27?2+d z1&P>Ajv&Bf3Iev&#JS2f$51tB$(;1)Krv@6<8Jp zp#n?)fge1^@daj}(80RUX%)Rs%~Y%|?HT3SDrFARBUW&~yq;PKs-aVI2#0=d%%PTd z-fIgKVLbw)JItwsgJgNupfl7lGj`U9II1k9Hdh%H#3JFF8dA5i;AFFImhuH`w*I+T zW-96ZRDqUs`<<@#X9Q*lyi7T(+UJ~+O*?e=PDg%b58KqeI&o8$e%v9;R+Ji~ZK_4pZ`4<3_oSBKCu5Jv-`Sg6m*$_Q-TcD9eU|MaZcq}sB$E5lSAP9@mG zP^WzwbdZ7bB2OI(Q`E!m9T7RgbCcZ<^p=daQ8s4!#Crq43|DhOKo3eisv8BYf!3(X}J!pe_TgCx$A6mT9_B6zK2}4Q}T);WOoyP$Gsa z?jPUi&?tS3Msizq=}ben2?!~Py5qAUM%q^5QVPf(G?f@CkQx&mG42y)t-!fw!bjz^ zgn!a9XmQ7T8)|yN?ujY_ zVEilSUQ`e`7$R2a>2d7ysoTYW-6+h5jyR47c%N`%hPJ5Pvp)1GA-<$B$bvn0lGT}SX-}>vVgb`3_>nS*_CNyX5)zy7%UE&@hTUWf@r>dbDNFmO; zSwAmRAe?c)L$t6ma0`!T67cJ_l`g4NasG>vjDWqSDKep3_dq-*VfZ!i6@7qz)0QH8 z>RtwyPZl?8X+;!YgSbLV?XT7};+|Z+%OzXx#8W;8Js2C*Gi>7GB0H7PxuH`95M!e>DzNDuexP=r*=!Xm*+hpWwnKy)e@F%6a;0^PYHyJ z-?2Wu&BCB1(RoAD-YYp}QtRm6(h9MC(-^m~9$lM|pecl|j#aAIVS65C`V#Bqf=#z$ z=ED8#hTryIYrpMn^=SC1V;PJ)?eE_19?HJKwAG*`YPbZTV2%~GL!;4vvEvq_x<=t^+TI%4eLS$LA2sBSt2fo~ra>8>M7uLVCc3gDh+u|)s z^C}BbootFu)JtOBK%-c?&B3YM&z7((e@No}i1Ew2U}gd8*Ue4(%l7U{Op&l}?$I5k zmkv1Y`o(P=PIlVAP_uJk#XgR$C1 zhQC6i-;}lFNe5=Rf;9>+i5L(5yaz-{w`L7Ob3(}|<2O;h23W&cmuz~FXnZr+pr`G4 zZdMo~6W~k){o_^MjXX>u?2H%}4j)G2X16M2J`V&|)78TF8tB`+wPZ6q2Es%Y-lYmt z(+#Bgbuyd?RI8=Rm&X_jI1_ls_7AZ_`2M93cBxy}-h91?Q8UW+b00i-X|olrcXA;N zfWYz|MHyf!H@VI+R~YEoNow8;9pY>-gYU(RMHx$@LHu`aofod7e?NDv|09M|g1q!r zF1m7XRA;S^#|*b3)_FoxI=k zTjd-7%eRl;zx6~{xD*j(Z@j61F8>#jirG2#Xz8+|kO)+Lk>FoznEC0d-v(;MEX%vz z9!kQi#56^7gS1b~&qC-@IK`o5f73*(k=pvuuTyii!$QH4n+8F)vz5$pKIfwZ^KeiT z5IexXz+C`Z3IBS+%g^M7>z8AB!nB^%O;`ecqTBn}>b)Gk& zMB6(}>lSsJwo%bAT^eXhTFa}~D6qMrXp!A}=`zaF9#OK8Dnm5$@jbRqdKy30GB_vhoHQOOoN>?e*i93;$>Y-uBEr zG(YeTwkhK%jlQ~>w{|4)Z2Rpj5Qs?c*?wk`g(Dp(KD}^kc}{US_r8f;X>I z>oC33T1n;#y>(ZBl00(;(9}ZQRTpjbn`Zm`O|SCrq?eUt$lCi8X7jbRwHfsmE(R4p zwzn|lmTzCvpM6QB{1~WisGu-tFVRJRjvw9@4U-S&C62MzSa>~Rz$h4<#{VfBUw(L< zB%eylb$jWkGr9a+6sJ!IovuY+y%nB09m>ODA+a8a$K#{-)cjUSj;S-kKLc5+zS^=% zUiG#77yl#6`+!}bl)}PSn>FV)Y#=K^Ed(&0K~YzFoh~|M%QOD#0!MZmTX1+*-MW^Z zp5S-N(+!g+VFw4vhnCwxGJtFl+G0BnoS@QUwT0PPYfik@v0|OL>9qJxk2pCj{s z4vdHk4Fv?%E@PLy(V10NmzAWcE_n-t@2%t<;=hD zT+wSh8>=0Nv3*wPUGWg}Pu?bSj*AD~QVbrO#I6@E8STkVdSOht)k!0ziW(fm1wuvk z4Ft&tFVS16g=>*kK6*e{uNr*8PN8T&hkn*!jk@rsJ?5>UR%m0cmDB5G*xv`TF7fK%Gg46q>~OU4+2)bUpRqd0F)?wWc)=eUQ9#-i}MCz2(iH9y7z;%_L9bpd4+cApCCY z1y#mO{n+!yDTn2iL8J!64^_d3r@$Y84_dF2b2&jPGxO(9iS6cj=CXbOJ;`d+&e;K} zl2rNL(TUc)=r&cn9Y4omfh*=RyW&;O<9u-CpP9^%aA?TA#D5HBWF+1k#ftXtkjQZcMEPd zWWJ@HZGLeh#c3zmEf(nCch*;}H8@T3!82MHovwHBJG0bt9m}tyTwqVSb$%(Sdhmbq z@#o@hCHy9;*_W#oT-VZgC=}Z5x_xz%$qNaymtG+cWp*;N)NGinE{fg19QW{O(v~ch z{3D{4sTV#n?zz%cqu#R*c55dw$wi`#-ENew;p%+ATiTu{0{cAl(k(d`#EC$`%J%f=N77;9aPU7^7H*RpgH-`=pyDM~lq3 z7i2LotY@J*Nn6jR5O6Q*_N7+-ja*!NX#IZq1(rFiI~E2Mo_|Y=#vaGM$?;uGe!#_W zX8-e5v$;-q@<`xb0yh)6(y|5*@*Jh@occvuaaNG-0#16<>SHu5af0cQKJk7^)VYYM zs4%(T=<+b=CK`ff(#+0p}Ksi2t@$;Fo|$&+4P|yXSdUicFn(*UY)>Y;l0&CRE|x#%b5Sx zi4&&R_1W3*N&6J2p57`HkmI8=hS%GKEYstyl%bgDvdGne)HYehzrwlR+X~JFT@cDt zizsxj=M?_wexx?OBf9d_EPYGDgq;22N27G~gka->&Ism=g^A>|KJdKisHK_aJepjR zHUcV0a*us;N^X_$GaU(8%Oj}EKo7ghfB)hYYtOY}8eW0X+uIwi%h)#Nw0_j~r;_ht z;LqBXZF2FZJ-1Gm7}Z{H_TaJue>|5m*qx}WL(k}Xj-qB5&Hj}%NSigO#Yuhlv}D^K z_Bji%hp0GcjiYAdCXS&~pAjsvncsE5(W~LdJ8s>Uk`;aej6YeFH~o&!I@?SJ^Gqh1e0{+qTI0u2CPMa( z(yfyrZiqiii^0d>eL3JHdedK)>8xf*-L!AA6k11rXH>or)ff%O zssr7JfkRSv?}UEnGVZf(l^AYe)ZWoLjVw3*Hq%v8*99N|h6ixv*!g6S_MYi=+g#Fa zZOT$VvpZjct#nd>xt^=Es6Z^p!a0HUD^~D2i5Txnfkd%vp3r`!riYnyo&= z{p^-cFO=k8F}UPh+aepAIkcuxQ{|koS~Rn4kA`FEM}3j!m|+4gIZ0qaqJH3~ScFvw*Cf zct3 z{JyP6&|6ohilInNfGcWE&X91+oT%Rkpbhjsz(Y#LvY-Bhd)3$5<8Xp)V|T`U9edp}(`lVw&RXCWEDmophUzz?T7h zFcjUP2$UGV{KvzQvX8M})|5@^r~me&-O!))^xTs#D+b{lAYK4?h9D-xTteE6DYnXZ zy$|LyAWNYa9_5;LwrG9rB$v!=_$_Nx+wu(OZ#F{}2|l=g;7zZeGYS=?@;0`M{Jl3O zK!-()D(qFP%~bPamz1?P_4J3K&bn0Qu}U6>m+Ql%L{2EBDQBJ1PQNF^|E*mrk##)+ z9OA}UoNl;bSl!EIz3Navx_-)ZX{}4O1AKIzv~1Bel531_Sb8n;e(lz1PjCR)y2Km* z8T!xF?=+{+LLnymS77ps*t=M2K}dnoaFtgceO22Oxe%Bt)0`OH=0 zw`R7|McjHP5V{t-?Qu2lg4>K#~1Z7VCpiM;WN@mmLiK z(<~aC#i+;w-?i!%n(hf1(qVvH*(~tg2+Bx_C$J2R0bG`q6{A*L0NoGcN zO2a6bDLXrriZaSd!%VhHl93fj$V!rAMP?K#$tD?Phmh>`e}3-0zyCQ-=iHloeLvs# zc&+E-*=?&ZUHGKaH~-0D+YDE^ONWKBmuj|;eK4ex5|V%RKp(Yni3Nz`l)0KOk2G3m zZlUrUwW=N+!L!Dhx62^?9%o=RA-JG6*~)aBj!P`BqNPlGg=hNPvmTZ+rRFZ*Js(KX zC!EONUf(_ii!5RD;C@9+BdX&s;BTDuD zu#gd5=g#Tyg`KGY1(u~csmVnAjSo8RGuAAGU_f;|Sa}XWEr^|-$KAaq>1D3;-FHPUyuvL>>|IcTrMcel=CPnrgE2r!We`Unt zSG1CUNvx_Tgz8%+vy7y*s#AKK9W-o&47%@Fv}CCgF$;@dP($z?`%u2@Vwr~hlZ6qn zVx1}VAU-oK-`Ik`6E-}|6c0VUB6=TaF*P3;@Y?YgkAcKRUK2z7gS437UZD4ma|un84p~2ksMOOk4?f z8AbRto2DWXU8AmeM0C!cQyz#UwKyNgL^U7{MCStopW6aGSyZ%QfBjERZ%%6?@l5B{ zDN-C?z}a*vDeA|$j25qUA7LHTuN%5T&*mns5aTbEAl10&d$+^tm*7lgo}I2o(#&Zc zi-)6g%c@^q{QZ{3z(*w$MTcnx!d?Y^Izncd)4^eMx5HRobN=MV(eV1gXC3xBwUM!M zs7Xa%=V+klk-jVNO<+vu;~PE`>S9kNroG$;o%XBvijqfbafpRbPnv8F@!-M8sn%^4 zy9V#8Heb0&KYWj!&Ek*KNHWbLdrBM7L>pkn_}-5qRrVj1n_4;OdQA5poe8;rpAXc9 zY3*zivV)`)EAqkDYnLRqQs$?Hq9Du!?N+i&rPa=)qaTgKU#jfT5e|%UGrZ9s(ivd< z`*`DXlPqF%_>M^H(EzDKLAz`7CKoR?QUp>SVNS|17LRMuvR-H%gq|ibTIY}MwvBSi zX^r@+8a{U(>zAvv8f@|Qe(8SvaBq`{CVlYx>ve|&P4?~!d{)I^Yh!d;fcNT5gSmUQ zUBt0|jz@#j6z5HSpe#X)QRkw6$pdZaxEo389#enwn$^cq-RC^X9(sR*h(- zJdG4E?s>J0AKZt6$=dp5>L*P7F#7SOW^35{Rw$A4(7I;`lKIgIW^YAMKeFKH;GM~R zB*Uv(L~!(mt2RUPS#2R@n?y~HmcPAK=ck$YR3kQl+>1!zKG_LTR`xm_&X<(r54g8( z+(;eK<>L`z4QeyXYCBcDKc_=aLOGMSb*xK!a$f^|g34-KZMTGCQ@7ZI7O{PL3#xy1 z{#AJHi8qUjJn+$+!4ZFw>mT!HzwSoJMI97eJ4G&~`76ki5MaVllC!kr?4FAwY4ZUU zZkan2Hy+>Rkfdr%b6tP4rrCIRIEqC}u;s`l&IT2nAn5-WZ`6nZrU=i+?->m@vaI zFDGp%#B(~rl0S$M81Kg`T8s#IW$(wW`|s zK;xd+jxfTn1!aLb@8rDDhwI4-Ix?BaNhoC%^ep~HP9j`-@h5abzU%1oD89pj_XM&8 z#s?42jNc(f-_$U71f2^p59N@-UdVM#)3j`P&;EPrezjKHWo2ak5%itY<@1!~{bg_G z`=9=1;4ee&ZPzkiEl)Z|*@CZKJ?y`Ws-Bb8tg^YfS)AJQ?Z?=x#nV22FZZd%fPgKf zQO7?A6gE?+ZE~IIa#{D1TkE~~W9Zz=6CZy??0DTec$;$@;!+aHtkm6)p!gWy=KQNM zw=8F^XMUJslPIf}jr0nALX^0W$w`w}Z}Wm3_5@?nCwfyUM72~M5R#A5}8jhxSAIaeCW?WCi2Sr0PAhT$frPGKIf z9Ju=S`_(s(_p*n4wP9qx$2m#Hw|mE?Z|LVq+0jc4y4N#2K1&u}&-ijXIVCew_vNJB z`;*wo`N)|THi8Pz-bojI>P_0qVx+g}tLtXN)N$iqQLfjIWUA1QbtWj>WP=gQC2Y== zEf!rY8t?O3HT``_3W{_pB!OIodV^?cvF5p*J%@YtuNu}yx+%Z)YfA7RO<~tC_R#)p zZ{cTf^~ejxP5JIIoVImM%RjX5+|VS;)D<&du6K)=`s=yWzbLB4M738w-r(csluI9c zsMogiy~^sAZ`vL`$`b1hB^vczqZ1Tmmj=#XiO~{D&(=D>#nvq1gCtomD{b>xX4((- z#(x@0xN^Hp)iZd`UlY54zLvd-&k-H1P-5edd-xt)iv= zsOOt#DPx3_XkSc7nXeXTsW3mu7P{PDCvyDo7&-=9bQc(;q%Pl z%k<3!J(&;vqxfYp$kw;9zHmQT_qsq0gGjo-IbH>)h)TZ7ScgMhtXg+9I!O!aIr=D5SB%Yd#d6887v}O!~Dt?~x(C#qIIFyq2_;(fR5FQ?n#-^Ih zlK)&MAGPtCQQWq~-0T$Q<5=@@@KgC)va1OZZq0L5iA6o_5Aw$zw|<#Xbj#@UT`0Dl z)HiBHUnxc^f;>FRb3mw~PPmEVqpZa+SAjtrclNH{c3!Gst&z~gt>r4>iL{Z+=MwUN zzI`ul=<^~HOH&H>5$fuMCe(X-7tOMc>B$X)G-+b*uUWR zKWR5Cs2Lfwt=mhaFZ=NJ$6ooRrJx6tPK#OkV6t9}j|KDJb7|dlZ9@Kr zZ}za1ys*f(pNf%NwUSPJ7FZMTyGZ}4L}%K**R1wUyptE}SI_3pLxGCMa)&Oc+iFDg znqp!A^*E~o4K!K<{=b}*ikrYL9S+?Ma55XC7y*e1@3S#UX? zEf=>sdr;u(SBTgA-aZFA?B*94~TNMDxPt^!@UUCZ(0vAXp_rsKwDpYoK0-XG;-ttgk<7w~rS zfuoaa>vxx3o4vZFT_UDt{SJ_knqANaBxhN)+h)5z*tb#l=9Hklww!Ep>c?v`V}e0X zB5hW93#e@`&uo)UIOQ)mdE}cv^Q9UJD$n9lXUQkGl3mXFKcP_>n@#hry+*eXDf2zLTuqtPHqh0y zi1LfU>}y>*jo0R$bNV7@e2fjpQpaCzy;<1ZICH-J8mUwB(E)Ag-)S!{l}jWlZ_C`m z(O5d=obGm*x35iDJ8|sVc&brEaXe%Dq}<{yCbB_88NsQWGZP-RCpZ|tYBj2fy;>`* ziE@-#OqG~Rv7+o9F71zeKB(^8A^{{`pp~4vtC(a(?MVk`%YNSIPPxp>$k!AaQ>{dbAZ_iWcibG1qql|EA`_4}temG`r29S4QIx#biuhVtg3^4@Ai?;w(hyUjDy^sEces zm@``9r+t>_;)j02a7(@;`u54bv=?OkAJ_XGwPrPw?&aL87!nXm6sDouIR!Z~XDI6K zWAu-7(p5Q=4E2qkH|X>k)os(yl+w4KkMo6M?Y1X_N5GCbH6Ez_@wF+9e1Gv4>bv^( ztt-0fd2|Mz4V;mm264gp-;Cql{c`XL`DvBTOH?0EXw?nvze_T0VEgvd-sEVRiE6H~ zT3LBtto3gV^X2%dFJ7##+ILruvZj_bdTDjBCww&MYbR5x@8<|pKgURFXL=r)ezhoR z+$;Y44z~(<(oU+jRFabj&B|rvCEbN@lM6vqUD=wU&M)Pne^xZiX^i}MQ#qMhH5d4T z;n1FNjNhHp-tm@f_f%fF?*0zmBPmk{r_5!aIP*C_E!Vdd@YlteT)F-}z@xQqr}9=5i7 zPe`|qDIS)-In?zbDmA&6sgzN>P0X|Um~DYUk&}w}tbjFTqyk^r0Qe#C4b-@wA@y_a znRGq8lWDq!JhQJMuRG1~(v-Mn6SIcG!JV0g`j|9}DdeLiW-6cR{rWWb@3_clh$OX? zV@i)*k^$aqlce{&TI_5boFo+`ko|%&Dy~P9D z8=y~!Mt@YjPSH$CHM%N5yPx);=-c+^WVCfdulKUwr=gb<*GOyL%W1iyqVtw2*DL8t zyMqeTD@ohrmLvA9DpxwMysY#!yN6_wT(-px`TZ8wbG4CST-%mQ^sw1 z%17GIL0Qc0f0lukru2O1X^H(AVV3lfEsO@_JEt~EE7v|JA5!{zh1sTvzwmviM3JuV zM4+>LNv=alv@&nnh}-vZ-cMqRdze<4lHMEmdCB dtDTH$?EuQ1|+asLMOO)Oud} zG455Yc{EOK=oVQ&=G@pr{!Z_LNSgh)SM07SC!QY8^e0g_miHum%y=@gKxP@1mss1C zp2B&_d&`;Y#*uG}G|fsIJ$_$2c{uurc2yvw%ejP!aN`d@o;i)Cx{f?c?YcIeyp_qN zbv%Jo5_ayT=l9};WU}UzFLjZ=q0Ki|PHFZzI$hN5LOWd91&e13e-fOYG$3{3#18%_s> zG-z*dizM??-3$98LYtp1oCLL*ChEoeF?@!W94RMj(~|dgDZN&~hkt+GsLxxVx}Ub7 zJOw3IxK{3iwhOVzSvI zl1?jx)BlJ!pAbKlE7=dGNO$wR*lZ2N?;v zJPsot4kce$tm>-`q?Rk$mljH)pd?t=oEhLDdtQ0@5$ofz52ou(4wma2n%e83cGND0 zUw@p-85h)Pb+oTIGti_*WwGPE@A}#CkUqCsg_Z$Q!oYlwCi$Ws8H*b^WoY+CtwOcq z!cua;yj#MQUrtSvBPH3hjJ7L>mzWYQo&RhO)e=l(y}HgMbEL#f zPIFkpM{RkzR>Pe~=#vY#hS*xMBj-n63kB}B^NU6+yI1p)1-YdQFb+-#E(z=@dRqI6 ziyR#mb)Ejo%nB8Br_LQOQ$kr6MSOxr1Ytv0pzaDS+d#A5Hb%1-{p0eYJ8rKIobFK{>(Hy(q@>uB6@O{s7cl{nRq0B#$5Eq zoG$n?pCikiw;`=N>VkREDOb|bPn2Ej6`G%7*V$~JaJ($t2;_UM>*j3kuVJ1La9g)> zy7v0PKI)pon^@P3b*BwF*7s@a^hJxchy0k|Q~7D-^IQgbhaSsdg4GknqP#URic;N$ zwLOidoONEb{r#$bj)~(O-V)PuUYF}e9=AjqM?H2f?~N(wZV)bOSRc<<4~@`VX1_G3 z8F@in=&fRU!eK`ER5-6#J6E89u5T<;6>M*(EmfKj`p<_XT$cP>he#c{}wi{ZKCn>Ag3&# z`cTESxV|y;zDAezW*qsZ6Qp08_rCQU9iLLKw7jjt#J95TORK^1MSs3ZP^mF)hrtJ^ zx}kl7gb4~ioyZd&q*>j-{QIGDr;UOlQNI9Wy}4Nc{htX4qk$gYd|-S3oCn(AO?J{v z>Eo8Kc9T?mwX*MMrTFRat8241*#+AK3mipdla^_aCPaAf`ZI<{Qq$+suzLCKJ(KotJjy-MQ9!E08m|-YSP|h+@sM ztBR-YpqQ0o7degHhj(P`^hx$NU|?bH#g!B$^)A%T(e14Ad@@BvN~K>|+UBmw*|*V3 z+CKAd3^yWuKQxbAk3i#t?_1E=-}1)EH-;xOsh|AyR zkj3gsbU9YIwXXPV>L0aC3@YVyH@?2~#%m>c>n?R^`xWE!6W2DBoH-X#$2n7zb(Km9NcR9!iGNFo3}$#FHLpd? z`9zGsdjf1AO9krJM zU0l9N2ddA$c>0Ypsa5&X-fD;T>ZAyt>#ruYIn`aBoD`2nvkyr$#?{ob3mKoW^natP zIrPiP{gS15{7H#TUy~;*s192KxVjw?HKb@2Xp&V zlwYam$p!*^f?uzFxklc&OvN0==xfH|_nL;G)-NA(GRc>Dh>_&gE=aQXdexcJFP&$qc@qUfLRcY)pdz3bv|IVVA2zBUBD;y0y%ta;0eQ z+i}_XgM2fVetSg3tf%Hzc+VIurK+?WBz>+e4^46Q4?7dd8*JO9IsfA_S$5;tu2OCN zwZZ@z=TP);a$GFJyy_@B44Mxb-c+$}6S;vZ1nWBcYaWrzmt!)r>O%5ihk48A#RDBj zn!CUGrg$)Fbo>gm=yhwEQ`Gu7qADe?7-ZgL8^SH*)Vy14Msa+?DZ44sPGdF%ULISa z4aR0f^Wm`KrxX_1DZ7qTjK_z;z!tp}kgo^wlJ z`4UG>+}Htj-i3EBSKr8eFyDX5(>NSLgCxUD*yAaFUDMF&r>eYIq>=?U_NGdQ0>U2x zW9(fP2CPlwU)ioD*?(6%<1m$XFIVr&<=~a`xuUcy`¬2G;DUte%o`d;CQsTCVcZ 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 R&Q*K&_>mJ|R~!zy_B%n$#5@21 diff --git a/examples/test_LUDOX_markdown.md b/examples/test_LUDOX_markdown.md deleted file mode 100644 index 84f6ea23..00000000 --- a/examples/test_LUDOX_markdown.md +++ /dev/null @@ -1,102 +0,0 @@ -# Experiment 3 - Cell measurement protocol Challenge - -This year we plan to test protocols that will eventually be automated. For this reason, we will use 96-well plates instead of test tubes for culturing. Consequently, we want to evaluate how the performance of our plate culturing protocol compares to culturing in test tubes (e.g. 10 mL falcon tube) on a global scale. This version of the interlab protocol involves 2 hr. time interval measurements and incubation inside a microplate reader/incubator. - -At the end of the experiment, you will have four plates to be measured. You will measure both fluorescence and absorbance in each plate. - -Before performing the cell measurements, you need to perform all the calibration measurements. Please do not proceed unless you have completed the calibration protocol. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Engineering Committee (engineering [at] igem [dot] org) to discuss your situation. - -For all below indicated cell measurements, you must use the same type of plates and the same volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same type of plates, volumes, and settings, the measurements will not be valid. - -Protocol summary: UPDATE You will transform the eight devices listed in Table 1 into E. coli K-12 DH5-alpha cells. The next day you will pick two colonies from each transformation (16 total) and use them to inoculate 5 mL overnight cultures (this step is still in tubes). Each of these 16 overnight cultures will be used to inoculate four wells in a 96-well plate (200 microliter each, 4 replicates) and one test tube (12 mL). You will measure how fluorescence and optical density develops over 6 hours by taking measurements at time point 0 hour and at time point 6 hours. Follow the protocol below and the visual instructions in Figure 1 and Figure 2. - - -## Protocol Outputs: -* `baseline absorbance of culture (day 2) measurements of cultures (0 hr timepoint)` -* `0 hr absorbance timepoint measurements of plate 1` -* `0 hr fluorescence timepoint measurements of plate 1` -* `absorbance timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour` -* `fluorescence timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour` -* `absorbance timepoint measurements of Plates 2, 3, and 4` -* `fluorescence timepoint measurements of Plates 2, 3, and 4` - - -## Protocol Materials: -* [_E. coli_ DH5 alpha competent cells](https://identifiers.org/taxonomy:668369) -* [Negative control](http://parts.igem.org/Part:BBa_J428100) -* [Positive control (I20270)](http://parts.igem.org/Part:BBa_I20270) -* [Test Device 1 (J364000)](http://parts.igem.org/Part:BBa_J364000) -* [Test Device 2 (J364001)](http://parts.igem.org/Part:BBa_J364001) -* [Test Device 3 (J364002)](http://parts.igem.org/Part:BBa_J364002) -* [Test Device 4 (J364007)](http://parts.igem.org/Part:BBa_J364007) -* [Test Device 5 (J364008)](http://parts.igem.org/Part:BBa_J364008) -* [Test Device 6 (J364009)](http://parts.igem.org/Part:BBa_J364009) -* [LB Broth + Chloramphenicol (34 ug/mL)]() -* [LB Agar + Chloramphenicol (34 ug/mL)]() -* [Chloramphenicol stock solution (34 mg/mL)](https://pubchem.ncbi.nlm.nih.gov/compound/5959) -* [Ice]() -* [Plate reader]() -* [Shaking incubator]() -* Petri dish (x 8) -* culture tube (x 32) -* 1.5 mL microfuge tube (x 16) -* 50 ml conical tube (x 64) -* 96 well microplate (x 2) -* microplate adhesive sealing film - - -## Protocol Steps: -1. Obtain 8 x Petri dish containing LB Agar + Chloramphenicol (34 ug/mL) growth medium for culturing `transformant strains` -2. Transform `Negative control` DNA into `_E. coli_ DH5 alpha competent cells`. Repeat for the remaining transformant DNA: `Positive control (I20270)`, `Test Device 1 (J364000)`, `Test Device 2 (J364001)`, `Test Device 3 (J364002)`, `Test Device 4 (J364007)`, `Test Device 5 (J364008)`, and `Test Device 6 (J364009)`. Plate transformants on LB Agar + Chloramphenicol (34 ug/mL) `transformant strains` plates. Incubate overnight (for 16 hour) at 37.0 degree Celsius. -3. Obtain 16 x culture tubes to contain `culture (day 1)` -4. Pick 2 colonies from each `transformant strains` plate. -5. Inoculate 2 colonies of each transformant strains, for a total of 16 cultures. Inoculate each into 5.0 milliliter of LB Broth + Chloramphenicol (34 ug/mL) in culture (day 1) and grow overnight (for 16.0 hour) at 37.0 degree Celsius and 220 rpm. -6. Obtain 16 x culture tubes to contain `culture (day 2)` -7. Dilute each of 16 `culture (day 1)` samples with LB Broth + Chloramphenicol (34 ug/mL) into the culture tube at a 1:10 ratio and final volume of 5.0 milliliter. Maintain at 4.0 degree Celsius while performing dilutions. (This can be also performed on ice). -8. Obtain 16 x 1.5 mL microfuge tubes to contain `cultures (0 hr timepoint)` -9. Hold `cultures (0 hr timepoint)` on ice. This will prevent cell growth while transferring samples. -10. Transfer 1.0 milliliter of each of 16 `culture (day 2)` samples to 1.5 mL microfuge tube containers to contain a total of 16 `cultures (0 hr timepoint)` samples. Maintain at 4.0 degree Celsius during transfer. (This can be also performed on Ice). -11. Measure baseline absorbance of culture (day 2) of `cultures (0 hr timepoint)` at 600.0 nanometer. -12. Obtain 16 x 50 ml conical tubes to contain `back-diluted culture` The conical tube should be opaque, amber-colored, or covered with foil. -13. Back-dilute each of 16 `culture (day 2)` samples to a target OD of 0.02 using LB Broth + Chloramphenicol (34 ug/mL) as diluent to a final volume of 40.0 milliliter. Maintain at 4.0 degree Celsius while performing dilutions. - -![](fig1_challenge_protocol.png) -

Fig 1: Visual representation of protocol

- -14. Obtain 16 x 50 ml conical tubes to contain `Tubes 1, 2 and 3` The conical tubes should be opaque, amber-colored, or covered with foil. -15. Obtain 16 x 50 ml conical tubes to contain `Tube 2` The conical tubes should be opaque, amber-colored, or covered with foil. -16. Obtain 16 x 50 ml conical tubes to contain `Tube 3` The conical tubes should be opaque, amber-colored, or covered with foil. -17. Transfer 12.0 milliliter of each of 16 `back-diluted culture` samples to 50 ml conical tube containers to contain a total of 16 `Tubes 1, 2 and 3` samples. Maintain at 4.0 degree Celsius during transfer. -18. Transfer 12.0 milliliter of each of 16 `back-diluted culture` samples to 50 ml conical tube containers to contain a total of 16 `Tube 2` samples. Maintain at 4.0 degree Celsius during transfer. -19. Transfer 12.0 milliliter of each of 16 `back-diluted culture` samples to 50 ml conical tube containers to contain a total of 16 `Tube 3` samples. Maintain at 4.0 degree Celsius during transfer. -20. Obtain a 96 well microplate to contain `plate 1` -21. Hold `plate 1` on ice. -22. Transfer 200.0 microliter of each `back-diluted culture` sample to 96 well microplate `plate 1` in the wells indicated in the plate layout. - Maintain at 4.0 degree Celsius during transfer. -23. Transfer 200.0 microliter of `LB Broth + Chloramphenicol (34 ug/mL)` sample to wells A1:H1, A10:H10, A12:H12 of 96 well microplate `plate 1`. Maintain at 4.0 degree Celsius during transfer. These samples are blanks. - -![](fig2_cell_calibration.png) -

Fig 2: Plate layout

- -24. Measure 0 hr absorbance timepoint of `plate 1` at 600.0 nanometer. -25. Measure 0 hr fluorescence timepoint of `plate 1` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass. -26. Cover `plate 1` samples in 96 well microplate with your choice of material to prevent evaporation. -27. Incubate all `plate 1` samples for 6.0 hour at 37.0 degree Celsius at 220 rpm. -28. Measure absorbance timepoint of `plate 1` at 600.0 nanometer at timepoints 2.0 hour, 4.0 hour, 6.0 hour. -29. Measure fluorescence timepoint of `plate 1` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass at timepoints 2.0 hour, 4.0 hour, 6.0 hour. -30. Incubate all `Tubes 1, 2 and 3` samples for 2.0 hour at 37.0 degree Celsius at 220 rpm. -31. Hold all `Tubes 1, 2 and 3` samples on ice. Reserve until the end of the experiment for absorbance and fluorescence measurements. -32. Incubate all `Tube 2` samples for 4.0 hour at 37.0 degree Celsius at 220 rpm. -33. Hold all `Tube 2` samples on ice. Reserve until the end of the experiment for absorbance and fluorescence measurements. -34. Incubate all `Tube 3` samples for 6.0 hour at 37.0 degree Celsius at 220 rpm. -35. Hold all `Tube 3` samples on ice. Reserve until the end of the experiment for absorbance and fluorescence measurements. -36. Obtain a 96 well microplate to contain `Plates 2, 3, and 4` -37. Transfer 200.0 microliter of each `Tubes 1, 2 and 3` sample to 96 well microplate `Plates 2, 3, and 4` in the wells indicated in the plate layout. - Maintain at 4.0 degree Celsius during transfer. -38. Transfer 200.0 microliter of `LB Broth + Chloramphenicol (34 ug/mL)` sample to wells A1:H1, A10:H10, A12:H12 of 96 well microplate `Plates 2, 3, and 4`. Maintain at 4.0 degree Celsius during transfer. These samples are blanks. -39. Measure absorbance timepoint of `Plates 2, 3, and 4` at 600.0 nanometer. -40. Measure fluorescence timepoint of `Plates 2, 3, and 4` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass. -41. Import data for `baseline absorbance of culture (day 2) measurements of cultures (0 hr timepoint)`, `0 hr absorbance timepoint measurements of plate 1`, `0 hr fluorescence timepoint measurements of plate 1`, `absorbance timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour`, `fluorescence timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour`, `absorbance timepoint measurements of Plates 2, 3, and 4`, `fluorescence timepoint measurements of Plates 2, 3, and 4` into provided Excel file. ---- -Timestamp: 2022-07-08 19:34:25.986146--- -Protocol version: 1.2b \ No newline at end of file From d4327628d361a550f45a241e81eff7056f1ec96f Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:40:57 -0500 Subject: [PATCH 02/12] add mkdocs and doctests --- .gitignore | 12 +++++++ doc/generate_specification_content.py | 7 ++-- docs/explanation.md | 1 + docs/how-to-guides.md | 1 + docs/index.md | 3 ++ docs/reference/labop/data.md | 3 ++ docs/reference/labop/execution.md | 6 ++++ docs/reference/labop/samples.md | 6 ++++ docs/reference/labop/top.md | 7 ++++ docs/reference/library.md | 11 ++++++ docs/reference/uml/activities.md | 21 +++++++++++ docs/reference/uml/behaviors.md | 5 +++ docs/reference/uml/literals.md | 10 ++++++ docs/reference/uml/time.md | 8 +++++ docs/reference/uml/top.md | 7 ++++ docs/tutorials.md | 1 + labop/__init__.py | 2 +- labop/activity_edge_flow.py | 4 +-- labop/activity_node_execution.py | 19 +++------- labop/behavior_execution.py | 5 +-- labop/call_behavior_execution.py | 3 +- labop/container_spec.py | 2 +- labop/data.py | 2 +- labop/dataset.py | 3 +- labop/execution_context.py | 3 +- labop/execution_engine.py | 10 +++--- labop/lab_interface.py | 7 ++-- labop/library.py | 2 -- labop/material.py | 2 +- labop/parameter_value.py | 3 +- labop/primitive.py | 2 +- labop/primitive_array.py | 2 +- labop/protocol.py | 5 ++- labop/protocol_execution.py | 14 +++----- labop/sample_array.py | 3 +- labop/sample_collection.py | 10 +++++- labop/sample_data.py | 6 ++-- labop/sample_map.py | 4 +-- labop/sample_mask.py | 20 ++++++++--- labop/sample_metadata.py | 9 ++--- labop/sbol_factory.py | 2 +- mkdocs.yml | 43 ++++++++++++++++++++++ uml/literal_boolean.py | 28 ++++++++++++++- uml/literal_specification.py | 52 ++++++++++++++++++++++++++- 44 files changed, 296 insertions(+), 80 deletions(-) create mode 100644 docs/explanation.md create mode 100644 docs/how-to-guides.md create mode 100644 docs/index.md create mode 100644 docs/reference/labop/data.md create mode 100644 docs/reference/labop/execution.md create mode 100644 docs/reference/labop/samples.md create mode 100644 docs/reference/labop/top.md create mode 100644 docs/reference/library.md create mode 100644 docs/reference/uml/activities.md create mode 100644 docs/reference/uml/behaviors.md create mode 100644 docs/reference/uml/literals.md create mode 100644 docs/reference/uml/time.md create mode 100644 docs/reference/uml/top.md create mode 100644 docs/tutorials.md create mode 100644 mkdocs.yml diff --git a/.gitignore b/.gitignore index c26221f6..065e5d1b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,15 @@ out cov.xml *.org **/sample_graph_** +site/404.html +site/index.html +site/objects.inv +site/sitemap.xml +site/sitemap.xml.gz +site/explanation/index.html +site/how-to-guides/index.html +site/pandoc/combined.pdf +site/pandoc/combined.pdf.md +site/reference/index.html +site/search/search_index.json +site/tutorials/index.html diff --git a/doc/generate_specification_content.py b/doc/generate_specification_content.py index 22be6e3a..779c0ddf 100644 --- a/doc/generate_specification_content.py +++ b/doc/generate_specification_content.py @@ -12,11 +12,11 @@ dirname = os.path.dirname(__file__) # UML Spec -UML_TTL = os.path.join(dirname, "../uml/uml.ttl") +UML_TTL = os.path.join(dirname, "../uml/inner/uml.ttl") UML_NAMESPACE = "http://bioprotocols.org/uml#" # LabOP Spec -LabOP_TTL = os.path.join(dirname, "../labop/labop.ttl") +LabOP_TTL = os.path.join(dirname, "../labop/inner/labop.ttl") LabOP_NAMESPACE = "http://bioprotocols.org/labop#" # Output location @@ -37,7 +37,8 @@ def generate_spec(spec_file, spec_name, spec_namespace): if not os.path.exists(SPEC_OUT): os.mkdir(SPEC_OUT) copy( - f"{spec_name}DataModel.tex", os.path.join(SPEC_OUT, f"{spec_name}DataModel.tex") + f"{spec_name}DataModel.tex", + os.path.join(SPEC_OUT, f"{spec_name}DataModel.tex"), ) os.remove(f"{spec_name}DataModel.tex") Path(os.path.join(SPEC_OUT, f"{spec_name}_classes/")).mkdir( diff --git a/docs/explanation.md b/docs/explanation.md new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/docs/explanation.md @@ -0,0 +1 @@ + diff --git a/docs/how-to-guides.md b/docs/how-to-guides.md new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/docs/how-to-guides.md @@ -0,0 +1 @@ + diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..b66247f9 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,3 @@ +# Laboratory Open Protocol Python Library Documentation + + diff --git a/docs/reference/labop/data.md b/docs/reference/labop/data.md new file mode 100644 index 00000000..e5c154b2 --- /dev/null +++ b/docs/reference/labop/data.md @@ -0,0 +1,3 @@ +::: labop.sample_data +::: labop.sample_metadata +::: labop.dataset \ No newline at end of file diff --git a/docs/reference/labop/execution.md b/docs/reference/labop/execution.md new file mode 100644 index 00000000..d5398ea0 --- /dev/null +++ b/docs/reference/labop/execution.md @@ -0,0 +1,6 @@ +::: labop.protocol_execution +::: labop.activity_edge_flow +::: labop.activity_node_execution +::: labop.behavior_execution +::: labop.call_behavior_execution + diff --git a/docs/reference/labop/samples.md b/docs/reference/labop/samples.md new file mode 100644 index 00000000..6c17641e --- /dev/null +++ b/docs/reference/labop/samples.md @@ -0,0 +1,6 @@ +::: labop.sample_collection +::: labop.sample_array +::: labop.sample_mask +::: labop.sample_map +::: labop.many_to_one_sample_map +::: labop.one_to_many_sample_map diff --git a/docs/reference/labop/top.md b/docs/reference/labop/top.md new file mode 100644 index 00000000..c9eb4397 --- /dev/null +++ b/docs/reference/labop/top.md @@ -0,0 +1,7 @@ +::: labop.protocol +::: labop.primitive +::: labop.parameter_value +::: labop.primitive_array +::: labop.material +::: labop.container_spec + diff --git a/docs/reference/library.md b/docs/reference/library.md new file mode 100644 index 00000000..90f97193 --- /dev/null +++ b/docs/reference/library.md @@ -0,0 +1,11 @@ +::: labop.sbol_factory +::: labop.strings +::: labop.type_inference +::: labop.data +::: labop.lab_interface +::: labop.library +::: labop.execution_engine +::: labop.execution_engine_utils +::: labop.execution_context +::: uml.uml_graphviz +::: uml.utils \ No newline at end of file diff --git a/docs/reference/uml/activities.md b/docs/reference/uml/activities.md new file mode 100644 index 00000000..fc507ba7 --- /dev/null +++ b/docs/reference/uml/activities.md @@ -0,0 +1,21 @@ +::: uml.action +::: uml.activity +::: uml.activity_edge +::: uml.activity_node +::: uml.activity_parameter_node +::: uml.behavior +::: uml.call_action +::: uml.call_behavior_action +::: uml.control_flow +::: uml.control_node +::: uml.decision_node +::: uml.join_node +::: uml.merge_node +::: uml.object_flow +::: uml.object_node +::: uml.final_node +::: uml.flow_final_node +::: uml.fork_node +::: uml.initial_node +::: uml.executable_node +::: uml.invocation_action \ No newline at end of file diff --git a/docs/reference/uml/behaviors.md b/docs/reference/uml/behaviors.md new file mode 100644 index 00000000..f643f80a --- /dev/null +++ b/docs/reference/uml/behaviors.md @@ -0,0 +1,5 @@ +::: uml.value_pin +::: uml.output_pin +::: uml.parameter +::: uml.pin +::: uml.input_pin \ No newline at end of file diff --git a/docs/reference/uml/literals.md b/docs/reference/uml/literals.md new file mode 100644 index 00000000..eae310d4 --- /dev/null +++ b/docs/reference/uml/literals.md @@ -0,0 +1,10 @@ +::: uml.value_specification +::: uml.literal_boolean +::: uml.literal_identified +::: uml.literal_integer +::: uml.literal_null +::: uml.literal_real +::: uml.literal_reference +::: uml.literal_specification +::: uml.literal_string + diff --git a/docs/reference/uml/time.md b/docs/reference/uml/time.md new file mode 100644 index 00000000..e90dffe9 --- /dev/null +++ b/docs/reference/uml/time.md @@ -0,0 +1,8 @@ +::: uml.duration +::: uml.duration_constraint +::: uml.duration_interval +::: uml.duration_observation +::: uml.time_constraint +::: uml.time_expression +::: uml.time_interval +::: uml.time_observation diff --git a/docs/reference/uml/top.md b/docs/reference/uml/top.md new file mode 100644 index 00000000..bb13a79f --- /dev/null +++ b/docs/reference/uml/top.md @@ -0,0 +1,7 @@ +::: uml.ordered_property_value +::: uml.expression +::: uml.constraint +::: uml.strings +::: uml.interval +::: uml.interval_constraint +::: uml.observation \ No newline at end of file diff --git a/docs/tutorials.md b/docs/tutorials.md new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/docs/tutorials.md @@ -0,0 +1 @@ + diff --git a/labop/__init__.py b/labop/__init__.py index 65ea2126..4c4f024b 100644 --- a/labop/__init__.py +++ b/labop/__init__.py @@ -1,7 +1,7 @@ import sbol3 from typing import List from uml import assign_outer_class_builders -import labop.inner as inner +from . import inner from .utils import * diff --git a/labop/activity_edge_flow.py b/labop/activity_edge_flow.py index f1b93da5..1c410127 100644 --- a/labop/activity_edge_flow.py +++ b/labop/activity_edge_flow.py @@ -6,10 +6,10 @@ import graphviz import sbol3 -from labop import inner -from labop.activity_node_execution import ActivityNodeExecution from uml import CallBehaviorAction, InputPin, LiteralReference, Parameter +from . import inner +from .activity_node_execution import ActivityNodeExecution from .protocol import Protocol diff --git a/labop/activity_node_execution.py b/labop/activity_node_execution.py index 3365e82c..9747ca50 100644 --- a/labop/activity_node_execution.py +++ b/labop/activity_node_execution.py @@ -4,29 +4,18 @@ from typing import Callable, List -import sbol3 - -from labop import inner -from labop.behavior_execution import BehaviorExecution from uml import ( - PARAMETER_OUT, - ActivityEdge, ActivityNode, - ActivityParameterNode, CallBehaviorAction, - ControlFlow, ForkNode, - InitialNode, InputPin, - LiteralSpecification, - ObjectFlow, - OutputPin, Parameter, - flow_final_node, labop_hash, - literal, ) +from . import inner +from .call_behavior_execution import CallBehaviorExecution + class ActivityNodeExecution(inner.ActivityNodeExecution): def __init__(self, *args, **kwargs): @@ -111,7 +100,7 @@ def get_calling_behavior_execution( for n in reversed(incoming_initial_flows) if isinstance( n.lookup().token_source.lookup(), - labop.CallBehaviorExecution, + CallBehaviorExecution, ) ) except StopIteration: diff --git a/labop/behavior_execution.py b/labop/behavior_execution.py index aad5c763..c099a739 100644 --- a/labop/behavior_execution.py +++ b/labop/behavior_execution.py @@ -4,12 +4,9 @@ from typing import Dict, List, Union -import sbol3 - -import labop.inner as inner from uml import Activity, LiteralSpecification -from . import ParameterValue +from . import ParameterValue, inner class BehaviorExecution(inner.BehaviorExecution, Activity): diff --git a/labop/call_behavior_execution.py b/labop/call_behavior_execution.py index e896cc53..5c670b25 100644 --- a/labop/call_behavior_execution.py +++ b/labop/call_behavior_execution.py @@ -4,12 +4,10 @@ from typing import Callable, List, Union -from labop import inner from uml import ( PARAMETER_IN, PARAMETER_OUT, Action, - ActivityParameterNode, Behavior, CallBehaviorAction, ObjectFlow, @@ -20,6 +18,7 @@ from uml.ordered_property_value import OrderedPropertyValue from uml.output_pin import OutputPin +from . import inner from .activity_edge_flow import ActivityEdgeFlow from .activity_node_execution import ActivityNodeExecution from .behavior_execution import BehaviorExecution diff --git a/labop/container_spec.py b/labop/container_spec.py index 0a934811..45a84324 100644 --- a/labop/container_spec.py +++ b/labop/container_spec.py @@ -2,7 +2,7 @@ The ContainerSpec class defines the functions corresponding to the dynamically generated labop class ContainerSpec """ -import labop.inner as inner +from . import inner class ContainerSpec(inner.ContainerSpec): diff --git a/labop/data.py b/labop/data.py index c6a38d60..df6c9427 100644 --- a/labop/data.py +++ b/labop/data.py @@ -12,7 +12,7 @@ import sbol3 import xarray as xr -from labop.strings import Strings +from .strings import Strings l = logging.getLogger(__file__) l.setLevel(logging.ERROR) diff --git a/labop/dataset.py b/labop/dataset.py index 37eba80a..2606bcd0 100644 --- a/labop/dataset.py +++ b/labop/dataset.py @@ -8,8 +8,7 @@ import pandas as pd import xarray as xr -import labop.inner as inner - +from . import inner from .data import sort_samples from .strings import Strings diff --git a/labop/execution_context.py b/labop/execution_context.py index 601c286d..fc84cca8 100644 --- a/labop/execution_context.py +++ b/labop/execution_context.py @@ -2,8 +2,6 @@ import sbol3 -from labop import parameter_value -from labop.call_behavior_execution import CallBehaviorExecution from uml import ( Action, Activity, @@ -25,6 +23,7 @@ from uml.final_node import FinalNode from uml.initial_node import InitialNode +from .call_behavior_execution import CallBehaviorExecution from .parameter_value import ParameterValue diff --git a/labop/execution_engine.py b/labop/execution_engine.py index 16ea1169..d62dffd7 100644 --- a/labop/execution_engine.py +++ b/labop/execution_engine.py @@ -10,31 +10,28 @@ import sbol3 from numpy import record -from labop.behavior_execution import BehaviorExecution -from labop.execution_context import ExecutionContext -from labop.strings import Strings from labop_convert.behavior_dynamics import SampleProvenanceObserver from uml import ActivityNode, CallBehaviorAction from uml.activity import Activity from uml.activity_edge import ActivityEdge from uml.activity_parameter_node import ActivityParameterNode -from uml.control_flow import ControlFlow -from uml.input_pin import InputPin from uml.object_flow import ObjectFlow from uml.output_pin import OutputPin from uml.pin import Pin from uml.utils import WellFormednessIssue, WellformednessLevels, literal -from uml.value_pin import ValuePin from .activity_edge_flow import ActivityEdgeFlow from .activity_node_execution import ActivityNodeExecution +from .behavior_execution import BehaviorExecution from .call_behavior_execution import CallBehaviorExecution from .dataset import Dataset +from .execution_context import ExecutionContext from .parameter_value import ParameterValue from .primitive import Primitive from .protocol import Protocol from .protocol_execution import ProtocolExecution from .sample_data import SampleData +from .strings import Strings l: logging.Logger = logging.getLogger(__file__) l.setLevel(logging.ERROR) @@ -759,6 +756,7 @@ def write_data_templates( ): """ Write a data template as an xlsx file if the record.node produces sample data (i.e., it has an output of type Dataset with a data attribute of type SampleData) + Parameters ---------- node : ActivityNodeExecution diff --git a/labop/lab_interface.py b/labop/lab_interface.py index b8144a84..f8703df5 100644 --- a/labop/lab_interface.py +++ b/labop/lab_interface.py @@ -1,12 +1,13 @@ import json -from urllib.parse import quote, unquote +from urllib.parse import quote import xarray as xr from numpy import nan from labop import SampleCollection -from labop.data import serialize_sample_format -from labop.strings import Strings + +from .data import serialize_sample_format +from .strings import Strings class LabInterface: diff --git a/labop/library.py b/labop/library.py index 3367bc4c..f8c520ac 100644 --- a/labop/library.py +++ b/labop/library.py @@ -3,8 +3,6 @@ import sbol3 -from uml.utils import convert_to_outer_class - loaded_libraries = {} diff --git a/labop/material.py b/labop/material.py index 76f09bf8..403131ab 100644 --- a/labop/material.py +++ b/labop/material.py @@ -2,7 +2,7 @@ The Material class defines the functions corresponding to the dynamically generated labop class Material """ -import labop.inner as inner +from . import inner class Material(inner.Material): diff --git a/labop/parameter_value.py b/labop/parameter_value.py index 53468718..12acac9e 100644 --- a/labop/parameter_value.py +++ b/labop/parameter_value.py @@ -6,9 +6,10 @@ import sbol3 -import labop.inner as inner from uml import LiteralSpecification, labop_hash +from . import inner + class ParameterValue(inner.ParameterValue): def __init__(self, *args, **kwargs): diff --git a/labop/primitive.py b/labop/primitive.py index e42c83bd..04e8a673 100644 --- a/labop/primitive.py +++ b/labop/primitive.py @@ -8,9 +8,9 @@ import sbol3 -import labop.inner as inner from uml import PARAMETER_IN, PARAMETER_OUT, Behavior, inner_to_outer +from . import inner from .dataset import Dataset from .lab_interface import LabInterface from .library import loaded_libraries diff --git a/labop/primitive_array.py b/labop/primitive_array.py index 8c1998ea..7f1f9e9a 100644 --- a/labop/primitive_array.py +++ b/labop/primitive_array.py @@ -2,7 +2,7 @@ The PrimitiveArray class defines the functions corresponding to the dynamically generated labop class PrimitiveArray """ -import labop.inner as inner +from . import inner class PrimitiveArray(inner.PrimitiveArray): diff --git a/labop/protocol.py b/labop/protocol.py index 32fcf3f1..54ca865c 100644 --- a/labop/protocol.py +++ b/labop/protocol.py @@ -8,10 +8,8 @@ import sbol3 -import labop.inner as inner from uml import ( Activity, - ActivityEdge, ActivityNode, Behavior, ControlFlow, @@ -23,8 +21,9 @@ ObjectNode, ValueSpecification, ) -from uml.utils import WellFormednessError, WellFormednessIssue, WhereDefinedMixin +from uml.utils import WellFormednessError, WellFormednessIssue +from . import inner from .library import import_library from .primitive import Primitive from .utils.helpers import prepare_document diff --git a/labop/protocol_execution.py b/labop/protocol_execution.py index 831b1fea..e27d3a39 100644 --- a/labop/protocol_execution.py +++ b/labop/protocol_execution.py @@ -9,31 +9,27 @@ import graphviz import sbol3 -import labop.inner as inner -import uml -from labop.execution_engine_utils import ( - JSONProtocolExecutionExtractor, - ProtocolExecutionExtractor, -) from uml import ( PARAMETER_IN, PARAMETER_OUT, ActivityNode, ActivityParameterNode, - CallBehaviorAction, ControlFlow, ControlNode, DecisionNode, - FinalNode, InitialNode, InputPin, - LiteralReference, ObjectFlow, Pin, ) +from . import inner from .behavior_execution import BehaviorExecution from .call_behavior_execution import CallBehaviorExecution +from .execution_engine_utils import ( + JSONProtocolExecutionExtractor, + ProtocolExecutionExtractor, +) from .material import Material from .protocol import Protocol from .sample_data import SampleData diff --git a/labop/sample_array.py b/labop/sample_array.py index c51d10a3..a30ea0f9 100644 --- a/labop/sample_array.py +++ b/labop/sample_array.py @@ -8,8 +8,7 @@ import xarray as xr -import labop.inner as inner - +from . import inner from .container_spec import ContainerSpec from .data import deserialize_sample_format, serialize_sample_format from .sample_collection import SampleCollection diff --git a/labop/sample_collection.py b/labop/sample_collection.py index 98ce8a3e..d15f22f9 100644 --- a/labop/sample_collection.py +++ b/labop/sample_collection.py @@ -2,9 +2,17 @@ The SampleCollection class defines the functions corresponding to the dynamically generated labop class SampleCollection """ -import labop.inner as inner +from . import inner class SampleCollection(inner.SampleCollection): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + + +if __name__ == "__main__": + import doctest + + doctest.testmod( + # extraglobs={"my_literal_specification": LiteralSpecification()} + ) diff --git a/labop/sample_data.py b/labop/sample_data.py index d830955e..167ff7e4 100644 --- a/labop/sample_data.py +++ b/labop/sample_data.py @@ -9,9 +9,9 @@ import xarray as xr from numpy import nan -import labop.inner as inner -from labop.data import deserialize_sample_format, serialize_sample_format -from labop.strings import Strings +from . import inner +from .data import deserialize_sample_format, serialize_sample_format +from .strings import Strings class SampleData(inner.SampleData): diff --git a/labop/sample_map.py b/labop/sample_map.py index c3b41272..9ff31ab8 100644 --- a/labop/sample_map.py +++ b/labop/sample_map.py @@ -2,8 +2,8 @@ The SampleMap class defines the functions corresponding to the dynamically generated labop class SampleMap """ -import labop.inner as inner -from labop.data import deserialize_sample_format, serialize_sample_format +from . import inner +from .data import deserialize_sample_format, serialize_sample_format class SampleMap(inner.SampleMap): diff --git a/labop/sample_mask.py b/labop/sample_mask.py index 271bc83d..13243a3b 100644 --- a/labop/sample_mask.py +++ b/labop/sample_mask.py @@ -6,11 +6,13 @@ import xarray as xr -import labop.inner as inner -from labop.data import deserialize_sample_format, serialize_sample_format -from labop.sample_collection import SampleCollection -from labop.strings import Strings -from labop.utils import contiguous_coordinates +from . import inner + +# from .data import deserialize_sample_format, serialize_sample_format +from .sample_collection import SampleCollection + +# from .strings import Strings +# from .utils import contiguous_coordinates class SampleMask(inner.SampleMask, SampleCollection): @@ -100,3 +102,11 @@ def __str__(self): def get_container_type(self): return self.get_source().get_container_type() + + +if __name__ == "__main__": + import doctest + + doctest.testmod( + # extraglobs={"my_literal_specification": LiteralSpecification()} + ) diff --git a/labop/sample_metadata.py b/labop/sample_metadata.py index ba7d1b4f..93477d4f 100644 --- a/labop/sample_metadata.py +++ b/labop/sample_metadata.py @@ -11,12 +11,13 @@ import xarray as xr from openpyxl import load_workbook -import labop.inner as inner -from labop.data import deserialize_sample_format, serialize_sample_format -from labop.sample_collection import SampleCollection -from labop.strings import Strings from uml.behavior import Behavior +from . import inner +from .data import deserialize_sample_format, serialize_sample_format +from .sample_collection import SampleCollection +from .strings import Strings + class SampleMetadata(inner.SampleMetadata): def __init__(self, *args, **kwargs): diff --git a/labop/sbol_factory.py b/labop/sbol_factory.py index 96d4d90a..4e463e9d 100644 --- a/labop/sbol_factory.py +++ b/labop/sbol_factory.py @@ -2,7 +2,7 @@ The SBOLFactory class defines the functions corresponding to the dynamically generated labop class SBOLFactory """ -import labop.inner as inner +from . import inner class SBOLFactory(inner.SBOLFactory): diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..11793132 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,43 @@ +site_name: LabOP Docs + +theme: + name: "material" + +plugins: +- search +# - pandoc: +# combined: true +- mkdocstrings: + handlers: + python: + paths: [uml] + options: + # show_submodules: true + allow_inspection: false + docstring_style: google + + +nav: + - LabOP Docs: index.md + - tutorials.md + - How-To Guides: how-to-guides.md + - Reference: + - Data Model: + - UML: + - Top-Level: reference/uml/top.md + - Literals: reference/uml/literals.md + - Activities: reference/uml/activities.md + - Behaviors: reference/uml/behaviors.md + - Time: reference/uml/time.md + - Literals: reference/uml/literals.md + - LabOP: + - Top-Level: reference/labop/top.md + - Data: reference/labop/data.md + - Execution: reference/labop/execution.md + - Samples: reference/labop/samples.md + - Other: reference/labop/other.md + - LabOP Library: reference/library.md + # - Containers: + # - Time: + # - Data: + - explanation.md diff --git a/uml/literal_boolean.py b/uml/literal_boolean.py index 7d150a4f..00a12bfb 100644 --- a/uml/literal_boolean.py +++ b/uml/literal_boolean.py @@ -8,7 +8,33 @@ class LiteralBoolean(inner.LiteralBoolean, LiteralSpecification): def __init__(self, *args, **kwargs): + r""" + Create a Boolean valued literal + + Examples: + >>> my_boolean = LiteralBoolean(value=True) + >>> my_boolean.get_value() + True + """ super().__init__(*args, **kwargs) - def dot_value(self): + def dot_value(self) -> str: + r""" + Return string representation that can be rendered by Graphviz dot. + + Examples: + >>> my_boolean.dot_value() + 'True' + + Returns + ------- + str + String representing the LiteralBoolean + """ return str(self.value) + + +if __name__ == "__main__": + import doctest + + doctest.testmod(extraglobs={"my_boolean": LiteralBoolean(value=True)}) diff --git a/uml/literal_specification.py b/uml/literal_specification.py index fc0dccac..d2476dc9 100644 --- a/uml/literal_specification.py +++ b/uml/literal_specification.py @@ -1,5 +1,5 @@ """ -The LiteralSpecification class defines the functions corresponding to the dynamically generated labop class LiteralSpecification +The LiteralSpecification class defines the functions corresponding to the dynamically generated labop class LiteralSpecification. """ import html @@ -10,15 +10,65 @@ class LiteralSpecification(inner.LiteralSpecification, ValueSpecification): def __init__(self, *args, **kwargs): + r""" + Create a LiteralSpecification + + Examples: + >>> my_literal_specification = LiteralSpecification() + """ super().__init__(*args, **kwargs) def get_value(self): + r""" + Get value of the LiteralSpecification. + + Examples: + >>> my_literal_specification.get_value() + Traceback (most recent call last): + ... + TypeError: is abstract and does not have a value. Try instantiating a subclass instead. + >>> from uml.literal_boolean import LiteralBoolean + >>> LiteralBoolean(value=False).get_value() + False + + Returns + ------- + type + The value of the literal whose type is determined by the subclass of LiteralSpecification. + """ + if type(self) == LiteralSpecification: + raise TypeError( + f"{__class__} is abstract and does not have a value. Try instantiating a subclass instead." + ) return self.value def __str__(self): + r""" + Generate string representation of LiteralSpecification + + Examples: + >>> str(my_literal_specification) + Traceback (most recent call last): + ... + TypeError: is abstract and does not have a value. Try instantiating a subclass instead. + >>> from uml.literal_boolean import LiteralBoolean + >>> str(LiteralBoolean(value=False)) + 'False' + + Returns + ------- + str + HTML-compatible string representation of the LiteralSpecification. + """ value = self.get_value() if isinstance(value, str) or isinstance(value, int) or isinstance(value, bool): val_str = html.escape(str(value)).lstrip("\n").replace("\n", "
") else: val_str = str(value) return val_str + + +if __name__ == "__main__": + import doctest + + doctest.testmod(extraglobs={"my_literal_specification": LiteralSpecification()}) From 0bce91de9678c7e66ed90906103a318609975c10 Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:40:57 -0500 Subject: [PATCH 03/12] fix tests --- labop/__init__.py | 2 +- labop/activity_edge_flow.py | 3 +-- labop/activity_node_execution.py | 3 ++- labop/lab_interface.py | 6 ++---- labop/sample_mask.py | 8 +++----- labop_convert/markdown/markdown_specialization.py | 1 + 6 files changed, 10 insertions(+), 13 deletions(-) diff --git a/labop/__init__.py b/labop/__init__.py index 4c4f024b..879befe1 100644 --- a/labop/__init__.py +++ b/labop/__init__.py @@ -6,12 +6,12 @@ from .utils import * from .parameter_value import * -from .activity_node_execution import * from .sample_collection import * from .activity_edge_flow import * from .behavior_execution import * from .call_behavior_execution import * from .protocol_execution import * +from .activity_node_execution import * from .primitive import * diff --git a/labop/activity_edge_flow.py b/labop/activity_edge_flow.py index 1c410127..0ea7cdbe 100644 --- a/labop/activity_edge_flow.py +++ b/labop/activity_edge_flow.py @@ -9,7 +9,6 @@ from uml import CallBehaviorAction, InputPin, LiteralReference, Parameter from . import inner -from .activity_node_execution import ActivityNodeExecution from .protocol import Protocol @@ -84,7 +83,7 @@ def get_token_source( def to_dot( self, dot: graphviz.Graph, - target_node_execution: ActivityNodeExecution, + target_node_execution: "ActivityNodeExecution", namespace, dest_parameter=None, out_dir=".", diff --git a/labop/activity_node_execution.py b/labop/activity_node_execution.py index 9747ca50..df7cd240 100644 --- a/labop/activity_node_execution.py +++ b/labop/activity_node_execution.py @@ -14,7 +14,6 @@ ) from . import inner -from .call_behavior_execution import CallBehaviorExecution class ActivityNodeExecution(inner.ActivityNodeExecution): @@ -87,6 +86,8 @@ def get_calling_behavior_execution( Returns: CallBehaviorExecution: CallBehaviorExecution """ + from .call_behavior_execution import CallBehaviorExecution + node = self.node.lookup() protocol = node.protocol() initial = protocol.initial() diff --git a/labop/lab_interface.py b/labop/lab_interface.py index f8703df5..5f2a7d2f 100644 --- a/labop/lab_interface.py +++ b/labop/lab_interface.py @@ -4,8 +4,6 @@ import xarray as xr from numpy import nan -from labop import SampleCollection - from .data import serialize_sample_format from .strings import Strings @@ -13,7 +11,7 @@ class LabInterface: @staticmethod def measure_absorbance( - samples: SampleCollection, wavelength: float, sample_format: str + samples: "SampleCollection", wavelength: float, sample_format: str ) -> xr.DataArray: # Override this method to interface with laboratory plate reader API if sample_format == Strings.XARRAY: @@ -30,7 +28,7 @@ def measure_absorbance( @staticmethod def measure_fluorescence( - samples: SampleCollection, + samples: "SampleCollection", excitation: float, emission: float, bandpass: float, diff --git a/labop/sample_mask.py b/labop/sample_mask.py index 13243a3b..3eb39ce3 100644 --- a/labop/sample_mask.py +++ b/labop/sample_mask.py @@ -7,12 +7,10 @@ import xarray as xr from . import inner - -# from .data import deserialize_sample_format, serialize_sample_format +from .data import deserialize_sample_format, serialize_sample_format from .sample_collection import SampleCollection - -# from .strings import Strings -# from .utils import contiguous_coordinates +from .strings import Strings +from .utils import contiguous_coordinates class SampleMask(inner.SampleMask, SampleCollection): diff --git a/labop_convert/markdown/markdown_specialization.py b/labop_convert/markdown/markdown_specialization.py index 4fd3a167..ef501657 100644 --- a/labop_convert/markdown/markdown_specialization.py +++ b/labop_convert/markdown/markdown_specialization.py @@ -177,6 +177,7 @@ def _outputs_markdown( def _materials_markdown(self, protocol, subprotocol_executions): document_objects = protocol.document.objects # TODO: Use different criteria for compiling Materials list based on ValueSpecifications for ValuePins + markdown = "" components = [ x for x in document_objects if isinstance(x, sbol3.component.Component) ] From d3fcfd883d9304345e908b42c00d2957f81c0edc Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:40:57 -0500 Subject: [PATCH 04/12] fix mkdocs warnings --- .gitignore | 10 ++++++++++ labop/activity_node_execution.py | 2 +- labop/execution_engine.py | 32 ++++++++------------------------ labop/primitive.py | 6 ++++++ labop/protocol.py | 8 ++++++-- labop/sample_data.py | 2 +- mkdocs.yml | 5 +---- uml/activity.py | 3 +++ uml/activity_node.py | 11 +++++++++++ uml/call_behavior_action.py | 12 ++++++++++++ 10 files changed, 59 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index 065e5d1b..26438e6c 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,13 @@ site/pandoc/combined.pdf.md site/reference/index.html site/search/search_index.json site/tutorials/index.html +site/reference/labop/data/index.html +site/reference/labop/execution/index.html +site/reference/labop/samples/index.html +site/reference/labop/top/index.html +site/reference/library/index.html +site/reference/uml/activities/index.html +site/reference/uml/behaviors/index.html +site/reference/uml/literals/index.html +site/reference/uml/time/index.html +site/reference/uml/top/index.html diff --git a/labop/activity_node_execution.py b/labop/activity_node_execution.py index df7cd240..8f387f85 100644 --- a/labop/activity_node_execution.py +++ b/labop/activity_node_execution.py @@ -77,7 +77,7 @@ def get_token_source( def get_calling_behavior_execution( self, visited=None, - ): + ) -> "CallBehaviorExecution": """Look for the InitialNode for the Activity including self and identify a Calling CallBehaviorExecution (if present) Args: diff --git a/labop/execution_engine.py b/labop/execution_engine.py index d62dffd7..5f513757 100644 --- a/labop/execution_engine.py +++ b/labop/execution_engine.py @@ -6,6 +6,7 @@ from abc import ABC from typing import Callable, Dict, List, Optional, Tuple, Union +import graphviz import pandas as pd import sbol3 from numpy import record @@ -807,30 +808,15 @@ def run(self, protocol: Protocol, start_time: datetime.datetime = None): return ready, choices, graph def advance(self, ready: List[ActivityNode]): - def auto_advance(r): - # If Node is a CallBehavior action, then: - if isinstance(r, CallBehaviorAction): - behavior = r.behavior.lookup() - return ( # It is a subprotocol - isinstance(behavior, Protocol) - or (len(list(behavior.get_outputs())) == 0) # Has no output pins - or ( # Overrides the (empty) default implementation of compute_output() - not hasattr(behavior.compute_output, "__func__") - or behavior.compute_output.__func__ != Primitive.compute_output - ) - ) - else: - return True - - auto_advance_nodes = [r for r in ready if auto_advance(r)] + auto_advance_nodes = [r for r in ready if r.auto_advance()] while len(auto_advance_nodes) > 0: ready = self.step(auto_advance_nodes) - auto_advance_nodes = [r for r in ready if auto_advance(r)] + auto_advance_nodes = [r for r in ready if r.auto_advance()] return self.executable_activity_nodes() - def ready_message(self, ready: List[ActivityNode]): + def ready_message(self, ready: List[ActivityNode]) -> str: msg = "Activities Ready to Execute:\n" def activity_name(a): @@ -865,7 +851,9 @@ def decision_name(a): ) # return choices #f"{msg}{ready_nodes}" - def next(self, activity_node: ActivityNode, node_output: callable): + def next( + self, activity_node: ActivityNode, node_output: callable + ) -> Tuple[List[ActivityNode], str, graphviz.Graph]: """Execute a single ActivityNode using the node_output function to calculate its output pin values. Args: @@ -873,7 +861,7 @@ def next(self, activity_node: ActivityNode, node_output: callable): node_output (callable): function to calculate output pins Returns: - _type_: _description_ + Tuple[List[ActivityNode], List[str], graphviz.Graph]: Summary of the next possible execution steps, including the executable ActivityNodes, Activities, and a graphical depiction of the execution state. """ successors = self.step( [activity_node], node_outputs={activity_node: node_output} @@ -882,7 +870,3 @@ def next(self, activity_node: ActivityNode, node_output: callable): choices = self.ready_message(ready) graph = self.ex.to_dot(ready=ready, done=self.ex.backtrace()[0]) return ready, choices, graph - - -################################## -# Helper utility functions diff --git a/labop/primitive.py b/labop/primitive.py index 04e8a673..90d8ce37 100644 --- a/labop/primitive.py +++ b/labop/primitive.py @@ -519,3 +519,9 @@ def template(self): ] ) return f"step = protocol.primitive_step(\n\t'{self.display_id}',\n\t{args}\n\t)" + + def auto_advance(self) -> bool: + return super(Behavior).auto_advance() or ( + not hasattr(self.compute_output, "__func__") + or self.compute_output.__func__ != Primitive.compute_output + ) diff --git a/labop/protocol.py b/labop/protocol.py index 54ca865c..522c85d8 100644 --- a/labop/protocol.py +++ b/labop/protocol.py @@ -114,8 +114,9 @@ def make_decision_node( Returns a uml:DecisionNode and a set of edges connecting incoming and outgoing nodes. Args: - primary_incoming_source_node (uml:ActivityNode): primary incoming edge type (control or object) determines output edge types - decision_input_source_node (uml:ActivityNode, optional): Used to evaluate guards. Defaults to None. + primary_incoming_node (uml:ActivityNode): primary incoming edge type (control or object) determines output edge types + decision_input_behavior (uml.Behavior): Behavior computing decision predicate + decision_input_source (uml:ActivityNode, optional): Used to evaluate guards. Defaults to None. outgoing_targets (List[Tuple[ValueSpecification, ActivityNode]], optional): List of pairs of guards and nodes for outgoing edges. Defaults to None. """ @@ -252,3 +253,6 @@ def remove_duplicates(self): dups_to_remove = [d for d in dup if targets[d] == 0 and sources[d] == 0] for n in dups_to_remove: del self.nodes[self.nodes.index(n)] + + def auto_advance(self): + return True diff --git a/labop/sample_data.py b/labop/sample_data.py index 167ff7e4..366a677d 100644 --- a/labop/sample_data.py +++ b/labop/sample_data.py @@ -36,7 +36,7 @@ def to_data_array(self, sample_format=Strings.XARRAY): sample_data = deserialize_sample_format(self.values, parent=self) return sample_data - def from_table(self, table: List[List[Dict[str, str]]]): + def from_table(self, table: List[List[Dict[str, str]]]) -> "SampleData": """Convert from LabOPED table to SampleData Args: diff --git a/mkdocs.yml b/mkdocs.yml index 11793132..59934758 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -17,6 +17,7 @@ plugins: docstring_style: google + nav: - LabOP Docs: index.md - tutorials.md @@ -35,9 +36,5 @@ nav: - Data: reference/labop/data.md - Execution: reference/labop/execution.md - Samples: reference/labop/samples.md - - Other: reference/labop/other.md - LabOP Library: reference/library.md - # - Containers: - # - Time: - # - Data: - explanation.md diff --git a/uml/activity.py b/uml/activity.py index d5a6d7d0..199bacd0 100644 --- a/uml/activity.py +++ b/uml/activity.py @@ -660,3 +660,6 @@ def get_edges(self, name: str = None, edge_type: Type = None) -> List[ActivityNo if (edge_type is None or isinstance(n, edge_type)) and (name is None or n.name == name) ] + + def auto_advance(self) -> bool: + return len(self.get_outputs()) == 0 diff --git a/uml/activity_node.py b/uml/activity_node.py index 43f6607f..3cb4306a 100644 --- a/uml/activity_node.py +++ b/uml/activity_node.py @@ -210,3 +210,14 @@ def get_value( def is_well_formed(self) -> List[WellFormednessIssue]: return [] + + def auto_advance(self) -> bool: + """ + Is the node executable without additional manual input? + + Returns + ------- + bool + Whether the node can be automatically executed. + """ + return True diff --git a/uml/call_behavior_action.py b/uml/call_behavior_action.py index e8ef5fd9..bc8e979b 100644 --- a/uml/call_behavior_action.py +++ b/uml/call_behavior_action.py @@ -161,3 +161,15 @@ def get_parameter_value( else: value = f"{parameter.name}" return value + + def auto_advance(self): + """ + Is the node executable without additional manual input? + + Returns + ------- + bool + Whether the node can be automatically executed. + """ + behavior = self.get_behavior() + return behavior.auto_advance() From e1275007e5c79836629002955ce47df44a284357 Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:40:57 -0500 Subject: [PATCH 05/12] cleanup files, make targets, ignores clean --- .gitignore | 40 +- Makefile | 13 + .../iGEM/artifacts/interlab-endpoint.md | 86 ++- .../protocols/iGEM/artifacts/interlab-exp2.md | 43 ++ .../iGEM/artifacts/interlab_growth_curve.md | 85 +++ .../iGEM/artifacts/particle_calibration.md | 69 ++ .../iGEM/challenging-interlab-growth-curve.py | 680 ++++++++++++++++++ .../iGEM/interlab-growth-curve.ipynb | 583 +++++++++++++++ .../protocols/iGEM/interlab-growth-curve.py | 316 ++++++++ .../iGEM/revised-interlab-growth-curve.py | 581 +++++++++++++++ .../ludox/artifacts/test_LUDOX_markdown.md | 102 +++ 11 files changed, 2526 insertions(+), 72 deletions(-) create mode 100644 examples/protocols/iGEM/artifacts/interlab-exp2.md create mode 100644 examples/protocols/iGEM/artifacts/interlab_growth_curve.md create mode 100644 examples/protocols/iGEM/artifacts/particle_calibration.md create mode 100644 examples/protocols/iGEM/challenging-interlab-growth-curve.py create mode 100644 examples/protocols/iGEM/interlab-growth-curve.ipynb create mode 100644 examples/protocols/iGEM/interlab-growth-curve.py create mode 100644 examples/protocols/iGEM/revised-interlab-growth-curve.py create mode 100644 examples/protocols/ludox/artifacts/test_LUDOX_markdown.md diff --git a/.gitignore b/.gitignore index 26438e6c..289276f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,12 @@ /secrets/strateos_secrets.json /.pytest_cache/ -/env/ +*env* **/.ipynb_checkpoints **/cluster* **/__pycache__ -notebooks/*md -pylabop.egg-info* -notebooks/out -notebooks/.* +notebooks/* +!notebooks/*.ipynb +**/*.egg-info* .vscode **/.DS_Store build @@ -16,36 +15,9 @@ _site .sass-cache *.gv.pdf **/*gv -test_LUDOX_markdown.md -**/labop.egg-info/* assets/ container-ontology -test/out -.env -out +**/out .coverage cov.xml -*.org -**/sample_graph_** -site/404.html -site/index.html -site/objects.inv -site/sitemap.xml -site/sitemap.xml.gz -site/explanation/index.html -site/how-to-guides/index.html -site/pandoc/combined.pdf -site/pandoc/combined.pdf.md -site/reference/index.html -site/search/search_index.json -site/tutorials/index.html -site/reference/labop/data/index.html -site/reference/labop/execution/index.html -site/reference/labop/samples/index.html -site/reference/labop/top/index.html -site/reference/library/index.html -site/reference/uml/activities/index.html -site/reference/uml/behaviors/index.html -site/reference/uml/literals/index.html -site/reference/uml/time/index.html -site/reference/uml/top/index.html +site/* diff --git a/Makefile b/Makefile index ec29156b..7e8f0945 100644 --- a/Makefile +++ b/Makefile @@ -27,3 +27,16 @@ run: docker -v $$PWD:/root/home:Z \ -e "PROTOCOL_SCRIPT=${PROTOCOL_SCRIPT}" \ ${TAGGED_NAME} + +spec: + python doc/generate_specification_content.py + +lib-docs: + mkdocs build + +test: + pytest test + pytest --nbmake --overwrite -n=auto "notebooks/labop_demo.ipynb" "notebooks/markdown.ipynb" + +format: + pre-commit diff --git a/examples/protocols/iGEM/artifacts/interlab-endpoint.md b/examples/protocols/iGEM/artifacts/interlab-endpoint.md index ad3cf1a0..527e43ca 100644 --- a/examples/protocols/iGEM/artifacts/interlab-endpoint.md +++ b/examples/protocols/iGEM/artifacts/interlab-endpoint.md @@ -8,17 +8,17 @@ Before performing the cell measurements, you need to perform all the calibration For all below indicated cell measurements, you must use the same type of plates and the same volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same type of plates, volumes, and settings, the measurements will not be valid. -Protocol summary: You will transform the eight devices listed in Table 1 into E. coli K-12 DH5-alpha cells. The next day you will pick two colonies from each transformation (16 total) and use them to inoculate 5 mL overnight cultures (this step is still in tubes). Each of these 16 overnight cultures will be used to inoculate four wells in a 96-well plate (200 microliters each, 4 replicates) or one test tube (12 mL). You will measure how fluorescence and optical density develops over 6 hours by taking measurements at time point 0 hour and at time point 6 hours. Follow the protocol below and the visual instructions in Figure 1 and Figure 2. +Protocol summary: You will transform the eight devices listed in Table 1 into E. coli K-12 DH5-alpha cells. The next day you will pick two colonies from each transformation (16 total) and use them to inoculate 5 mL overnight cultures (this step is still in tubes). Each of these 16 overnight cultures will be used to inoculate four wells in a 96-well plate (200uL each, 4 replicates) and one test tube (12 mL). You will measure how fluorescence and optical density develops over 6 hours by taking measurements at time point 0 hour and at time point 6 hours. Follow the protocol below and the visual instructions in Figure 1 and Figure 2. ## Protocol Outputs: -* `baseline absorbance of culture (day 2) measurements of cultures (0 hr timepoint)` -* `0 hr absorbance timepoint measurements of plate 1` -* `0 hr fluorescence timepoint measurements of plate 1` -* `6 hr absorbance timepoint measurements of plate 1` -* `6 hr fluorescence timepoint measurements of plate 1` -* `6 hr absorbance timepoint measurements of plate 2` -* `6 hr fluorescence timepoint measurements of plate 2` +* Dataset: [test_LUDOX_markdown.xlsx](test_LUDOX_markdown.xlsx) +* Dataset: [test_LUDOX_markdown.xlsx](test_LUDOX_markdown.xlsx) +* Dataset: [test_LUDOX_markdown.xlsx](test_LUDOX_markdown.xlsx) +* Dataset: [test_LUDOX_markdown.xlsx](test_LUDOX_markdown.xlsx) +* Dataset: [test_LUDOX_markdown.xlsx](test_LUDOX_markdown.xlsx) +* Dataset: [test_LUDOX_markdown.xlsx](test_LUDOX_markdown.xlsx) +* Dataset: [test_LUDOX_markdown.xlsx](test_LUDOX_markdown.xlsx) ## Protocol Materials: @@ -26,8 +26,8 @@ Protocol summary: You will transform the eight devices listed in Table 1 into E. * [Negative control](http://parts.igem.org/Part:BBa_J428100) * [Positive control (I20270)](http://parts.igem.org/Part:BBa_I20270) * [Test Device 1 (J364000)](http://parts.igem.org/Part:BBa_J364000) -* [Test Device 2 (J36401)](http://parts.igem.org/Part:BBa_J364001) -* [Test Device 3 (J36402)](http://parts.igem.org/Part:BBa_J364002) +* [Test Device 2 (J364001)](http://parts.igem.org/Part:BBa_J364001) +* [Test Device 3 (J364002)](http://parts.igem.org/Part:BBa_J364002) * [Test Device 4 (J364007)](http://parts.igem.org/Part:BBa_J364007) * [Test Device 5 (J364008)](http://parts.igem.org/Part:BBa_J364008) * [Test Device 6 (J364009)](http://parts.igem.org/Part:BBa_J364009) @@ -41,7 +41,7 @@ Protocol summary: You will transform the eight devices listed in Table 1 into E. * culture tube (x 32) * 1.5 mL microfuge tube (x 32) * 50 ml conical tube (x 16) -* 96 well microplate (x 2) +* 96 well plate (x 2) * microplate adhesive sealing film @@ -60,51 +60,61 @@ Protocol summary: You will transform the eight devices listed in Table 1 into E. ## Protocol Steps: 1. Obtain 8 x Petri dish containing LB Agar + Chloramphenicol (34 ug/mL) growth medium for culturing `transformant strains` -2. Transform `Negative control` DNA into _`E. coli`_ ` DH5 alpha competent cells`. Repeat for the remaining transformant DNA: `Positive control (I20270)`, `Test Device 1 (J364000)`, `Test Device 2 (J36401)`, `Test Device 3 (J36402)`, `Test Device 4 (J364007)`, `Test Device 5 (J364008)`, and `Test Device 6 (J364009)`. Plate transformants on LB Agar + Chloramphenicol (34 ug/mL) `transformant strains` plates. Incubate at 37.0°C for 16.0 hour (overnight). +2. Transform `Negative control` DNA into _`E. coli`_ ` DH5 alpha competent cells`. Repeat for the remaining transformant DNA: `Positive control (I20270)`, `Test Device 1 (J364000)`, `Test Device 2 (J364001)`, `Test Device 3 (J364002)`, `Test Device 4 (J364007)`, `Test Device 5 (J364008)`, and `Test Device 6 (J364009)`. Plate transformants on LB Agar + Chloramphenicol (34 ug/mL) `transformant strains` plates. Incubate overnight (for 16 hour) at 37.0°C. 3. Obtain 16 x culture tubes to contain `culture (day 1)` 4. Pick 2 colonies from each `transformant strains` plate. -5. Inoculate 2 colonies of each transformant strains, for a total of 16 cultures. Inoculate each into 12.0 mL of LB Broth + Chloramphenicol (34 ug/mL) in culture (day 1) and grow overnight (for 16.0 hour) at 37.0°C and 220 rpm. +5. Inoculate 2 colonies of each transformant strains, for a total of 16 cultures. Inoculate each into 12.0mL of LB Broth + Chloramphenicol (34 ug/mL) in culture (day 1) and grow overnight (for 16.0 hour) at 37.0°C and 220 rpm. 6. Obtain 16 x culture tubes to contain `culture (day 2)` -7. Dilute each of 16 `culture (day 1)` samples with LB Broth + Chloramphenicol (34 ug/mL) into the culture tube at a 1:10 ratio and final volume of 5.0 mL. Maintain at 4.0°C while performing dilutions. (This can be also performed on ice). +7. Dilute each of 16 `culture (day 1)` samples with LB Broth + Chloramphenicol (34 ug/mL) into the culture tube at a 1:10 ratio and final volume of 5.0mL. Maintain at 4.0°C while performing dilutions. (This can be also performed on ice). 8. Obtain 16 x 1.5 mL microfuge tubes to contain `cultures (0 hr timepoint)` 9. Hold `cultures (0 hr timepoint)` on ice. This will prevent cell growth while transferring samples. -10. Transfer 1.0 mL of each of 16 `culture (day 2)` samples to 1.5 mL microfuge tube containers to contain a total of 16 `cultures (0 hr timepoint)` samples. Maintain at 4.0°C during transfer. (This can be also performed on Ice). -11. Measure baseline absorbance of culture (day 2) of `cultures (0 hr timepoint)` at 600.0 nanometer. +10. Transfer 1.0mL of each of 16 `culture (day 2)` samples to wells +Dimensions: () +Data variables: + *empty* of 1.5 mL microfuge tube containers to contain a total of 16 `cultures (0 hr timepoint)` samples. Maintain at 4.0°C during transfer. (This can be also performed on Ice). +11. Measure baseline absorbance of culture (day 2) of `cultures (0 hr timepoint)` at 600.0nm. 12. Obtain 16 x 50 ml conical tubes to contain `back-diluted culture` The conical tube should be opaque, amber-colored, or covered with foil. -13. Back-dilute each of 16 `culture (day 2)` samples to a target OD of 0.02 using LB Broth + Chloramphenicol (34 ug/mL) as diluent to a final volume of 12.0 mL. Maintain at 4.0°C while performing dilutions. +13. Back-dilute each of 16 `culture (day 2)` samples to a target OD of 0.02 using LB Broth + Chloramphenicol (34 ug/mL) as diluent to a final volume of 12.0mL. Maintain at 4.0°C while performing dilutions. -![](C:\Users\Ale\Documents\labop_local\examples\fig1_standard_protocol.png) +![](/Users/danbryce/Documents/sift/xplan/external/labop/examples/fig1_standard_protocol.png)

Fig 1: Visual representation of protocol

14. Obtain 16 x 1.5 mL microfuge tubes to contain `back-diluted culture aliquots` 15. Hold `back-diluted culture aliquots` on ice. This will prevent cell growth while transferring samples. -16. Transfer 1.0 mL of each of 16 `back-diluted culture` samples to 1.5 mL microfuge tube containers to contain a total of 16 `back-diluted culture aliquots` samples. Maintain at 4.0°C during transfer. (This can be also performed on Ice). -17. Obtain a 96 well microplate to contain `plate 1` -18. Hold `plate 1` on ice. -19. Transfer 200.0 microliter of each `back-diluted culture aliquots` sample to 96 well microplate `plate 1` in the wells indicated in the plate layout. +16. Transfer 1.0mL of each of 16 `back-diluted culture` samples to wells +Dimensions: () +Data variables: + *empty* of 1.5 mL microfuge tube containers to contain a total of 16 `back-diluted culture aliquots` samples. Maintain at 4.0°C during transfer. (This can be also performed on Ice). +17. Provision a container named `plate 1` such as: + [NEST96WellPlate](https://sift.net/container-ontology/container-ontology#NEST96WellPlate), + [Corning96WellPlate360uLFlat](https://sift.net/container-ontology/container-ontology#Corning96WellPlate360uLFlat). +18. Hold all `None` samples on ice. +19. Transfer 200.0uL of each `back-diluted culture aliquots` sample to 96 well plate `plate 1` in the wells indicated in the plate layout. Maintain at 4.0°C during transfer. -20. Transfer 200.0 microliter of `LB Broth + Chloramphenicol (34 ug/mL)` sample to wells A1:H1, A10:H10, A12:H12 of 96 well microplate `plate 1`. Maintain at 4.0°C during transfer. These samples are blanks. +20. Transfer 200.0uL of `LB Broth + Chloramphenicol (34 ug/mL)` sample to wells {'A1': None, 'B1': None, 'C1': None, 'D1': None, 'E1': None, 'F1': None, 'G1': None, 'H1': None, 'A2': None, 'B2': None, 'C2': None, 'D2': None, 'E2': None, 'F2': None, 'G2': None, 'H2': None, 'A3': None, 'B3': None, 'C3': None, 'D3': None, 'E3': None, 'F3': None, 'G3': None, 'H3': None, 'A4': None, 'B4': None, 'C4': None, 'D4': None, 'E4': None, 'F4': None, 'G4': None, 'H4': None, 'A5': None, 'B5': None, 'C5': None, 'D5': None, 'E5': None, 'F5': None, 'G5': None, 'H5': None, 'A6': None, 'B6': None, 'C6': None, 'D6': None, 'E6': None, 'F6': None, 'G6': None, 'H6': None, 'A7': None, 'B7': None, 'C7': None, 'D7': None, 'E7': None, 'F7': None, 'G7': None, 'H7': None, 'A8': None, 'B8': None, 'C8': None, 'D8': None, 'E8': None, 'F8': None, 'G8': None, 'H8': None, 'A9': None, 'B9': None, 'C9': None, 'D9': None, 'E9': None, 'F9': None, 'G9': None, 'H9': None, 'A10': None, 'B10': None, 'C10': None, 'D10': None, 'E10': None, 'F10': None, 'G10': None, 'H10': None, 'A11': None, 'B11': None, 'C11': None, 'D11': None, 'E11': None, 'F11': None, 'G11': None, 'H11': None, 'A12': None, 'B12': None, 'C12': None, 'D12': None, 'E12': None, 'F12': None, 'G12': None, 'H12': None} of 96 well plate `plate 1`. Maintain at 4.0°C during transfer. These samples are blanks. -![](C:\Users\Ale\Documents\labop_local\examples\fig2_cell_calibration.png) +![](/Users/danbryce/Documents/sift/xplan/external/labop/examples/fig2_cell_calibration.png)

Fig 2: Plate layout

-21. Measure 0 hr absorbance timepoint of `plate 1` at 600.0 nanometer. -22. Measure 0 hr fluorescence timepoint of `plate 1` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass. -23. Cover `plate 1` samples in 96 well microplate with your choice of material to prevent evaporation. +21. Measure 0 hr absorbance timepoint of `plate 1` at 600.0nm. +22. Measure 0 hr fluorescence timepoint of `plate 1` with excitation wavelength of 488.0nm and emission filter of 530.0nm and 30.0nm bandpass. +23. Cover `plate 1` samples in 96 well plate with your choice of material to prevent evaporation. 24. Incubate all `back-diluted culture` samples for 6.0 hour at 37.0°C at 220 rpm. -25. Incubate all `plate 1` samples for 6.0 hour at 37.0°C at 220 rpm. +25. Incubate `plate 1` for 6.0 hour at 37.0°C at 220 rpm. 26. Hold all `back-diluted culture` samples on ice. This will inhibit cell growth during the subsequent pipetting steps. 27. Hold all `plate 1` samples on ice. This will inhibit cell growth during the subsequent pipetting steps. -28. Obtain a 96 well microplate to contain `plate 2` -29. Hold `plate 2` on ice. -30. Transfer 200.0 microliter of each `back-diluted culture` sample to 96 well microplate `plate 2` in the wells indicated in the plate layout. +28. Provision a container named `plate 2` such as: + [NEST96WellPlate](https://sift.net/container-ontology/container-ontology#NEST96WellPlate), + [Corning96WellPlate360uLFlat](https://sift.net/container-ontology/container-ontology#Corning96WellPlate360uLFlat). +29. Hold all `None` samples on ice. +30. Transfer 200.0uL of each `back-diluted culture` sample to 96 well plate `plate 2` in the wells indicated in the plate layout. Maintain at 4.0°C during transfer. -31. Transfer 200.0 microliter of `LB Broth + Chloramphenicol (34 ug/mL)` sample to wells A1:H1, A10:H10, A12:H12 of 96 well microplate `plate 2`. Maintain at 4.0°C during transfer. These are the blanks. -32. Measure 6 hr absorbance timepoint of `plate 1` at 600.0 nanometer. -33. Measure 6 hr fluorescence timepoint of `plate 1` with excitation wavelength of 485.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass. -34. Measure 6 hr absorbance timepoint of `plate 2` at 600.0 nanometer. -35. Measure 6 hr fluorescence timepoint of `plate 2` with excitation wavelength of 485.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass. -36. Import data for `baseline absorbance of culture (day 2) measurements of cultures (0 hr timepoint)`, `0 hr absorbance timepoint measurements of plate 1`, `0 hr fluorescence timepoint measurements of plate 1`, `6 hr absorbance timepoint measurements of plate 1`, `6 hr fluorescence timepoint measurements of plate 1`, `6 hr absorbance timepoint measurements of plate 2`, `6 hr fluorescence timepoint measurements of plate 2` into provided Excel file. +31. Transfer 200.0uL of `LB Broth + Chloramphenicol (34 ug/mL)` sample to wells {'A1': None, 'B1': None, 'C1': None, 'D1': None, 'E1': None, 'F1': None, 'G1': None, 'H1': None, 'A2': None, 'B2': None, 'C2': None, 'D2': None, 'E2': None, 'F2': None, 'G2': None, 'H2': None, 'A3': None, 'B3': None, 'C3': None, 'D3': None, 'E3': None, 'F3': None, 'G3': None, 'H3': None, 'A4': None, 'B4': None, 'C4': None, 'D4': None, 'E4': None, 'F4': None, 'G4': None, 'H4': None, 'A5': None, 'B5': None, 'C5': None, 'D5': None, 'E5': None, 'F5': None, 'G5': None, 'H5': None, 'A6': None, 'B6': None, 'C6': None, 'D6': None, 'E6': None, 'F6': None, 'G6': None, 'H6': None, 'A7': None, 'B7': None, 'C7': None, 'D7': None, 'E7': None, 'F7': None, 'G7': None, 'H7': None, 'A8': None, 'B8': None, 'C8': None, 'D8': None, 'E8': None, 'F8': None, 'G8': None, 'H8': None, 'A9': None, 'B9': None, 'C9': None, 'D9': None, 'E9': None, 'F9': None, 'G9': None, 'H9': None, 'A10': None, 'B10': None, 'C10': None, 'D10': None, 'E10': None, 'F10': None, 'G10': None, 'H10': None, 'A11': None, 'B11': None, 'C11': None, 'D11': None, 'E11': None, 'F11': None, 'G11': None, 'H11': None, 'A12': None, 'B12': None, 'C12': None, 'D12': None, 'E12': None, 'F12': None, 'G12': None, 'H12': None, 'A2:D2': 'http://igem.org/engineering/transformant1', 'E2:H2': 'http://igem.org/engineering/transformant2', 'A3:D3': 'http://igem.org/engineering/transformant3', 'E3:H3': 'http://igem.org/engineering/transformant4', 'A4:D4': 'http://igem.org/engineering/transformant5', 'E4:H4': 'http://igem.org/engineering/transformant6', 'A5:D5': 'http://igem.org/engineering/transformant7', 'E5:H5': 'http://igem.org/engineering/transformant8', 'A7:D7': 'http://igem.org/engineering/transformant1', 'E7:H7': 'http://igem.org/engineering/transformant2', 'A8:D8': 'http://igem.org/engineering/transformant3', 'E8:H8': 'http://igem.org/engineering/transformant4', 'A9:D9': 'http://igem.org/engineering/transformant5', 'E9:H9': 'http://igem.org/engineering/transformant6', 'A10:D10': 'http://igem.org/engineering/transformant7', 'E10:H10': 'http://igem.org/engineering/transformant8'} of 96 well plate `plate 2`. Maintain at 4.0°C during transfer. These are the blanks. +32. Measure 6 hr absorbance timepoint of `plate 1` at 600.0nm. +33. Measure 6 hr fluorescence timepoint of `plate 1` with excitation wavelength of 485.0nm and emission filter of 530.0nm and 30.0nm bandpass. +34. Measure 6 hr absorbance timepoint of `plate 2` at 600.0nm. +35. Measure 6 hr fluorescence timepoint of `plate 2` with excitation wavelength of 485.0nm and emission filter of 530.0nm and 30.0nm bandpass. +36. Import data into the provided Excel file: `baseline absorbance of culture (day 2) measurements of cultures (0 hr timepoint)`, `0 hr absorbance timepoint measurements of plate 1`, `0 hr fluorescence timepoint measurements of plate 1`, `6 hr absorbance timepoint measurements of plate 1`, `6 hr fluorescence timepoint measurements of plate 1`, `6 hr absorbance timepoint measurements of plate 2`, `6 hr fluorescence timepoint measurements of plate 2`. --- -Timestamp: 2022-07-02 12:34:58.015749--- +Timestamp: 2023-03-11 16:05:11.966021 Protocol version: 1.2.2 diff --git a/examples/protocols/iGEM/artifacts/interlab-exp2.md b/examples/protocols/iGEM/artifacts/interlab-exp2.md new file mode 100644 index 00000000..28926134 --- /dev/null +++ b/examples/protocols/iGEM/artifacts/interlab-exp2.md @@ -0,0 +1,43 @@ +# Using the three color calibration protocol: Does the order of transcritional units influence their expression strength? + +In this experiment, your team will measure the fluorescence of six devices that encode two fluorescence proteins in two transcriptional units. The devices differ in the order of the transcriptional units. You will calibrate the fluorescence of these devices to the calibrant dyes and the optical density of the culture to the cell density calibrant. + +This experiment aims to assess the lab-to-lab reproducibility of the three color calibration protocol when two fluorescent proteins are expressed in the same cell. Besides this technical question, it also adresses a fundamental synthetic biology question: does the order of the transcritional units (that encode for the two different fluorescent proteins) on the devices influence their expression levels? + + +## Protocol Materials: +* [_E. coli_ DH5 alpha](https://identifiers.org/taxonomy:668369) +* [LB Broth+chloramphenicol]() +* [chloramphenicol](https://pubchem.ncbi.nlm.nih.gov/compound/5959) +* [Negative control 2022](http://parts.igem.org/Part:BBa_J428100) +* [Positive control 2022 Green](http://parts.igem.org/Part:BBa_J428112) +* [Positive control red (mCherry) Exp 2](http://parts.igem.org/Part:BBa_J428101) +* [Test Device 1 Exp 2 (Dual construct Green and Blue)](http://parts.igem.org/Part:BBa_J428106) +* [Test Device 2 Exp 2 (Dual construct Green and Red)](http://parts.igem.org/Part:BBa_J428107) +* [Test Device 3 Exp 2 (Dual construct Red and Blue)](http://parts.igem.org/Part:BBa_J428105) +* [Test Device 4 Exp 2 (Dual construct Blue and Red)](http://parts.igem.org/Part:BBa_J428108) +* [Test Device 5 Exp 2 (Dual construct Red and Green)](http://parts.igem.org/Part:BBa_J428104) +* culture tube (x 32) +* 1.5 mL microfuge tube (x 48) +* 50 ml conical tube (x 16) +* 96 well plate (x 2) + + +#### Table 1: Part Locations in Distribution Kit +| Part | Coordinate | +| ---- | -------------- | +|BBa_J428100|Kit Plate 1 Well 12M| +|3_Colors_ins_K2656022|BBa_J428112 Kit Plate 1 Well 14C| +|BBa_J428101|Kit Plate 1 Well 12I| +|BBa_J428106|Kit Plate 1 Well 12G| +|BBa_J428107|Kit Plate 1 Well 3L| +|BBa_J428105|Kit Plate 1 Well 5J| +|BBa_J428108|Kit Plate 1 Well 14E| +|DC_R_ins_K2656022|BBa_J428104 Kit Plate 1 Well 5L| + + +## Protocol Steps: +1. Import data into the provided Excel file: . +--- +Timestamp: 2023-03-11 16:05:34.526107 +Protocol version: 1.0b diff --git a/examples/protocols/iGEM/artifacts/interlab_growth_curve.md b/examples/protocols/iGEM/artifacts/interlab_growth_curve.md new file mode 100644 index 00000000..186201ef --- /dev/null +++ b/examples/protocols/iGEM/artifacts/interlab_growth_curve.md @@ -0,0 +1,85 @@ +# Cell measurement protocol + +## Description: +Prior to performing the cell measurements you should perform all three of the calibration measurements. Please do not proceed unless you have completed the three calibration protocols. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For the sake of consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you, and this can count as a collaboration as long as it is appropriately documented on both teams' wikis. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Measurement Committee (measurement at igem dot org) to discuss your situation. + +For all of these cell measurements, you must use the same plates and volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same plates, volumes, and settings, the measurements will not be valid. + + +## Protocol Materials: +* [_E. coli_ DH5 alpha](https://identifiers.org/pubchem.substance:24901740) +* [LB Broth+chloramphenicol](https://identifiers.org/pubchem.substance:24901740) +* [chloramphenicol](https://identifiers.org/pubchem.substance:24901740) +* [Negative control](https://identifiers.org/SBO:0000251) +* [Positive control](https://identifiers.org/SBO:0000251) +* [Test Device 1](https://identifiers.org/SBO:0000251) +* [Test Device 2](https://identifiers.org/SBO:0000251) +* [Test Device 3](https://identifiers.org/SBO:0000251) +* [Test Device 4](https://identifiers.org/SBO:0000251) +* [Test Device 5](https://identifiers.org/SBO:0000251) +* [Test Device 6](https://identifiers.org/SBO:0000251) + + +## Protocol Inputs: + + +## Protocol Outputs: +* `baseline absorbance of culture (day 2) measurements of culture (day 2)` +* `0 hr absorbance timepoint measurements of plate 1` +* `0 hr fluorescence timepoint measurements of plate 1` +* `6 hr absorbance timepoint measurements of plate 1` +* `6 hr fluorescence timepoint measurements of plate 1` +* `6 hr absorbance timepoint measurements of plate 2` +* `6 hr fluorescence timepoint measurements of plate 2` + + +## Steps +1. Transform `Negative control` DNA into _`E. coli`_ ` DH5 alpha` and plate transformants on LB Broth+chloramphenicol. Repeat for the remaining transformant DNA: `Positive control`, `Test Device 1`, `Test Device 2`, `Test Device 3`, `Test Device 4`, `Test Device 5`, and `Test Device 6`. +2. Provision 16 x culture tubes to contain `culture (day 1)` +3. Inoculate _`E. coli`_ ` DH5 alpha+Negative control transformant` into 5.0 milliliter of LB Broth+chloramphenicol in culture (day 1) and grow for 16.0 hour at 37.0 degree Celsius and 220.0 rpm. Repeat this procedure for the other inocula: _`E. coli`_ ` DH5 alpha+Positive control transformant`, _`E. coli`_ ` DH5 alpha+Test Device 1 transformant`, _`E. coli`_ ` DH5 alpha+Test Device 2 transformant`, _`E. coli`_ ` DH5 alpha+Test Device 3 transformant`, _`E. coli`_ ` DH5 alpha+Test Device 4 transformant`, _`E. coli`_ ` DH5 alpha+Test Device 5 transformant`, and _`E. coli`_ ` DH5 alpha+Test Device 6 transformant`. Inoculate 2 replicates for each transformant, for a total of 16 cultures. +4. Provision 16 x culture tubes to contain `culture (day 2)` +5. Dilute each of 16 `culture (day 1)` samples with LB Broth+chloramphenicol into the culture tube at a 1:10 ratio and final volume of 5.0 milliliter. Maintain at 4.0 degree Celsius while performing dilutions. +6. Measure baseline absorbance of culture (day 2) of `culture (day 2)` at 600.0 nanometer. +7. Provision 16 x 50 ml conical tubes to contain `back-diluted culture` The conical tube should be opaque, amber-colored, or covered with foil. +8. Back-dilute each of 16 `culture (day 2)` samples to a target OD of 0.02 using LB Broth+chloramphenicol as diluent to a final volume of 12.0 milliliter. Maintain at 4.0 degree Celsius while performing dilutions. + +![](/Users/bbartley/Dev/git/sd2/labop/fig1_cell_calibration.png) + + +9. Provision 16 x 1.5 mL microfuge tubes to contain `cultures (0 hr timepoint)` +10. Provision a 96 well microplate to contain `plate 1` +11. Hold `cultures (0 hr timepoint)` at 4.0 degree Celsius. This will prevent cell growth while transferring samples. +12. Hold `plate 1` at 4.0 degree Celsius. +13. Transfer 1.0 milliliter of each of 16 `back-diluted culture` samples to 1.5 mL microfuge tube containers to contain a total of 16 `cultures (0 hr timepoint)` samples. Maintain at 4.0 degree Celsius during transfer. +14. Transfer 100.0 microliter of each `cultures (0 hr timepoint)` sample to 96 well microplate `plate 1` in the wells indicated in the plate layout. + Maintain at 4.0 degree Celsius during transfer. +15. Transfer 100.0 microliter of `LB Broth+chloramphenicol` sample to wells A1:H1, A10:H10, A12:H12 of 96 well microplate `plate 1`. Maintain at 4.0 degree Celsius during transfer. These samples are blanks. + +![](/Users/bbartley/Dev/git/sd2/labop/fig2_cell_calibration.png) + + +16. Measure 0 hr absorbance timepoint of `plate 1` at 600.0 nanometer. +17. Measure 0 hr fluorescence timepoint of `plate 1` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass +18. Cover `plate 1` samples in 96 well microplate with your choice of material to prevent evaporation. +19. Incubate all `back-diluted culture` samples for 6.0 hour at 37.0 degree Celsius at 220.0. +20. Incubate all `plate 1` samples for 6.0 hour at 37.0 degree Celsius at 220.0. +21. Hold all `cultures (0 hr timepoint)` samples at 4.0 degree Celsius. This will inhibit cell growth during the subsequent pipetting steps. +22. Hold all `plate 1` samples at 4.0 degree Celsius. This will inhibit cell growth during the subsequent pipetting steps. +23. Provision 16 x 1.5 mL microfuge tubes to contain `6hr timepoint` +24. Provision a 96 well microplate to contain `plate 2` +25. Hold `6hr timepoint` at 4.0 degree Celsius. This will prevent cell growth while transferring samples. +26. Hold `plate 2` at 4.0 degree Celsius. +27. Transfer 1.0 milliliter of each of 16 `back-diluted culture` samples to 1.5 mL microfuge tube containers to contain a total of 16 `6hr timepoint` samples. Maintain at 4.0 degree Celsius during transfer. +28. Transfer 100.0 microliter of each `6hr timepoint` sample to 96 well microplate `plate 2` in the wells indicated in the plate layout. + Maintain at 4.0 degree Celsius during transfer. +29. Transfer 100.0 microliter of `LB Broth+chloramphenicol` sample to wells A1:H1, A10:H10, A12:H12 of 96 well microplate `plate 2`. Maintain at 4.0 degree Celsius during transfer. These are the blanks. +30. Perform a brief centrifugation on 96 well microplate containing `plate 1` samples. This will prevent cross-contamination when removing the seal. +31. Remove the seal from 96 well microplate containing `plate 1` samples. +32. Measure 6 hr absorbance timepoint of `plate 1` at 600.0 nanometer. +33. Measure 6 hr fluorescence timepoint of `plate 1` with excitation wavelength of 485.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass +34. Measure 6 hr absorbance timepoint of `plate 2` at 600.0 nanometer. +35. Measure 6 hr fluorescence timepoint of `plate 2` with excitation wavelength of 485.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass +36. Import data for `baseline absorbance of culture (day 2) measurements of culture (day 2)`, `0 hr absorbance timepoint measurements of plate 1`, `0 hr fluorescence timepoint measurements of plate 1`, `6 hr absorbance timepoint measurements of plate 1`, `6 hr fluorescence timepoint measurements of plate 1`, `6 hr absorbance timepoint measurements of plate 2`, `6 hr fluorescence timepoint measurements of plate 2` into provided Excel file. +--- +Timestamp: 2022-04-24 22:42:28.454856--- +Protocol version: 1.0b diff --git a/examples/protocols/iGEM/artifacts/particle_calibration.md b/examples/protocols/iGEM/artifacts/particle_calibration.md new file mode 100644 index 00000000..7b03dae1 --- /dev/null +++ b/examples/protocols/iGEM/artifacts/particle_calibration.md @@ -0,0 +1,69 @@ +# Multicolor fluorescence per bacterial particle calibration + +## Description: +Plate readers report fluorescence values in arbitrary units that vary widely from instrument to instrument. Therefore absolute fluorescence values cannot be directly compared from one instrument to another. In order to compare fluorescence output of biological devices, it is necessary to create a standard fluorescence curve. This variant of the protocol uses two replicates of three colors of dye, plus beads. +Adapted from [https://dx.doi.org/10.17504/protocols.io.bht7j6rn](https://dx.doi.org/10.17504/protocols.io.bht7j6r) and [https://dx.doi.org/10.17504/protocols.io.6zrhf56](https://dx.doi.org/10.17504/protocols.io.6zrhf56) + + +## Protocol Materials: +* [Water, sterile-filtered, BioReagent, suitable for cell culture](https://identifiers.org/pubchem.substance:24901740) +* [NanoCym 950 nm monodisperse silica nanoparticles](https://nanocym.com/wp-content/uploads/2018/07/NanoCym-All-Datasheets-.pdf) +* [Phosphate Buffered Saline](https://pubchem.ncbi.nlm.nih.gov/substance/329753341) +* [Fluorescein](https://pubchem.ncbi.nlm.nih.gov/substance/329753341) +* [Cascade Blue](https://pubchem.ncbi.nlm.nih.gov/substance/329753341) +* [Sulforhodamine](https://pubchem.ncbi.nlm.nih.gov/substance/329753341) + + +## Protocol Inputs: + + +## Protocol Outputs: +* `fluorescein and bead fluorescence measurements of calibration plate` +* `sulforhodamine 101 fluorescence measurements of calibration plate` +* `cascade blue fluorescence measurements of calibration plate` +* `absorbance measurements of calibration plate` + + +## Steps +1. Provision the stock reagent container containing `Fluorescein calibrant` +2. Provision the stock reagent container containing `Sulforhodamine 101 calibrant` +3. Provision the stock reagent container containing `Cascade blue calibrant` +4. Provision the stock reagent container containing `NanoCym 950 nm microspheres` +5. Transfer 1.0 milliliter of `Phosphate Buffered Saline` sample to stock reagent container `Fluorescein calibrant`. The reconsituted fluorescein calibrant will have a final concentration of 10 uM in PBS +6. Vortex Fluorescein calibrant +7. Transfer 1.0 milliliter of `Phosphate Buffered Saline` sample to stock reagent container `Sulforhodamine 101 calibrant`. The reconstituted sulforhodamine standard will have a final concentration of 2 uM in PBS +8. Vortex Sulforhodamine 101 calibrant +9. Transfer 1.0 milliliter of `Water, sterile-filtered, BioReagent, suitable for cell culture` sample to stock reagent container `Cascade blue calibrant`. The reconstituted cascade blue calibrant will have a final concentration of 10 uM in ddH2O. +10. Vortex Cascade blue calibrant +11. Transfer 1.0 milliliter of `Water, sterile-filtered, BioReagent, suitable for cell culture` sample to stock reagent container `NanoCym 950 nm microspheres`. The resuspended microspheres will have a final concentration of 3e9 microspheres/mL in ddH20. +12. Vortex NanoCym 950 nm microspheres +13. Provision a 96 well microplate to contain `calibration plate` +14. Transfer 100.0 microliter of `Phosphate Buffered Saline` sample to wells A12:D12 of 96 well microplate `calibration plate`. These are blanks. +15. Transfer 100.0 microliter of `Water, sterile-filtered, BioReagent, suitable for cell culture` sample to wells E12:H12 of 96 well microplate `calibration plate`. These are blanks. +16. Transfer 200.0 microliter of `Fluorescein calibrant` sample to wells A1 of 96 well microplate `calibration plate`. +17. Transfer 200.0 microliter of `Fluorescein calibrant` sample to wells B1 of 96 well microplate `calibration plate`. +18. Transfer 200.0 microliter of `Sulforhodamine 101 calibrant` sample to wells C1 of 96 well microplate `calibration plate`. +19. Transfer 200.0 microliter of `Sulforhodamine 101 calibrant` sample to wells D1 of 96 well microplate `calibration plate`. +20. Transfer 200.0 microliter of `Cascade blue calibrant` sample to wells E1 of 96 well microplate `calibration plate`. +21. Transfer 200.0 microliter of `Cascade blue calibrant` sample to wells F1 of 96 well microplate `calibration plate`. +22. Transfer 200.0 microliter of `NanoCym 950 nm microspheres` sample to wells G1 of 96 well microplate `calibration plate`. +23. Transfer 200.0 microliter of `NanoCym 950 nm microspheres` sample to wells H1 of 96 well microplate `calibration plate`. +24. Perform a series of 10 2-fold dilutions on `Fluorescein calibrant` using `Phosphate Buffered Saline` as diluent to a final volume of 200.0 microliter in wells A1:A11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. +25. Perform a series of 10 2-fold dilutions on `Fluorescein calibrant` using `Phosphate Buffered Saline` as diluent to a final volume of 200.0 microliter in wells B1:B11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. +26. Perform a series of 10 2-fold dilutions on `Sulforhodamine 101 calibrant` using `Phosphate Buffered Saline` as diluent to a final volume of 200.0 microliter in wells C1:C11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. +27. Perform a series of 10 2-fold dilutions on `Sulforhodamine 101 calibrant` using `Phosphate Buffered Saline` as diluent to a final volume of 200.0 microliter in wells D1:D11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. +28. Perform a series of 10 2-fold dilutions on `Cascade blue calibrant` using `Water, sterile-filtered, BioReagent, suitable for cell culture` as diluent to a final volume of 200.0 microliter in wells E1:E11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. +29. Perform a series of 10 2-fold dilutions on `Cascade blue calibrant` using `Water, sterile-filtered, BioReagent, suitable for cell culture` as diluent to a final volume of 200.0 microliter in wells F1:F11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. +30. Perform a series of 10 2-fold dilutions on `NanoCym 950 nm microspheres` using `Water, sterile-filtered, BioReagent, suitable for cell culture` as diluent to a final volume of 200.0 microliter in wells G1:G11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. +31. Perform a series of 10 2-fold dilutions on `NanoCym 950 nm microspheres` using `Water, sterile-filtered, BioReagent, suitable for cell culture` as diluent to a final volume of 200.0 microliter in wells H1:H11 of 96 well microplate `calibration plate`. For each transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously. +32. Discard 100.0 microliter from wells A11:H11 of 96 well microplate `calibration plate`. This step ensures that all wells contain an equivalent volume. Be sure to change pipette tips for every well to avoid cross-contamination +33. Transfer 100.0 microliter of `Phosphate Buffered Saline` sample to wells A1:D12 of 96 well microplate `calibration plate`. This will bring all wells to volume 200 microliter. +34. Transfer 100.0 microliter of `Water, sterile-filtered, BioReagent, suitable for cell culture` sample to wells E1:H12 of 96 well microplate `calibration plate`. This will bring all wells to volume 200 microliter. +35. Measure fluorescein and bead fluorescence of `calibration plate` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass +36. Measure sulforhodamine 101 fluorescence of `calibration plate` with excitation wavelength of 561.0 nanometer and emission filter of 610.0 nanometer and 20.0 nanometer bandpass +37. Measure cascade blue fluorescence of `calibration plate` with excitation wavelength of 405.0 nanometer and emission filter of 450.0 nanometer and 50.0 nanometer bandpass +38. Measure absorbance of `calibration plate` at 600.0 nanometer. +39. Import data for `fluorescein and bead fluorescence measurements of calibration plate`, `sulforhodamine 101 fluorescence measurements of calibration plate`, `cascade blue fluorescence measurements of calibration plate`, `absorbance measurements of calibration plate` into provided Excel file. +--- +Timestamp: 2022-04-24 22:14:30.132906--- +Protocol version: 1.0b \ No newline at end of file diff --git a/examples/protocols/iGEM/challenging-interlab-growth-curve.py b/examples/protocols/iGEM/challenging-interlab-growth-curve.py new file mode 100644 index 00000000..a68db89b --- /dev/null +++ b/examples/protocols/iGEM/challenging-interlab-growth-curve.py @@ -0,0 +1,680 @@ +""" +http://2018.igem.org/wiki/images/0/09/2018_InterLab_Plate_Reader_Protocol.pdf +""" +import json +from urllib.parse import quote + +import sbol3 +from tyto import OM + +import labop +import uml +from labop.execution_engine import ExecutionEngine +from labop_convert.markdown.markdown_specialization import MarkdownSpecialization + +doc = sbol3.Document() +sbol3.set_namespace("http://igem.org/engineering/") + +############################################# +# Import the primitive libraries +print("Importing libraries") +labop.import_library("liquid_handling") +print("... Imported liquid handling") +labop.import_library("plate_handling") +# print('... Imported plate handling') +labop.import_library("spectrophotometry") +print("... Imported spectrophotometry") +labop.import_library("sample_arrays") +print("... Imported sample arrays") +labop.import_library("culturing") +############################################# + + +# create the materials to be provisioned +dh5alpha = sbol3.Component( + "dh5alpha", "https://identifiers.org/pubchem.substance:24901740" +) +dh5alpha.name = "_E. coli_ DH5 alpha" +doc.add(dh5alpha) + +lb_cam = sbol3.Component("lb_cam", "https://identifiers.org/pubchem.substance:24901740") +lb_cam.name = "LB Broth+chloramphenicol" +doc.add(lb_cam) + +chloramphenicol = sbol3.Component( + "chloramphenicol", "https://identifiers.org/pubchem.substance:24901740" +) +chloramphenicol.name = "chloramphenicol" +doc.add(chloramphenicol) + + +neg_control_plasmid = sbol3.Component("neg_control_plasmid", sbol3.SBO_DNA) +neg_control_plasmid.name = "Negative control" +neg_control_plasmid.description = "BBa_R0040 Kit Plate 7 Well 2D" + +pos_control_plasmid = sbol3.Component("pos_control_plasmid", sbol3.SBO_DNA) +pos_control_plasmid.name = "Positive control" +pos_control_plasmid.description = "BBa_I20270 Kit Plate 7 Well 2B" + +test_device1 = sbol3.Component("test_device1", sbol3.SBO_DNA) +test_device1.name = "Test Device 1" +test_device1.description = "BBa_J364000 Kit Plate 7 Well 2F" + +test_device2 = sbol3.Component("test_device2", sbol3.SBO_DNA) +test_device2.name = "Test Device 2" +test_device2.description = "BBa_J364001 Kit Plate 7 Well 2H" + +test_device3 = sbol3.Component("test_device3", sbol3.SBO_DNA) +test_device3.name = "Test Device 3" +test_device3.description = "BBa_J364002 Kit Plate 7 Well 2J" + +test_device4 = sbol3.Component("test_device4", sbol3.SBO_DNA) +test_device4.name = "Test Device 4" +test_device4.description = "BBa_J364007 Kit Plate 7 Well 2L" + +test_device5 = sbol3.Component("test_device5", sbol3.SBO_DNA) +test_device5.name = "Test Device 5" +test_device5.description = "BBa_J364008 Kit Plate 7 Well 2N" + +test_device6 = sbol3.Component("test_device6", sbol3.SBO_DNA) +test_device6.name = "Test Device 6" +test_device6.description = "BBa_J364009 Kit Plate 7 Well 2P" + +doc.add(neg_control_plasmid) +doc.add(pos_control_plasmid) +doc.add(test_device1) +doc.add(test_device2) +doc.add(test_device3) +doc.add(test_device4) +doc.add(test_device5) +doc.add(test_device6) + + +activity = labop.Protocol("interlab") +activity.name = "Cell measurement protocol (Challenging)" +activity.description = """ +This is a more challenging version of the cell calibration protocol for time-interval measurement. At each time point 0-hour, 2-hour, 4-hour and 6-hour, you will take a sample from each of the eight devices, two colonies per device, three falcon tubes per colony → total 48 tubes.""" +activity.version = "1.0b" +doc.add(activity) + +plasmids = [ + neg_control_plasmid, + pos_control_plasmid, + test_device1, + test_device2, + test_device3, + test_device4, + test_device5, + test_device6, +] + +# Day 1: Transformation +transformation = activity.primitive_step( + f"Transform", host=dh5alpha, dna=plasmids, selection_medium=lb_cam +) + +# Day 2: Pick colonies and culture overnight +culture_container_day1 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + name=f"culture (day 1)", + queryString="cont:CultureTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +overnight_culture = activity.primitive_step( + "Culture", + inoculum=transformation.output_pin("transformants"), + replicates=2, + growth_medium=lb_cam, + volume=sbol3.Measure(5, OM.millilitre), # Actually 5-10 ml in the written protocol + duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours + orbital_shake_speed=sbol3.Measure(220, None), # No unit for RPM or inverse minutes + temperature=sbol3.Measure(37, OM.degree_Celsius), + container=culture_container_day1.output_pin("samples"), +) + +# Day 3 culture +culture_container_day2 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + name=f"culture (day 2)", + queryString="cont:CultureTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + + +back_dilution = activity.primitive_step( + "Dilute", + source=culture_container_day1.output_pin("samples"), + destination=culture_container_day2.output_pin("samples"), + replicates=2, + diluent=lb_cam, + amount=sbol3.Measure(5.0, OM.millilitre), + dilution_factor=uml.LiteralInteger(value=10), +) + +baseline_absorbance = activity.primitive_step( + "MeasureAbsorbance", + samples=culture_container_day2.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) +baseline_absorbance.name = "baseline absorbance" + +parent_conical_tube = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + name=f"back-diluted culture", + queryString="cont:50mlConicalTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +dilution = activity.primitive_step( + "DiluteToTargetOD", + source=culture_container_day2.output_pin("samples"), + destination=parent_conical_tube.output_pin("samples"), + diluent=lb_cam, + amount=sbol3.Measure(40, OM.millilitre), + target_od=sbol3.Measure(0.2, None), +) # Dilute to a target OD of 0.2, opaque container +dilution.description = ( + "(Reliability of the dilution upon Abs600 measurement: should stay between 0.1-0.9)" +) + +# Further subdivision into triplicates +conical_tubes = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + replicates=3, + specification=labop.ContainerSpec( + name=f"replicate subcultures", + queryString="cont:50mlConicalTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) +conical_tubes.description = ( + "The conical tubes should be opaque, amber-colored, or covered with foil." +) + +transfer = activity.primitive_step( + "Transfer", + source=parent_conical_tube.output_pin("samples"), + replicates=3, + destination=conical_tubes.output_pin("samples"), + amount=sbol3.Measure(12, OM.milliliter), +) + +embedded_image = activity.primitive_step( + "EmbeddedImage", + image="/Users/bbartley/Dev/git/sd2/labop/fig3_cell_calibration.png", +) + + +# Transfer cultures to a microplate baseline measurement and outgrowth +timepoint_0hrs = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids) * 3, + specification=labop.ContainerSpec( + name="cultures (0 hr timepoint)", + queryString="cont:MicrofugeTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) +# Hold on ice +hold = activity.primitive_step( + "Hold", + location=timepoint_0hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) +hold.description = "This will prevent cell growth while transferring samples." + +transfer = activity.primitive_step( + "Transfer", + source=conical_tubes.output_pin("samples"), + destination=timepoint_0hrs.output_pin("samples"), + amount=sbol3.Measure(1, OM.milliliter), +) + +# Plate cultures +plate1 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + name="plate 1", + queryString="cont:Plate96Well", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) +plate2 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + name="plate 2", + queryString="cont:Plate96Well", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) +plate3 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + name="plate 3", + queryString="cont:Plate96Well", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + + +hold = activity.primitive_step( + "Hold", + location=plate1.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) + +hold = activity.primitive_step( + "Hold", + location=plate2.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) + +hold = activity.primitive_step( + "Hold", + location=plate3.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) + + +transfer_map = quote( + json.dumps( + { + "1": "A2:D2", + "2": "E2:H2", + "3": "A3:D3", + "4": "E3:H3", + "5": "A4:D4", + "6": "E4:H4", + "7": "A5:D5", + "8": "E5:H5", + "9": "A7:D7", + "10": "E7:H7", + "11": "A8:D8", + "12": "E8:H8", + "13": "A9:D9", + "14": "E9:H9", + "15": "A10:D10", + "16": "E10:H10", + "17": "A2:D2", + "18": "E2:H2", + "19": "A3:D3", + "20": "E3:H3", + "21": "A4:D4", + "22": "E4:H4", + "23": "A5:D5", + "24": "E5:H5", + "25": "A7:D7", + "26": "E7:H7", + "27": "A8:D8", + "28": "E8:H8", + "29": "A9:D9", + "30": "E9:H9", + "31": "A10:D10", + "32": "E10:H10", + "33": "A2:D2", + "34": "E2:H2", + "35": "A3:D3", + "36": "E3:H3", + "37": "A4:D4", + "38": "E4:H4", + "39": "A5:D5", + "40": "E5:H5", + "41": "A7:D7", + "42": "E7:H7", + "43": "A8:D8", + "44": "E8:H8", + "45": "A9:D9", + "46": "E9:H9", + "47": "A10:D10", + "48": "E10:H10", + } + ) +) + + +plan = labop.SampleData(values=transfer_map) +transfer = activity.primitive_step( + "TransferByMap", + source=timepoint_0hrs.output_pin("samples"), + destination=plate1.output_pin("samples"), + amount=sbol3.Measure(100, OM.microliter), + plan=plan, +) +transfer.description = "See the plate layout below." + +plan = labop.SampleData(values=transfer_map) + +transfer = activity.primitive_step( + "TransferByMap", + source=timepoint_0hrs.output_pin("samples"), + destination=plate2.output_pin("samples"), + amount=sbol3.Measure(100, OM.microliter), + plan=plan, +) +plan = labop.SampleData(values=transfer_map) + +transfer = activity.primitive_step( + "TransferByMap", + source=timepoint_0hrs.output_pin("samples"), + destination=plate3.output_pin("samples"), + amount=sbol3.Measure(100, OM.microliter), + plan=plan, +) + + +plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate1.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + amount=sbol3.Measure(100, OM.microliter), +) +plate_blanks.description = "These samples are blanks." + +embedded_image = activity.primitive_step( + "EmbeddedImage", + image="/Users/bbartley/Dev/git/sd2/labop/fig2_cell_calibration.png", +) + + +# Possibly display map here +absorbance_0hrs_plate1 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate1.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) +absorbance_0hrs_plate1.name = "0 hr absorbance timepoint" + +fluorescence_0hrs_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), +) +fluorescence_0hrs_plate1.name = "0 hr fluorescence timepoint" + +absorbance_0hrs_plate2 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate2.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) +absorbance_0hrs_plate2.name = "0 hr absorbance timepoint" +fluorescence_0hrs_plate2 = activity.primitive_step( + "MeasureFluorescence", + samples=plate2.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), +) +fluorescence_0hrs_plate2.name = "0 hr fluorescence timepoint" + +absorbance_0hrs_plate3 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate3.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) +absorbance_0hrs_plate3.name = "0 hr absorbance timepoint" +fluorescence_0hrs_plate3 = activity.primitive_step( + "MeasureFluorescence", + samples=plate3.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), +) +fluorescence_0hrs_plate3.name = "0 hr fluorescence timepoint" + +## Cover plate +seal = activity.primitive_step( + "EvaporativeSeal", location=plate1.output_pin("samples"), type="foo" +) +seal = activity.primitive_step( + "EvaporativeSeal", location=plate2.output_pin("samples"), type="foo" +) +seal = activity.primitive_step( + "EvaporativeSeal", location=plate3.output_pin("samples"), type="foo" +) + + +## Begin outgrowth +incubate = activity.primitive_step( + "Incubate", + location=conical_tubes.output_pin("samples"), + duration=sbol3.Measure(2, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, None), +) + +incubate = activity.primitive_step( + "Incubate", + location=plate1.output_pin("samples"), + duration=sbol3.Measure(2, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, None), +) +incubate = activity.primitive_step( + "Incubate", + location=plate2.output_pin("samples"), + duration=sbol3.Measure(4, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, None), +) +incubate = activity.primitive_step( + "Incubate", + location=plate1.output_pin("samples"), + duration=sbol3.Measure(6, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, None), +) + +# Hold on ice to inhibit cell growth +hold = activity.primitive_step( + "Hold", + location=conical_tubes.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) +hold.description = ( + "This will inhibit cell growth during the subsequent pipetting steps." +) + +hold = activity.primitive_step( + "Hold", + location=plate1.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) +hold.description = ( + "This will inhibit cell growth during the subsequent pipetting steps." +) + +# Transfer cultures to a microplate baseline measurement and outgrowth +timepoint_2hrs = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids) * 3, + specification=labop.ContainerSpec( + name="cultures (0 hr timepoint)", + queryString="cont:MicrofugeTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +# Hold on ice +hold = activity.primitive_step( + "Hold", + location=timepoint_2hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) +hold.description = "This will prevent cell growth while transferring samples." + +transfer = activity.primitive_step( + "Transfer", + source=conical_tubes.output_pin("samples"), + destination=timepoint_2hrs.output_pin("samples"), + amount=sbol3.Measure(1, OM.milliliter), +) + +plate4 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + name="plate 4", + queryString="cont:Plate96Well", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +plan = labop.SampleData(values=transfer_map) +transfer = activity.primitive_step( + "TransferByMap", + source=timepoint_2hrs.output_pin("samples"), + destination=plate4.output_pin("samples"), + amount=sbol3.Measure(100, OM.microliter), + plan=plan, +) +# Plate the blanks +plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate4.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + amount=sbol3.Measure(100, OM.microliter), +) +plate_blanks.description = "These are the blanks." + + +quick_spin = activity.primitive_step("QuickSpin", location=plate1.output_pin("samples")) +quick_spin.description = "This will prevent cross-contamination when removing the seal." + +remove_seal = activity.primitive_step("Unseal", location=plate1.output_pin("samples")) + +absorbance_2hrs_plate1 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate1.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) +absorbance_2hrs_plate1.name = "2 hr absorbance timepoint" +fluorescence_2hrs_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), +) +fluorescence_2hrs_plate1.name = "2 hr fluorescence timepoint" + +absorbance_2hrs_plate4 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate4.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) +absorbance_2hrs_plate4.name = "2 hr absorbance timepoint" +fluorescence_2hrs_plate4 = activity.primitive_step( + "MeasureFluorescence", + samples=plate4.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), +) +fluorescence_2hrs_plate4.name = "2 hr fluorescence timepoint" + +# endpoint_fluorescence_plate1 = protocol.primitive_step('MeasureFluorescence', +# samples=plate4.output_pin('samples'), +# excitationWavelength=sbol3.Measure(485, OM.nanometer), +# emissionWavelength=sbol3.Measure(530, OM.nanometer), +# emissionBandpassWidth=sbol3.Measure(30, OM.nanometer)) +# +# endpoint_absorbance_plate2 = protocol.primitive_step('MeasureAbsorbance', +# samples=plate2.output_pin('samples'), +# wavelength=sbol3.Measure(600, OM.nanometer)) +# +# endpoint_fluorescence_plate2 = protocol.primitive_step('MeasureFluorescence', +# samples=plate2.output_pin('samples'), +# excitationWavelength=sbol3.Measure(485, OM.nanometer), +# emissionWavelength=sbol3.Measure(530, OM.nanometer), +# emissionBandpassWidth=sbol3.Measure(30, OM.nanometer)) +# +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=baseline_absorbance.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_0hrs_plate1.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_0hrs_plate2.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_0hrs_plate3.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_0hrs_plate1.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_0hrs_plate2.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_0hrs_plate3.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_2hrs_plate1.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_2hrs_plate4.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_2hrs_plate1.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_2hrs_plate4.output_pin("measurements"), +) + + +# protocol.designate_output('measurements', 'http://bioprotocols.org/labop#SampleData', source=absorbance_plate1.output_pin('measurements')) +# protocol.designate_output('measurements', 'http://bioprotocols.org/labop#SampleData', source=fluorescence_plate1.output_pin('measurements')) +# +# protocol.designate_output('measurements', 'http://bioprotocols.org/labop#SampleData', source=endpoint_absorbance_plate1.output_pin('measurements')) +# protocol.designate_output('measurements', 'http://bioprotocols.org/labop#SampleData', source=endpoint_fluorescence_plate1.output_pin('measurements')) +# +# protocol.designate_output('measurements', 'http://bioprotocols.org/labop#SampleData', source=endpoint_absorbance_plate2.output_pin('measurements')) +# protocol.designate_output('measurements', 'http://bioprotocols.org/labop#SampleData', source=endpoint_fluorescence_plate2.output_pin('measurements')) +# + +agent = sbol3.Agent("test_agent") +ee = ExecutionEngine(specializations=[MarkdownSpecialization("test_LUDOX_markdown.md")]) +execution = ee.execute(activity, agent, id="test_execution", parameter_values=[]) +print(ee.specializations[0].markdown) +ee.specializations[0].markdown = ee.specializations[0].markdown.replace( + "`_E. coli_", "_`E. coli`_ `" +) +with open("example.md", "w", encoding="utf-8") as f: + f.write(ee.specializations[0].markdown) diff --git a/examples/protocols/iGEM/interlab-growth-curve.ipynb b/examples/protocols/iGEM/interlab-growth-curve.ipynb new file mode 100644 index 00000000..e1e1a334 --- /dev/null +++ b/examples/protocols/iGEM/interlab-growth-curve.ipynb @@ -0,0 +1,583 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "db403f18", + "metadata": {}, + "outputs": [], + "source": [ + "'''\n", + "http://2018.igem.org/wiki/images/0/09/2018_InterLab_Plate_Reader_Protocol.pdf\n", + "'''\n", + "import labop\n", + "import uml\n", + "import sbol3\n", + "from tyto import OM\n", + "from labop.execution_engine import ExecutionEngine\n", + "from labop_convert.markdown.markdown_specialization import MarkdownSpecialization\n", + "\n", + "\n", + "doc = sbol3.Document()\n", + "sbol3.set_namespace('http://igem.org/engineering/')\n", + "\n", + "#############################################\n", + "# Import the primitive libraries\n", + "print('Importing libraries')\n", + "labop.import_library('liquid_handling')\n", + "print('... Imported liquid handling')\n", + "labop.import_library('plate_handling')\n", + "# print('... Imported plate handling')\n", + "labop.import_library('spectrophotometry')\n", + "print('... Imported spectrophotometry')\n", + "labop.import_library('sample_arrays')\n", + "print('... Imported sample arrays')\n", + "labop.import_library('culturing')\n", + "#############################################\n", + "\n", + "\n", + "# create the materials to be provisioned\n", + "dh5alpha = sbol3.Component('dh5alpha', 'https://identifiers.org/pubchem.substance:24901740')\n", + "dh5alpha.name = '_E. coli_ DH5 alpha' \n", + "doc.add(dh5alpha)\n", + "\n", + "lb_cam = sbol3.Component('lb_cam', 'https://identifiers.org/pubchem.substance:24901740')\n", + "lb_cam.name = 'LB Broth+chloramphenicol' \n", + "doc.add(lb_cam)\n", + "\n", + "chloramphenicol = sbol3.Component('chloramphenicol', 'https://identifiers.org/pubchem.substance:24901740')\n", + "chloramphenicol.name = 'chloramphenicol' \n", + "doc.add(chloramphenicol)\n", + "\n", + "\n", + "neg_control_plasmid = sbol3.Component('neg_control_plasmid', sbol3.SBO_DNA)\n", + "neg_control_plasmid.name = 'Negative control'\n", + "neg_control_plasmid.description = 'BBa_R0040 Kit Plate 7 Well 2D'\n", + "\n", + "pos_control_plasmid = sbol3.Component('pos_control_plasmid', sbol3.SBO_DNA)\n", + "pos_control_plasmid.name = 'Positive control'\n", + "pos_control_plasmid.description = 'BBa_I20270 Kit Plate 7 Well 2B'\n", + "\n", + "test_device1 = sbol3.Component('test_device1', sbol3.SBO_DNA)\n", + "test_device1.name = 'Test Device 1'\n", + "test_device1.description = 'BBa_J364000 Kit Plate 7 Well 2F'\n", + "\n", + "test_device2 = sbol3.Component('test_device2', sbol3.SBO_DNA)\n", + "test_device2.name = 'Test Device 2'\n", + "test_device2.description = 'BBa_J364001 Kit Plate 7 Well 2H'\n", + "\n", + "test_device3 = sbol3.Component('test_device3', sbol3.SBO_DNA)\n", + "test_device3.name = 'Test Device 3'\n", + "test_device3.description = 'BBa_J364002 Kit Plate 7 Well 2J'\n", + "\n", + "test_device4 = sbol3.Component('test_device4', sbol3.SBO_DNA)\n", + "test_device4.name = 'Test Device 4'\n", + "test_device4.description = 'BBa_J364007 Kit Plate 7 Well 2L'\n", + "\n", + "test_device5 = sbol3.Component('test_device5', sbol3.SBO_DNA)\n", + "test_device5.name = 'Test Device 5'\n", + "test_device5.description = 'BBa_J364008 Kit Plate 7 Well 2N'\n", + "\n", + "test_device6 = sbol3.Component('test_device6', sbol3.SBO_DNA)\n", + "test_device6.name = 'Test Device 6'\n", + "test_device6.description = 'BBa_J364009 Kit Plate 7 Well 2P'\n", + "\n", + "doc.add(neg_control_plasmid)\n", + "doc.add(pos_control_plasmid)\n", + "doc.add(test_device1)\n", + "doc.add(test_device2)\n", + "doc.add(test_device3)\n", + "doc.add(test_device4)\n", + "doc.add(test_device5)\n", + "doc.add(test_device6)\n", + "\n", + "\n", + "protocol = labop.Protocol('interlab')\n", + "protocol.name = 'Cell measurement protocol'\n", + "protocol.description = '''Prior to performing the cell measurements you should perform all three of\n", + "the calibration measurements. Please do not proceed unless you have\n", + "completed the three calibration protocols.\n", + "Completion of the calibrations will ensure that you understand the measurement process and that\n", + "you can take the cell measurements under the same conditions. For the sake of consistency and\n", + "reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to\n", + "this strain, you can request streaks of the transformed devices from another team near you, and this\n", + "can count as a collaboration as long as it is appropriately documented on both teams' wikis. If you\n", + "are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study\n", + "by contacting the Measurement Committee (measurement at igem dot org) to discuss your\n", + "situation.\n", + "For all of these cell measurements, you must use the same plates and volumes that you used in your\n", + "calibration protocol. You must also use the same settings (e.g., filters or excitation and emission\n", + "wavelengths) that you used in your calibration measurements. If you do not use the same plates,\n", + "volumes, and settings, the measurements will not be valid.'''\n", + "doc.add(protocol)\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "54fdacf7", + "metadata": {}, + "outputs": [], + "source": [ + "plasmids = [neg_control_plasmid, pos_control_plasmid, test_device1, test_device2, test_device3, test_device4, test_device5, test_device6]\n", + "\n", + "# Day 1: Transformation\n", + "transformation = protocol.primitive_step(f'Transform',\n", + " host=dh5alpha,\n", + " dna=plasmids,\n", + " selection_medium=lb_cam)\n", + " \n", + "# Day 2: Pick colonies and culture overnight\n", + "culture_container_day1 = protocol.primitive_step('ContainerSet', \n", + " quantity=uml.LiteralInteger(value=len(plasmids)),\n", + " specification=labop.ContainerSpec(name=f'culture (day 1)',\n", + " queryString='cont:CultureTube', \n", + " prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'}))\n", + " \n", + "overnight_culture = protocol.primitive_step('Culture',\n", + " inoculum=transformation.output_pin('transformants'),\n", + " growth_medium=lb_cam,\n", + " volume=sbol3.Measure(5, OM.millilitre), # Actually 5-10 ml in the written protocol\n", + " duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours\n", + " orbital_shake_speed=sbol3.Measure(220, None), # No unit for RPM or inverse minutes\n", + " temperature=sbol3.Measure(37, OM.degree_Celsius),\n", + " container=culture_container_day1.output_pin('samples'))\n", + "\n", + "# Day 3 culture\n", + "culture_container_day2 = protocol.primitive_step('ContainerSet', \n", + " specification=labop.ContainerSpec(name=f'culture (day 2)',\n", + " queryString='cont:CultureTube', \n", + " prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'}))\n", + "\n", + "back_dilution = protocol.primitive_step('Dilute',\n", + " source=culture_container_day1.output_pin('samples'),\n", + " destination=culture_container_day2.output_pin('samples'),\n", + " diluent=lb_cam,\n", + " amount=sbol3.Measure(5.0, OM.millilitre),\n", + " dilution_factor=uml.LiteralInteger(value=10))\n", + "\n", + "# absorbance = protocol.primitive_step('MeasureAbsorbance',\n", + "# samples=culture_container_day2.output_pin('samples'),\n", + "# wavelength=sbol3.Measure(600, OM.nanometer))\n", + "\n", + "# conical_tube = protocol.primitive_step('EmptyContainer', \n", + "# specification=labop.ContainerSpec(name=f'{plasmid.name} culture',\n", + "# queryString='cont:ConicalTube', \n", + "# prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'})) # Should be opaque\n", + "\n", + "# dilution = protocol.primitive_step('DiluteToTargetOD',\n", + "# source=culture_container_day2.output_pin('samples'),\n", + "# destination=conical_tube.output_pin('samples'),\n", + "# diluent=lb_cam,\n", + "# amount=sbol3.Measure(12, OM.millilitre),\n", + "# target_od=sbol3.Measure(0.2, None)) # Dilute to a target OD of 0.2, opaque container\n", + "\n", + "# microfuge_tube_0hrs = protocol.primitive_step('EmptyContainer', \n", + "# specification=labop.ContainerSpec(name=f'{plasmid.name} culture (0 hrs)',\n", + "# queryString='cont:MicrofugeTube', \n", + "# prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'}))\n", + "\n", + "# transfer = protocol.primitive_step('Transfer',\n", + "# source=conical_tube.output_pin('samples'),\n", + "# destination=microfuge_tube_0hrs.output_pin('samples'),\n", + "# amount=sbol3.Measure(0.5, OM.milliliter))\n", + "\n", + "# hold = protocol.primitive_step('Hold',\n", + "# location=microfuge_tube_0hrs.output_pin('samples'),\n", + "# temperature=sbol3.Measure(4, OM.degree_Celsius))\n", + "\n", + "# incubate = protocol.primitive_step('Incubate',\n", + "# location=conical_tube.output_pin('samples'),\n", + "# duration=sbol3.Measure(6, OM.hour),\n", + "# temperature=sbol3.Measure(37, OM.degree_Celsius),\n", + "# shakingFrequency=sbol3.Measure(220, None))\n", + "\n", + "# microfuge_tube_6hrs = protocol.primitive_step('EmptyContainer', \n", + "# specification=labop.ContainerSpec(name=f'{plasmid.name} culture (6 hrs)',\n", + "# queryString='cont:MicrofugeTube', \n", + "# prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'}))\n", + "\n", + "\n", + "# transfer = protocol.primitive_step('Transfer',\n", + "# source=conical_tube.output_pin('samples'),\n", + "# destination=microfuge_tube_6hrs.output_pin('samples'),\n", + "# amount=sbol3.Measure(0.5, OM.milliliter)) \n", + "\n", + "# hold = protocol.primitive_step('Hold',\n", + "# location=microfuge_tube_6hrs.output_pin('samples'),\n", + "# temperature=sbol3.Measure(4, OM.degree_Celsius))\n", + " \n", + "# # timepoint_samples_0hrs.append(microfuge_tube_0hrs)\n", + "# # timepoint_samples_6hrs.append(microfuge_tube_6hrs)\n", + "\n", + "\n", + " \n", + "# # Transfer culture samples to a microwell plate for absorbance/fluorescence measurements \n", + "# plate = protocol.primitive_step('EmptyContainer', \n", + "# specification=labop.ContainerSpec(name=f'measurement plate',\n", + "# queryString='cont:Plate96Well', \n", + "# prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'}))\n", + "\n", + "# # Plate 0hr timepoint samples\n", + "# for i_sample, sample in enumerate(timepoint_samples_0hrs):\n", + " \n", + "# # Plate one sample per column, replicates in rows A-D\n", + "# column = i_sample + 1\n", + "# replicate1 = protocol.primitive_step('PlateCoordinates', \n", + "# source=plate.output_pin('samples'),\n", + "# coordinates=f'A{column}')\n", + "# replicate2 = protocol.primitive_step('PlateCoordinates', \n", + "# source=plate.output_pin('samples'),\n", + "# coordinates=f'B{column}')\n", + "# replicate3 = protocol.primitive_step('PlateCoordinates', \n", + "# source=plate.output_pin('samples'),\n", + "# coordinates=f'C{column}')\n", + "# replicate4 = protocol.primitive_step('PlateCoordinates', \n", + "# source=plate.output_pin('samples'),\n", + "# coordinates=f'D{column}')\n", + "# transfer1 = protocol.primitive_step('Transfer',\n", + "# source=sample.output_pin('samples'),\n", + "# destination=replicate1.output_pin('samples'),\n", + "# amount=sbol3.Measure(100, OM.microliter)) \n", + "# transfer2 = protocol.primitive_step('Transfer',\n", + "# source=sample.output_pin('samples'),\n", + "# destination=replicate2.output_pin('samples'),\n", + "# amount=sbol3.Measure(100, OM.microliter))\n", + "# transfer3 = protocol.primitive_step('Transfer',\n", + "# source=sample.output_pin('samples'),\n", + "# destination=replicate3.output_pin('samples'),\n", + "# amount=sbol3.Measure(100, OM.microliter))\n", + "# transfer4 = protocol.primitive_step('Transfer',\n", + "# source=sample.output_pin('samples'),\n", + "# destination=replicate4.output_pin('samples'),\n", + "# amount=sbol3.Measure(100, OM.microliter))\n", + " \n", + "# # Plate 6hr timepoint samples\n", + "# for i_sample, sample in enumerate(timepoint_samples_6hrs):\n", + "\n", + "# # Plate one sample per column, replicates in rows E-H\n", + "# column = i_sample + 1\n", + "# replicate1 = protocol.primitive_step('PlateCoordinates', \n", + "# source=plate.output_pin('samples'),\n", + "# coordinates=f'E{column}')\n", + "# replicate2 = protocol.primitive_step('PlateCoordinates', \n", + "# source=plate.output_pin('samples'),\n", + "# coordinates=f'F{column}')\n", + "# replicate3 = protocol.primitive_step('PlateCoordinates', \n", + "# source=plate.output_pin('samples'),\n", + "# coordinates=f'G{column}')\n", + "# replicate4 = protocol.primitive_step('PlateCoordinates', \n", + "# source=plate.output_pin('samples'),\n", + "# coordinates=f'H{column}')\n", + "# transfer1 = protocol.primitive_step('Transfer',\n", + "# source=sample.output_pin('samples'),\n", + "# destination=replicate1.output_pin('samples'),\n", + "# amount=sbol3.Measure(100, OM.microliter)) \n", + "# transfer2 = protocol.primitive_step('Transfer',\n", + "# source=sample.output_pin('samples'),\n", + "# destination=replicate2.output_pin('samples'),\n", + "# amount=sbol3.Measure(100, OM.microliter))\n", + "# transfer3 = protocol.primitive_step('Transfer',\n", + "# source=sample.output_pin('samples'),\n", + "# destination=replicate3.output_pin('samples'),\n", + "# amount=sbol3.Measure(100, OM.microliter))\n", + "# transfer4 = protocol.primitive_step('Transfer',\n", + "# source=sample.output_pin('samples'),\n", + "# destination=replicate4.output_pin('samples'),\n", + "# amount=sbol3.Measure(100, OM.microliter))\n", + "\n", + "# Execute the protocol\n", + "\n", + "from IPython.display import Markdown\n", + "\n", + "agent = sbol3.Agent(\"test_agent\")\n", + "ee = ExecutionEngine(specializations=[MarkdownSpecialization(\"test_LUDOX_markdown.md\")])\n", + "execution = ee.execute(protocol, agent, id=\"test_execution\", parameter_values=[])\n", + "Markdown(ee.specializations[0].markdown)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f38dad2", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "\n", + "\n", + "timepoint_samples_0hrs = [] # Collection of samples on which we will run abs and fluorescence measurements\n", + "timepoint_samples_6hrs = []\n", + "\n", + "plasmids = [neg_control_plasmid, pos_control_plasmid, test_device1, test_device2, test_device3, test_device4, test_device5, test_device6]\n", + "transformant_colonies = []\n", + "i_transformant_clone = 0\n", + "for plasmid in plasmids[:2]:\n", + " \n", + " # Day 1: Transformation\n", + " transformation = protocol.primitive_step(f'Transform',\n", + " host=dh5alpha,\n", + " dna=plasmid,\n", + " selection_medium=lb_cam)\n", + " \n", + " # Day 2: Pick colonies and culture overnight\n", + " for i_replicates in range(0, 1):\n", + "\n", + " i_transformant_clone += 1\n", + " culture_container_day1 = protocol.primitive_step('EmptyContainer', \n", + " specification=labop.ContainerSpec(name=f'{plasmid.name} culture (day 1)',\n", + " queryString='cont:CultureTube', \n", + " prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'}))\n", + " \n", + " overnight_culture = protocol.primitive_step('Culture',\n", + " inoculum=transformation.output_pin('transformants'),\n", + " growth_medium=lb_cam,\n", + " volume=sbol3.Measure(5, OM.millilitre), # Actually 5-10 ml in the written protocol\n", + " duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours\n", + " orbital_shake_speed=sbol3.Measure(220, None), # No unit for RPM or inverse minutes\n", + " temperature=sbol3.Measure(37, OM.degree_Celsius),\n", + " container=culture_container_day1.output_pin('samples'))\n", + "\n", + " # Day 3 culture\n", + " culture_container_day2 = protocol.primitive_step('EmptyContainer', \n", + " specification=labop.ContainerSpec(name=f'{plasmid.name} culture (day 2)',\n", + " queryString='cont:CultureTube', \n", + " prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'}))\n", + " \n", + " back_dilution = protocol.primitive_step('Dilute',\n", + " source=culture_container_day1.output_pin('samples'),\n", + " destination=culture_container_day2.output_pin('samples'),\n", + " diluent=lb_cam,\n", + " amount=sbol3.Measure(5.0, OM.millilitre),\n", + " dilution_factor=uml.LiteralInteger(value=10))\n", + "\n", + " absorbance = protocol.primitive_step('MeasureAbsorbance',\n", + " samples=culture_container_day2.output_pin('samples'),\n", + " wavelength=sbol3.Measure(600, OM.nanometer))\n", + "\n", + " conical_tube = protocol.primitive_step('EmptyContainer', \n", + " specification=labop.ContainerSpec(name=f'{plasmid.name} culture',\n", + " queryString='cont:ConicalTube', \n", + " prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'})) # Should be opaque\n", + "\n", + " dilution = protocol.primitive_step('DiluteToTargetOD',\n", + " source=culture_container_day2.output_pin('samples'),\n", + " destination=conical_tube.output_pin('samples'),\n", + " diluent=lb_cam,\n", + " amount=sbol3.Measure(12, OM.millilitre),\n", + " target_od=sbol3.Measure(0.2, None)) # Dilute to a target OD of 0.2, opaque container\n", + " \n", + " microfuge_tube_0hrs = protocol.primitive_step('EmptyContainer', \n", + " specification=labop.ContainerSpec(name=f'{plasmid.name} culture (0 hrs)',\n", + " queryString='cont:MicrofugeTube', \n", + " prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'}))\n", + "\n", + " transfer = protocol.primitive_step('Transfer',\n", + " source=conical_tube.output_pin('samples'),\n", + " destination=microfuge_tube_0hrs.output_pin('samples'),\n", + " amount=sbol3.Measure(0.5, OM.milliliter))\n", + "\n", + " hold = protocol.primitive_step('Hold',\n", + " location=microfuge_tube_0hrs.output_pin('samples'),\n", + " temperature=sbol3.Measure(4, OM.degree_Celsius))\n", + " \n", + " incubate = protocol.primitive_step('Incubate',\n", + " location=conical_tube.output_pin('samples'),\n", + " duration=sbol3.Measure(6, OM.hour),\n", + " temperature=sbol3.Measure(37, OM.degree_Celsius),\n", + " shakingFrequency=sbol3.Measure(220, None))\n", + " \n", + " microfuge_tube_6hrs = protocol.primitive_step('EmptyContainer', \n", + " specification=labop.ContainerSpec(name=f'{plasmid.name} culture (6 hrs)',\n", + " queryString='cont:MicrofugeTube', \n", + " prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'}))\n", + " \n", + " \n", + " transfer = protocol.primitive_step('Transfer',\n", + " source=conical_tube.output_pin('samples'),\n", + " destination=microfuge_tube_6hrs.output_pin('samples'),\n", + " amount=sbol3.Measure(0.5, OM.milliliter)) \n", + "\n", + " hold = protocol.primitive_step('Hold',\n", + " location=microfuge_tube_6hrs.output_pin('samples'),\n", + " temperature=sbol3.Measure(4, OM.degree_Celsius))\n", + " \n", + " timepoint_samples_0hrs.append(microfuge_tube_0hrs)\n", + " timepoint_samples_6hrs.append(microfuge_tube_6hrs)\n", + "\n", + "\n", + " \n", + "# Transfer culture samples to a microwell plate for absorbance/fluorescence measurements \n", + "plate = protocol.primitive_step('EmptyContainer', \n", + " specification=labop.ContainerSpec(name=f'measurement plate',\n", + " queryString='cont:Plate96Well', \n", + " prefixMap={'cont': 'https://sift.net/container-ontology/container-ontology#'}))\n", + "\n", + "# Plate 0hr timepoint samples\n", + "for i_sample, sample in enumerate(timepoint_samples_0hrs):\n", + " \n", + " # Plate one sample per column, replicates in rows A-D\n", + " column = i_sample + 1\n", + " replicate1 = protocol.primitive_step('PlateCoordinates', \n", + " source=plate.output_pin('samples'),\n", + " coordinates=f'A{column}')\n", + " replicate2 = protocol.primitive_step('PlateCoordinates', \n", + " source=plate.output_pin('samples'),\n", + " coordinates=f'B{column}')\n", + " replicate3 = protocol.primitive_step('PlateCoordinates', \n", + " source=plate.output_pin('samples'),\n", + " coordinates=f'C{column}')\n", + " replicate4 = protocol.primitive_step('PlateCoordinates', \n", + " source=plate.output_pin('samples'),\n", + " coordinates=f'D{column}')\n", + " transfer1 = protocol.primitive_step('Transfer',\n", + " source=sample.output_pin('samples'),\n", + " destination=replicate1.output_pin('samples'),\n", + " amount=sbol3.Measure(100, OM.microliter)) \n", + " transfer2 = protocol.primitive_step('Transfer',\n", + " source=sample.output_pin('samples'),\n", + " destination=replicate2.output_pin('samples'),\n", + " amount=sbol3.Measure(100, OM.microliter))\n", + " transfer3 = protocol.primitive_step('Transfer',\n", + " source=sample.output_pin('samples'),\n", + " destination=replicate3.output_pin('samples'),\n", + " amount=sbol3.Measure(100, OM.microliter))\n", + " transfer4 = protocol.primitive_step('Transfer',\n", + " source=sample.output_pin('samples'),\n", + " destination=replicate4.output_pin('samples'),\n", + " amount=sbol3.Measure(100, OM.microliter))\n", + " \n", + "# Plate 6hr timepoint samples\n", + "for i_sample, sample in enumerate(timepoint_samples_6hrs):\n", + "\n", + " # Plate one sample per column, replicates in rows E-H\n", + " column = i_sample + 1\n", + " replicate1 = protocol.primitive_step('PlateCoordinates', \n", + " source=plate.output_pin('samples'),\n", + " coordinates=f'E{column}')\n", + " replicate2 = protocol.primitive_step('PlateCoordinates', \n", + " source=plate.output_pin('samples'),\n", + " coordinates=f'F{column}')\n", + " replicate3 = protocol.primitive_step('PlateCoordinates', \n", + " source=plate.output_pin('samples'),\n", + " coordinates=f'G{column}')\n", + " replicate4 = protocol.primitive_step('PlateCoordinates', \n", + " source=plate.output_pin('samples'),\n", + " coordinates=f'H{column}')\n", + " transfer1 = protocol.primitive_step('Transfer',\n", + " source=sample.output_pin('samples'),\n", + " destination=replicate1.output_pin('samples'),\n", + " amount=sbol3.Measure(100, OM.microliter)) \n", + " transfer2 = protocol.primitive_step('Transfer',\n", + " source=sample.output_pin('samples'),\n", + " destination=replicate2.output_pin('samples'),\n", + " amount=sbol3.Measure(100, OM.microliter))\n", + " transfer3 = protocol.primitive_step('Transfer',\n", + " source=sample.output_pin('samples'),\n", + " destination=replicate3.output_pin('samples'),\n", + " amount=sbol3.Measure(100, OM.microliter))\n", + " transfer4 = protocol.primitive_step('Transfer',\n", + " source=sample.output_pin('samples'),\n", + " destination=replicate4.output_pin('samples'),\n", + " amount=sbol3.Measure(100, OM.microliter))\n", + " \n", + "# Plate blanks in column 9\n", + "for row in ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']:\n", + " blank_wells = protocol.primitive_step('PlateCoordinates', \n", + " source=plate.output_pin('samples'),\n", + " coordinates=f'{row}9')\n", + " transfer = protocol.primitive_step('Transfer',\n", + " source=lb_cam,\n", + " destination=blank_wells.output_pin('samples'),\n", + " amount=sbol3.Measure(100, OM.microliter))\n", + "\n", + "# Perform measurements\n", + "scan_coordinates = protocol.primitive_step('PlateCoordinates', \n", + " source=plate.output_pin('samples'),\n", + " coordinates=f'A1:H9')\n", + "measure_absorbance = protocol.primitive_step('MeasureAbsorbance',\n", + " samples=scan_coordinates.output_pin('samples'),\n", + " wavelength=sbol3.Measure(600, OM.nanometer))\n", + "measure_fluorescence = protocol.primitive_step('MeasureFluorescence',\n", + " samples=scan_coordinates.output_pin('samples'),\n", + " excitationWavelength=sbol3.Measure(485, OM.nanometer),\n", + " emissionWavelength=sbol3.Measure(530, OM.nanometer),\n", + " emissionBandpassWidth=sbol3.Measure(30, OM.nanometer))\n", + "\n", + "protocol.designate_output('measurements', 'http://bioprotocols.org/labop#SampleData', source=measure_absorbance.output_pin('measurements'))\n", + "protocol.designate_output('measurements', 'http://bioprotocols.org/labop#SampleData', source=measure_aborbance.output_pin('measurements'))\n", + "protocol.designate_output('measurements', 'http://bioprotocols.org/labop#SampleData', source=measure_absorbance.output_pin('measurements'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fddb543b", + "metadata": {}, + "outputs": [], + "source": [ + "# Execute the protocol\n", + "\n", + "from IPython.display import Markdown\n", + "\n", + "agent = sbol3.Agent(\"test_agent\")\n", + "ee = ExecutionEngine(specializations=[MarkdownSpecialization(\"test_LUDOX_markdown.md\")])\n", + "execution = ee.execute(protocol, agent, id=\"test_execution\", parameter_values=[])\n", + "Markdown(ee.specializations[0].markdown)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa8c1d77", + "metadata": {}, + "outputs": [], + "source": [ + "print(ee.specializations[0].markdown)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "96e10509", + "metadata": {}, + "outputs": [], + "source": [ + "text_file = open('interlab-growth-curve.md', \"w\")\n", + "n = text_file.write(ee.specializations[0].markdown)\n", + "text_file.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "968cce82", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/protocols/iGEM/interlab-growth-curve.py b/examples/protocols/iGEM/interlab-growth-curve.py new file mode 100644 index 00000000..b2785794 --- /dev/null +++ b/examples/protocols/iGEM/interlab-growth-curve.py @@ -0,0 +1,316 @@ +""" +http://2018.igem.org/wiki/images/0/09/2018_InterLab_Plate_Reader_Protocol.pdf +""" +import json +from urllib.parse import quote + +import sbol3 +from tyto import OM + +import labop +import uml +from labop.execution_engine import ExecutionEngine +from labop_convert.markdown.markdown_specialization import MarkdownSpecialization + +doc = sbol3.Document() +sbol3.set_namespace("http://igem.org/engineering/") + +############################################# +# Import the primitive libraries +print("Importing libraries") +labop.import_library("liquid_handling") +print("... Imported liquid handling") +labop.import_library("plate_handling") +# print('... Imported plate handling') +labop.import_library("spectrophotometry") +print("... Imported spectrophotometry") +labop.import_library("sample_arrays") +print("... Imported sample arrays") +labop.import_library("culturing") +############################################# + + +# create the materials to be provisioned +dh5alpha = sbol3.Component( + "dh5alpha", "https://identifiers.org/pubchem.substance:24901740" +) +dh5alpha.name = "_E. coli_ DH5 alpha" +doc.add(dh5alpha) + +lb_cam = sbol3.Component("lb_cam", "https://identifiers.org/pubchem.substance:24901740") +lb_cam.name = "LB Broth+chloramphenicol" +doc.add(lb_cam) + +chloramphenicol = sbol3.Component( + "chloramphenicol", "https://identifiers.org/pubchem.substance:24901740" +) +chloramphenicol.name = "chloramphenicol" +doc.add(chloramphenicol) + + +neg_control_plasmid = sbol3.Component("neg_control_plasmid", sbol3.SBO_DNA) +neg_control_plasmid.name = "Negative control" +neg_control_plasmid.description = "BBa_R0040 Kit Plate 7 Well 2D" + +pos_control_plasmid = sbol3.Component("pos_control_plasmid", sbol3.SBO_DNA) +pos_control_plasmid.name = "Positive control" +pos_control_plasmid.description = "BBa_I20270 Kit Plate 7 Well 2B" + +test_device1 = sbol3.Component("test_device1", sbol3.SBO_DNA) +test_device1.name = "Test Device 1" +test_device1.description = "BBa_J364000 Kit Plate 7 Well 2F" + +test_device2 = sbol3.Component("test_device2", sbol3.SBO_DNA) +test_device2.name = "Test Device 2" +test_device2.description = "BBa_J364001 Kit Plate 7 Well 2H" + +test_device3 = sbol3.Component("test_device3", sbol3.SBO_DNA) +test_device3.name = "Test Device 3" +test_device3.description = "BBa_J364002 Kit Plate 7 Well 2J" + +test_device4 = sbol3.Component("test_device4", sbol3.SBO_DNA) +test_device4.name = "Test Device 4" +test_device4.description = "BBa_J364007 Kit Plate 7 Well 2L" + +test_device5 = sbol3.Component("test_device5", sbol3.SBO_DNA) +test_device5.name = "Test Device 5" +test_device5.description = "BBa_J364008 Kit Plate 7 Well 2N" + +test_device6 = sbol3.Component("test_device6", sbol3.SBO_DNA) +test_device6.name = "Test Device 6" +test_device6.description = "BBa_J364009 Kit Plate 7 Well 2P" + +doc.add(neg_control_plasmid) +doc.add(pos_control_plasmid) +doc.add(test_device1) +doc.add(test_device2) +doc.add(test_device3) +doc.add(test_device4) +doc.add(test_device5) +doc.add(test_device6) + + +activity = labop.Protocol("interlab") +activity.name = "Cell measurement protocol" +activity.description = """Prior to performing the cell measurements you should perform all three of the calibration measurements. Please do not proceed unless you have completed the three calibration protocols. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For the sake of consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you, and this can count as a collaboration as long as it is appropriately documented on both teams' wikis. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Measurement Committee (measurement at igem dot org) to discuss your situation. + +For all of these cell measurements, you must use the same plates and volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same plates, volumes, and settings, the measurements will not be valid.""" + +doc.add(activity) +plasmids = [ + neg_control_plasmid, + pos_control_plasmid, + test_device1, + test_device2, + test_device3, + test_device4, + test_device5, + test_device6, +] + +# Day 1: Transformation +transformation = activity.primitive_step( + f"Transform", host=dh5alpha, dna=plasmids, selection_medium=lb_cam +) + +# Day 2: Pick colonies and culture overnight +culture_container_day1 = activity.primitive_step( + "ContainerSet", + quantity=uml.LiteralInteger(value=len(plasmids)), + specification=labop.ContainerSpec( + name=f"culture (day 1)", + queryString="cont:CultureTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +overnight_culture = activity.primitive_step( + "Culture", + inoculum=transformation.output_pin("transformants"), + growth_medium=lb_cam, + volume=sbol3.Measure(5, OM.millilitre), # Actually 5-10 ml in the written protocol + duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours + orbital_shake_speed=sbol3.Measure(220, None), # No unit for RPM or inverse minutes + temperature=sbol3.Measure(37, OM.degree_Celsius), + container=culture_container_day1.output_pin("samples"), +) + +# Day 3 culture +culture_container_day2 = activity.primitive_step( + "ContainerSet", + quantity=uml.LiteralInteger(value=len(plasmids)), + specification=labop.ContainerSpec( + name=f"culture (day 2)", + queryString="cont:CultureTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + + +back_dilution = activity.primitive_step( + "Dilute", + source=culture_container_day1.output_pin("samples"), + destination=culture_container_day2.output_pin("samples"), + diluent=lb_cam, + amount=sbol3.Measure(5.0, OM.millilitre), + dilution_factor=uml.LiteralInteger(value=10), +) + +baseline_absorbance = activity.primitive_step( + "MeasureAbsorbance", + samples=culture_container_day2.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) + +conical_tube = activity.primitive_step( + "ContainerSet", + quantity=uml.LiteralInteger(value=len(plasmids)), + specification=labop.ContainerSpec( + name=f"culture (day 2), backdiluted", + queryString="cont:ConicalTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) # Should be opaque + +dilution = activity.primitive_step( + "DiluteToTargetOD", + source=culture_container_day2.output_pin("samples"), + destination=conical_tube.output_pin("samples"), + diluent=lb_cam, + amount=sbol3.Measure(12, OM.millilitre), + target_od=sbol3.Measure(0.2, None), +) # Dilute to a target OD of 0.2, opaque container + +microfuge_tube_0hrs = activity.primitive_step( + "ContainerSet", + quantity=uml.LiteralInteger(value=len(plasmids)), + specification=labop.ContainerSpec( + name="absorbance timepoint (0 hrs)", + queryString="cont:MicrofugeTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +transfer = activity.primitive_step( + "Transfer", + source=conical_tube.output_pin("samples"), + destination=microfuge_tube_0hrs.output_pin("samples"), + amount=sbol3.Measure(0.5, OM.milliliter), +) + +hold = activity.primitive_step( + "Hold", + location=microfuge_tube_0hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) + +incubate = activity.primitive_step( + "Incubate", + location=conical_tube.output_pin("samples"), + duration=sbol3.Measure(6, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, None), +) + +microfuge_tube_6hrs = activity.primitive_step( + "ContainerSet", + quantity=uml.LiteralInteger(value=len(plasmids)), + specification=labop.ContainerSpec( + name=f"absorbance timepoint (6 hrs)", + queryString="cont:MicrofugeTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + + +transfer = activity.primitive_step( + "Transfer", + source=conical_tube.output_pin("samples"), + destination=microfuge_tube_6hrs.output_pin("samples"), + amount=sbol3.Measure(0.5, OM.milliliter), +) + +hold = activity.primitive_step( + "Hold", + location=microfuge_tube_6hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) + +# Transfer to Plate +plate = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + name=f"measurement plate", + queryString="cont:Plate96Well", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +plan = labop.SampleData( + values=quote( + json.dumps( + { + 1: "A1:D1", + 2: "A2:D2", + 3: "A3:D3", + 4: "A4:D4", + 5: "A5:D5", + 6: "A6:D6", + 7: "A7:D7", + 8: "A8:D8", + } + ) + ) +) +transfer = activity.primitive_step( + "TransferByMap", + source=microfuge_tube_0hrs.output_pin("samples"), + destination=plate.output_pin("samples"), + amount=sbol3.Measure(100, OM.microliter), + plan=plan, +) + +plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate.output_pin("samples"), + coordinates="A9:D9", + amount=sbol3.Measure(100, OM.microliter), +) + +measure_absorbance = activity.primitive_step( + "MeasureAbsorbance", + samples=plate.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) +measure_fluorescence = activity.primitive_step( + "MeasureFluorescence", + samples=plate.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), +) + +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=baseline_absorbance.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=measure_absorbance.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=measure_fluorescence.output_pin("measurements"), +) + + +agent = sbol3.Agent("test_agent") +ee = ExecutionEngine(specializations=[MarkdownSpecialization("test_LUDOX_markdown.md")]) +execution = ee.execute(activity, agent, id="test_execution", parameter_values=[]) +print(ee.specializations[0].markdown) +with open("example.md", "w", encoding="utf-8") as f: + f.write(ee.specializations[0].markdown) diff --git a/examples/protocols/iGEM/revised-interlab-growth-curve.py b/examples/protocols/iGEM/revised-interlab-growth-curve.py new file mode 100644 index 00000000..bcf4dbb3 --- /dev/null +++ b/examples/protocols/iGEM/revised-interlab-growth-curve.py @@ -0,0 +1,581 @@ +""" +http://2018.igem.org/wiki/images/0/09/2018_InterLab_Plate_Reader_Protocol.pdf +""" +import json +from urllib.parse import quote + +import sbol3 +from tyto import OM + +import labop +import uml +from labop.execution_engine import ExecutionEngine +from labop_convert import MarkdownSpecialization + +if "unittest" in sys.modules: + REGENERATE_ARTIFACTS = False +else: + REGENERATE_ARTIFACTS = True + +filename = "".join(__file__.split(".py")[0].split("/")[-1:]) + +doc = sbol3.Document() +sbol3.set_namespace("http://igem.org/engineering/") + +############################################# +# Import the primitive libraries +print("Importing libraries") +labop.import_library("liquid_handling") +print("... Imported liquid handling") +labop.import_library("plate_handling") +# print('... Imported plate handling') +labop.import_library("spectrophotometry") +print("... Imported spectrophotometry") +labop.import_library("sample_arrays") +print("... Imported sample arrays") +labop.import_library("culturing") +############################################# + + +# create the materials to be provisioned +dh5alpha = sbol3.Component( + "dh5alpha", "https://identifiers.org/pubchem.substance:24901740" +) +dh5alpha.name = "_E. coli_ DH5 alpha" +doc.add(dh5alpha) + +lb_cam = sbol3.Component("lb_cam", "https://identifiers.org/pubchem.substance:24901740") +lb_cam.name = "LB Broth+chloramphenicol" +doc.add(lb_cam) + +chloramphenicol = sbol3.Component( + "chloramphenicol", "https://identifiers.org/pubchem.substance:24901740" +) +chloramphenicol.name = "chloramphenicol" +doc.add(chloramphenicol) + + +neg_control_plasmid = sbol3.Component("neg_control_plasmid", sbol3.SBO_DNA) +neg_control_plasmid.name = "Negative control" +neg_control_plasmid.description = "BBa_R0040 Kit Plate 1 Well 12M" + +pos_control_plasmid = sbol3.Component("pos_control_plasmid", sbol3.SBO_DNA) +pos_control_plasmid.name = "Positive control" +pos_control_plasmid.description = "BBa_I20270 Kit Plate 1 Well 1A" + +test_device1 = sbol3.Component("test_device1", sbol3.SBO_DNA) +test_device1.name = "Test Device 1" +test_device1.description = "BBa_J364000 Kit Plate 1 Well 1C" + +test_device2 = sbol3.Component("test_device2", sbol3.SBO_DNA) +test_device2.name = "Test Device 2" +test_device2.description = "BBa_J364001 Kit Plate 1 Well 1E" + +test_device3 = sbol3.Component("test_device3", sbol3.SBO_DNA) +test_device3.name = "Test Device 3" +test_device3.description = "BBa_J364002 Kit Plate 1 Well 1G" + +test_device4 = sbol3.Component("test_device4", sbol3.SBO_DNA) +test_device4.name = "Test Device 4" +test_device4.description = "BBa_J364007 Kit Plate 1 Well 1I" + +test_device5 = sbol3.Component("test_device5", sbol3.SBO_DNA) +test_device5.name = "Test Device 5" +test_device5.description = "BBa_J364008 Kit Plate 1 Well 1K" + +test_device6 = sbol3.Component("test_device6", sbol3.SBO_DNA) +test_device6.name = "Test Device 6" +test_device6.description = "BBa_J364009 Kit Plate 1 Well 1M" + +doc.add(neg_control_plasmid) +doc.add(pos_control_plasmid) +doc.add(test_device1) +doc.add(test_device2) +doc.add(test_device3) +doc.add(test_device4) +doc.add(test_device5) +doc.add(test_device6) + + +activity = labop.Protocol("interlab") +activity.name = "Cell measurement protocol" +activity.version = sbol3.TextProperty( + activity, "http://igem.org/interlab_working_group#Version", 0, 1, [], "1.0b" +) +activity.description = """This year we plan to go towards automation, where a 96-well plate instead of a tube is used for culturing. Prior to the full establishment of this protocol, we need to evaluate how the performance is worldwide with this as well as with parallel experiment in the test tube, which has been used as standard culturing protocol. + +At the end of the experiment, you would have two plates to be measured (five for challenging version). You will measure both fluorescence and absorbance in each plate. + +Prior to performing the cell measurements you should perform all three of the calibration measurements. Please do not proceed unless you have completed the three calibration protocols. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For the sake of consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you, and this can count as a collaboration as long as it is appropriately documented on both teams' wikis. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Measurement Committee (measurement at igem dot org) to discuss your situation. + +For all of these cell measurements, you must use the same plates and volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same plates, volumes, and settings, the measurements will not be valid.""" + +doc.add(activity) +activity = doc.find(activity.identity) + +plasmids = [ + neg_control_plasmid, + pos_control_plasmid, + test_device1, + test_device2, + test_device3, + test_device4, + test_device5, + test_device6, +] + +# Day 1: Transformation +transformation = activity.primitive_step( + f"Transform", host=dh5alpha, dna=plasmids, selection_medium=lb_cam +) + +# Day 2: Pick colonies and culture overnight +culture_container_day1 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + name=f"culture (day 1)", + queryString="cont:CultureTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +overnight_culture = activity.primitive_step( + "Culture", + inoculum=transformation.output_pin("transformants"), + replicates=2, + growth_medium=lb_cam, + volume=sbol3.Measure(5, OM.millilitre), # Actually 5-10 ml in the written protocol + duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours + orbital_shake_speed=sbol3.Measure(220, None), # No unit for RPM or inverse minutes + temperature=sbol3.Measure(37, OM.degree_Celsius), + container=culture_container_day1.output_pin("samples"), +) + +# Day 3 culture +culture_container_day2 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + name=f"culture (day 2)", + queryString="cont:CultureTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + + +back_dilution = activity.primitive_step( + "Dilute", + source=culture_container_day1.output_pin("samples"), + destination=culture_container_day2.output_pin("samples"), + replicates=2, + diluent=lb_cam, + amount=sbol3.Measure(5.0, OM.millilitre), + dilution_factor=uml.LiteralInteger(value=10), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) + +# Transfer cultures to a microplate baseline measurement and outgrowth +timepoint_0hrs = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + name="cultures (0 hr timepoint)", + queryString="cont:MicrofugeTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +hold = activity.primitive_step( + "Hold", + location=timepoint_0hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) +hold.description = "This will prevent cell growth while transferring samples." + +transfer = activity.primitive_step( + "Transfer", + source=culture_container_day2.output_pin("samples"), + destination=timepoint_0hrs.output_pin("samples"), + amount=sbol3.Measure(1, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) + +baseline_absorbance = activity.primitive_step( + "MeasureAbsorbance", + samples=timepoint_0hrs.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) +baseline_absorbance.name = "baseline absorbance of culture (day 2)" + + +conical_tube = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + name=f"back-diluted culture", + queryString="cont:50mlConicalTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) +conical_tube.description = ( + "The conical tube should be opaque, amber-colored, or covered with foil." +) + +dilution = activity.primitive_step( + "DiluteToTargetOD", + source=culture_container_day2.output_pin("samples"), + destination=conical_tube.output_pin("samples"), + diluent=lb_cam, + amount=sbol3.Measure(12, OM.millilitre), + target_od=sbol3.Measure(0.02, None), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) # Dilute to a target OD of 0.2, opaque container +dilution.description = " Use the provided Excel sheet to calculate this dilution. Reliability of the dilution upon Abs600 measurement: should stay between 0.1-0.9" + +embedded_image = activity.primitive_step( + "EmbeddedImage", + image="/Users/bbartley/Dev/git/sd2/labop/fig1_cell_calibration.png", +) + + +temporary = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + name="back-diluted culture aliquots", + queryString="cont:MicrofugeTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +hold = activity.primitive_step( + "Hold", + location=temporary.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) +hold.description = "This will prevent cell growth while transferring samples." + +transfer = activity.primitive_step( + "Transfer", + source=conical_tube.output_pin("samples"), + destination=temporary.output_pin("samples"), + amount=sbol3.Measure(1, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) + +plate1 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + name="plate 1", + queryString="cont:Plate96Well", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + + +hold = activity.primitive_step( + "Hold", + location=plate1.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) + + +plan = labop.SampleData( + values=quote( + json.dumps( + { + "1": "A2:D2", + "2": "E2:H2", + "3": "A3:D3", + "4": "E3:H3", + "5": "A4:D4", + "6": "E4:H4", + "7": "A5:D5", + "8": "E5:H5", + "9": "A7:D7", + "10": "E7:H7", + "11": "A8:D8", + "12": "E8:H8", + "13": "A9:D9", + "14": "E9:H9", + "15": "A10:D10", + "16": "E10:H10", + } + ) + ) +) + + +transfer = activity.primitive_step( + "TransferByMap", + source=timepoint_0hrs.output_pin("samples"), + destination=plate1.output_pin("samples"), + amount=sbol3.Measure(100, OM.microliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + plan=plan, +) +transfer.description = "See also the plate layout below." + +plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate1.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(100, OM.microliter), +) +plate_blanks.description = "These samples are blanks." + +embedded_image = activity.primitive_step( + "EmbeddedImage", + image="/Users/bbartley/Dev/git/sd2/labop/fig2_cell_calibration.png", +) + +# Cover plate +seal = activity.primitive_step( + "EvaporativeSeal", location=plate1.output_pin("samples"), type="foo" +) + + +# Possibly display map here +absorbance_plate1 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate1.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) +absorbance_plate1.name = "0 hr absorbance timepoint" +fluorescence_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(488, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), +) +fluorescence_plate1.name = "0 hr fluorescence timepoint" + + +# Begin outgrowth +incubate = activity.primitive_step( + "Incubate", + location=conical_tube.output_pin("samples"), + duration=sbol3.Measure(6, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, None), +) + +incubate = activity.primitive_step( + "Incubate", + location=plate1.output_pin("samples"), + duration=sbol3.Measure(6, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, None), +) + +# Hold on ice to inhibit cell growth +hold = activity.primitive_step( + "Hold", + location=timepoint_0hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) +hold.description = ( + "This will inhibit cell growth during the subsequent pipetting steps." +) + +hold = activity.primitive_step( + "Hold", + location=plate1.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) +hold.description = ( + "This will inhibit cell growth during the subsequent pipetting steps." +) + + +# Take a 6hr timepoint measurement +timepoint_6hrs = activity.primitive_step( + "ContainerSet", + quantity=len(plasmids) * 2, + specification=labop.ContainerSpec( + name=f"6hr timepoint", + queryString="cont:MicrofugeTube", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +plate2 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + name="plate 2", + queryString="cont:Plate96Well", + prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, + ), +) + +# Hold on ice +hold = activity.primitive_step( + "Hold", + location=timepoint_6hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) +hold.description = "This will prevent cell growth while transferring samples." + +hold = activity.primitive_step( + "Hold", + location=plate2.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), +) + + +transfer = activity.primitive_step( + "Transfer", + source=conical_tube.output_pin("samples"), + destination=timepoint_6hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(1, OM.milliliter), +) + + +plan = labop.SampleData( + values=quote( + json.dumps( + { + "1": "A2:D2", + "2": "E2:H2", + "3": "A3:D3", + "4": "E3:H3", + "5": "A4:D4", + "6": "E4:H4", + "7": "A5:D5", + "8": "E5:H5", + "9": "A7:D7", + "10": "E7:H7", + "11": "A8:D8", + "12": "E8:H8", + "13": "A9:D9", + "14": "E9:H9", + "15": "A10:D10", + "16": "E10:H10", + } + ) + ) +) + +transfer = activity.primitive_step( + "TransferByMap", + source=timepoint_6hrs.output_pin("samples"), + destination=plate2.output_pin("samples"), + amount=sbol3.Measure(100, OM.microliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + plan=plan, +) +transfer.description = "See the plate layout." + +# Plate the blanks +plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate2.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(100, OM.microliter), +) +plate_blanks.description = "These are the blanks." + +# Cover plate +seal = activity.primitive_step( + "EvaporativeSeal", location=plate1.output_pin("samples"), type="foo" +) + + +# quick_spin = protocol.primitive_step('QuickSpin', +# location=plate1.output_pin('samples')) +# quick_spin.description = 'This will prevent cross-contamination when removing the seal.' +# +# remove_seal = protocol.primitive_step('Unseal', +# location=plate1.output_pin('samples')) + +endpoint_absorbance_plate1 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate1.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) +endpoint_absorbance_plate1.name = "6 hr absorbance timepoint" + +endpoint_fluorescence_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), +) +endpoint_fluorescence_plate1.name = "6 hr fluorescence timepoint" + +endpoint_absorbance_plate2 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate2.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), +) +endpoint_absorbance_plate2.name = "6 hr absorbance timepoint" + +endpoint_fluorescence_plate2 = activity.primitive_step( + "MeasureFluorescence", + samples=plate2.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), +) +endpoint_fluorescence_plate2.name = "6 hr fluorescence timepoint" + +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=baseline_absorbance.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_plate1.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_plate1.output_pin("measurements"), +) + +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_absorbance_plate1.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_fluorescence_plate1.output_pin("measurements"), +) + +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_absorbance_plate2.output_pin("measurements"), +) +activity.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_fluorescence_plate2.output_pin("measurements"), +) + + +agent = sbol3.Agent("test_agent") +ee = ExecutionEngine(specializations=[MarkdownSpecialization("test_LUDOX_markdown.md")]) +execution = ee.execute(activity, agent, id="test_execution", parameter_values=[]) +print(ee.specializations[0].markdown) +ee.specializations[0].markdown = ee.specializations[0].markdown.replace( + "`_E. coli_", "_`E. coli`_ `" +) + +filename = "".join(__file__.split(".py")[0].split("/")[-1:]) + +if REGENERATE_ARTIFACTS: + with open(filename + ".md", "w", encoding="utf-8") as f: + f.write(ee.specializations[0].markdown) diff --git a/examples/protocols/ludox/artifacts/test_LUDOX_markdown.md b/examples/protocols/ludox/artifacts/test_LUDOX_markdown.md new file mode 100644 index 00000000..84f6ea23 --- /dev/null +++ b/examples/protocols/ludox/artifacts/test_LUDOX_markdown.md @@ -0,0 +1,102 @@ +# Experiment 3 - Cell measurement protocol Challenge + +This year we plan to test protocols that will eventually be automated. For this reason, we will use 96-well plates instead of test tubes for culturing. Consequently, we want to evaluate how the performance of our plate culturing protocol compares to culturing in test tubes (e.g. 10 mL falcon tube) on a global scale. This version of the interlab protocol involves 2 hr. time interval measurements and incubation inside a microplate reader/incubator. + +At the end of the experiment, you will have four plates to be measured. You will measure both fluorescence and absorbance in each plate. + +Before performing the cell measurements, you need to perform all the calibration measurements. Please do not proceed unless you have completed the calibration protocol. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Engineering Committee (engineering [at] igem [dot] org) to discuss your situation. + +For all below indicated cell measurements, you must use the same type of plates and the same volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same type of plates, volumes, and settings, the measurements will not be valid. + +Protocol summary: UPDATE You will transform the eight devices listed in Table 1 into E. coli K-12 DH5-alpha cells. The next day you will pick two colonies from each transformation (16 total) and use them to inoculate 5 mL overnight cultures (this step is still in tubes). Each of these 16 overnight cultures will be used to inoculate four wells in a 96-well plate (200 microliter each, 4 replicates) and one test tube (12 mL). You will measure how fluorescence and optical density develops over 6 hours by taking measurements at time point 0 hour and at time point 6 hours. Follow the protocol below and the visual instructions in Figure 1 and Figure 2. + + +## Protocol Outputs: +* `baseline absorbance of culture (day 2) measurements of cultures (0 hr timepoint)` +* `0 hr absorbance timepoint measurements of plate 1` +* `0 hr fluorescence timepoint measurements of plate 1` +* `absorbance timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour` +* `fluorescence timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour` +* `absorbance timepoint measurements of Plates 2, 3, and 4` +* `fluorescence timepoint measurements of Plates 2, 3, and 4` + + +## Protocol Materials: +* [_E. coli_ DH5 alpha competent cells](https://identifiers.org/taxonomy:668369) +* [Negative control](http://parts.igem.org/Part:BBa_J428100) +* [Positive control (I20270)](http://parts.igem.org/Part:BBa_I20270) +* [Test Device 1 (J364000)](http://parts.igem.org/Part:BBa_J364000) +* [Test Device 2 (J364001)](http://parts.igem.org/Part:BBa_J364001) +* [Test Device 3 (J364002)](http://parts.igem.org/Part:BBa_J364002) +* [Test Device 4 (J364007)](http://parts.igem.org/Part:BBa_J364007) +* [Test Device 5 (J364008)](http://parts.igem.org/Part:BBa_J364008) +* [Test Device 6 (J364009)](http://parts.igem.org/Part:BBa_J364009) +* [LB Broth + Chloramphenicol (34 ug/mL)]() +* [LB Agar + Chloramphenicol (34 ug/mL)]() +* [Chloramphenicol stock solution (34 mg/mL)](https://pubchem.ncbi.nlm.nih.gov/compound/5959) +* [Ice]() +* [Plate reader]() +* [Shaking incubator]() +* Petri dish (x 8) +* culture tube (x 32) +* 1.5 mL microfuge tube (x 16) +* 50 ml conical tube (x 64) +* 96 well microplate (x 2) +* microplate adhesive sealing film + + +## Protocol Steps: +1. Obtain 8 x Petri dish containing LB Agar + Chloramphenicol (34 ug/mL) growth medium for culturing `transformant strains` +2. Transform `Negative control` DNA into `_E. coli_ DH5 alpha competent cells`. Repeat for the remaining transformant DNA: `Positive control (I20270)`, `Test Device 1 (J364000)`, `Test Device 2 (J364001)`, `Test Device 3 (J364002)`, `Test Device 4 (J364007)`, `Test Device 5 (J364008)`, and `Test Device 6 (J364009)`. Plate transformants on LB Agar + Chloramphenicol (34 ug/mL) `transformant strains` plates. Incubate overnight (for 16 hour) at 37.0 degree Celsius. +3. Obtain 16 x culture tubes to contain `culture (day 1)` +4. Pick 2 colonies from each `transformant strains` plate. +5. Inoculate 2 colonies of each transformant strains, for a total of 16 cultures. Inoculate each into 5.0 milliliter of LB Broth + Chloramphenicol (34 ug/mL) in culture (day 1) and grow overnight (for 16.0 hour) at 37.0 degree Celsius and 220 rpm. +6. Obtain 16 x culture tubes to contain `culture (day 2)` +7. Dilute each of 16 `culture (day 1)` samples with LB Broth + Chloramphenicol (34 ug/mL) into the culture tube at a 1:10 ratio and final volume of 5.0 milliliter. Maintain at 4.0 degree Celsius while performing dilutions. (This can be also performed on ice). +8. Obtain 16 x 1.5 mL microfuge tubes to contain `cultures (0 hr timepoint)` +9. Hold `cultures (0 hr timepoint)` on ice. This will prevent cell growth while transferring samples. +10. Transfer 1.0 milliliter of each of 16 `culture (day 2)` samples to 1.5 mL microfuge tube containers to contain a total of 16 `cultures (0 hr timepoint)` samples. Maintain at 4.0 degree Celsius during transfer. (This can be also performed on Ice). +11. Measure baseline absorbance of culture (day 2) of `cultures (0 hr timepoint)` at 600.0 nanometer. +12. Obtain 16 x 50 ml conical tubes to contain `back-diluted culture` The conical tube should be opaque, amber-colored, or covered with foil. +13. Back-dilute each of 16 `culture (day 2)` samples to a target OD of 0.02 using LB Broth + Chloramphenicol (34 ug/mL) as diluent to a final volume of 40.0 milliliter. Maintain at 4.0 degree Celsius while performing dilutions. + +![](fig1_challenge_protocol.png) +

Fig 1: Visual representation of protocol

+ +14. Obtain 16 x 50 ml conical tubes to contain `Tubes 1, 2 and 3` The conical tubes should be opaque, amber-colored, or covered with foil. +15. Obtain 16 x 50 ml conical tubes to contain `Tube 2` The conical tubes should be opaque, amber-colored, or covered with foil. +16. Obtain 16 x 50 ml conical tubes to contain `Tube 3` The conical tubes should be opaque, amber-colored, or covered with foil. +17. Transfer 12.0 milliliter of each of 16 `back-diluted culture` samples to 50 ml conical tube containers to contain a total of 16 `Tubes 1, 2 and 3` samples. Maintain at 4.0 degree Celsius during transfer. +18. Transfer 12.0 milliliter of each of 16 `back-diluted culture` samples to 50 ml conical tube containers to contain a total of 16 `Tube 2` samples. Maintain at 4.0 degree Celsius during transfer. +19. Transfer 12.0 milliliter of each of 16 `back-diluted culture` samples to 50 ml conical tube containers to contain a total of 16 `Tube 3` samples. Maintain at 4.0 degree Celsius during transfer. +20. Obtain a 96 well microplate to contain `plate 1` +21. Hold `plate 1` on ice. +22. Transfer 200.0 microliter of each `back-diluted culture` sample to 96 well microplate `plate 1` in the wells indicated in the plate layout. + Maintain at 4.0 degree Celsius during transfer. +23. Transfer 200.0 microliter of `LB Broth + Chloramphenicol (34 ug/mL)` sample to wells A1:H1, A10:H10, A12:H12 of 96 well microplate `plate 1`. Maintain at 4.0 degree Celsius during transfer. These samples are blanks. + +![](fig2_cell_calibration.png) +

Fig 2: Plate layout

+ +24. Measure 0 hr absorbance timepoint of `plate 1` at 600.0 nanometer. +25. Measure 0 hr fluorescence timepoint of `plate 1` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass. +26. Cover `plate 1` samples in 96 well microplate with your choice of material to prevent evaporation. +27. Incubate all `plate 1` samples for 6.0 hour at 37.0 degree Celsius at 220 rpm. +28. Measure absorbance timepoint of `plate 1` at 600.0 nanometer at timepoints 2.0 hour, 4.0 hour, 6.0 hour. +29. Measure fluorescence timepoint of `plate 1` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass at timepoints 2.0 hour, 4.0 hour, 6.0 hour. +30. Incubate all `Tubes 1, 2 and 3` samples for 2.0 hour at 37.0 degree Celsius at 220 rpm. +31. Hold all `Tubes 1, 2 and 3` samples on ice. Reserve until the end of the experiment for absorbance and fluorescence measurements. +32. Incubate all `Tube 2` samples for 4.0 hour at 37.0 degree Celsius at 220 rpm. +33. Hold all `Tube 2` samples on ice. Reserve until the end of the experiment for absorbance and fluorescence measurements. +34. Incubate all `Tube 3` samples for 6.0 hour at 37.0 degree Celsius at 220 rpm. +35. Hold all `Tube 3` samples on ice. Reserve until the end of the experiment for absorbance and fluorescence measurements. +36. Obtain a 96 well microplate to contain `Plates 2, 3, and 4` +37. Transfer 200.0 microliter of each `Tubes 1, 2 and 3` sample to 96 well microplate `Plates 2, 3, and 4` in the wells indicated in the plate layout. + Maintain at 4.0 degree Celsius during transfer. +38. Transfer 200.0 microliter of `LB Broth + Chloramphenicol (34 ug/mL)` sample to wells A1:H1, A10:H10, A12:H12 of 96 well microplate `Plates 2, 3, and 4`. Maintain at 4.0 degree Celsius during transfer. These samples are blanks. +39. Measure absorbance timepoint of `Plates 2, 3, and 4` at 600.0 nanometer. +40. Measure fluorescence timepoint of `Plates 2, 3, and 4` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass. +41. Import data for `baseline absorbance of culture (day 2) measurements of cultures (0 hr timepoint)`, `0 hr absorbance timepoint measurements of plate 1`, `0 hr fluorescence timepoint measurements of plate 1`, `absorbance timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour`, `fluorescence timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour`, `absorbance timepoint measurements of Plates 2, 3, and 4`, `fluorescence timepoint measurements of Plates 2, 3, and 4` into provided Excel file. +--- +Timestamp: 2022-07-08 19:34:25.986146--- +Protocol version: 1.2b \ No newline at end of file From 2e9ea4fecca3fb9575919adf785bad682456b684 Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:40:57 -0500 Subject: [PATCH 06/12] pylabrobot specialization starting point --- labop/container-ontology.ttl | 42 + labop_convert/__init__.py | 1 + labop_convert/pylabrobot/__init__.py | 0 .../pylabrobot/pylabrobot_specialization.py | 752 ++++++++++++++++++ 4 files changed, 795 insertions(+) create mode 100644 labop_convert/pylabrobot/__init__.py create mode 100644 labop_convert/pylabrobot/pylabrobot_specialization.py diff --git a/labop/container-ontology.ttl b/labop/container-ontology.ttl index 417ff533..0fc0d12b 100644 --- a/labop/container-ontology.ttl +++ b/labop/container-ontology.ttl @@ -624,6 +624,22 @@ cont:Rack rdf:type owl:Class ; rdfs:subClassOf cont:LabEquipment . +############################################################ +### CARRIERS +############################################################ + +### https://sift.net/container-ontology/container-ontology#Thermocycler +cont:TipCarrier rdf:type owl:Class ; + rdfs:subClassOf cont:LabEquipment ; + rdfs:label "TipCarrier" . + + +### https://sift.net/container-ontology/container-ontology#TipRack +cont:PlateCarrier rdf:type owl:Class ; + rdfs:subClassOf cont:LabEquipment ; + rdfs:label "PlateCarrier" . + + ### https://sift.net/container-ontology/container-ontology#SLAS-1-2004 cont:SLAS-1-2004 rdf:type owl:Class ; owl:equivalentClass [ owl:intersectionOf ( [ rdf:type owl:Restriction ; @@ -1307,6 +1323,32 @@ cont:Opentrons96TipRack300uL rdf:type owl:NamedIndividual , cont:TipRack ; rdfs:label "Opentrons 96 Tip Rack 300 µL" . +################################################################## +### HAMILTON LABWARE +################################################################## + +### https://github.com/PyLabRobot/pylabrobot/blob/main/pylabrobot/resources/corning_costar/plates.py +cont:MLSTARTipCarrier4ml rdf:type owl:NamedIndividual , + cont:TipCarrier ; + rdfs:label "ML STAR Tip Carrier with 5 4ml tip with filter racks landscape" . + +### https://github.com/PyLabRobot/pylabrobot/blob/main/pylabrobot/resources/corning_costar/plates.py +cont:MLSTARTipCarrier5ml rdf:type owl:NamedIndividual , + cont:TipCarrier ; + rdfs:label "ML STAR Tip carrier with 5 5ml tip racks landscape" . + +### https://github.com/PyLabRobot/pylabrobot/blob/main/pylabrobot/resources/corning_costar/plates.py +cont:MLSTARTipCarrier3rackA rdf:type owl:NamedIndividual , + cont:TipCarrier ; + rdfs:label "ML STAR Tip carrier for 3 Racks with 96 Tips portrait revision A00" . + +### https://github.com/PyLabRobot/pylabrobot/blob/main/pylabrobot/resources/corning_costar/plates.py +cont:MLSTARTipCarrier3rackB rdf:type owl:NamedIndividual , + cont:TipCarrier ; + rdfs:label "ML STAR Tip carrier for 3 Racks with 96 Tips portrait revision B00" . + + + ### https://sift.net/container-ontology/container-ontology#PlateReader cont:PlateReader rdf:type owl:NamedIndividual . diff --git a/labop_convert/__init__.py b/labop_convert/__init__.py index 68283724..ff627d87 100644 --- a/labop_convert/__init__.py +++ b/labop_convert/__init__.py @@ -3,3 +3,4 @@ from .emeraldcloud import * from .markdown import * from .opentrons import * +from .pylabrobot import * diff --git a/labop_convert/pylabrobot/__init__.py b/labop_convert/pylabrobot/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/labop_convert/pylabrobot/pylabrobot_specialization.py b/labop_convert/pylabrobot/pylabrobot_specialization.py new file mode 100644 index 00000000..53b60d53 --- /dev/null +++ b/labop_convert/pylabrobot/pylabrobot_specialization.py @@ -0,0 +1,752 @@ +import json +import logging +import os +from typing import Dict + +import sbol3 +import tyto +import xarray as xr + +import labop +import uml +from labop.utils.plate_coordinates import get_sample_list +from labop_convert.behavior_specialization import BehaviorSpecialization + +l = logging.getLogger(__file__) +l.setLevel(logging.ERROR) + + +container_ontology_path = os.path.join( + os.path.dirname(os.path.realpath(__file__)), "../../labop/container-ontology.ttl" +) +ContO = tyto.Ontology( + path=container_ontology_path, + uri="https://sift.net/container-ontology/container-ontology", +) + +# Map pylabrobot pipette names to compatible tipracks +# left is for Pylabrobot names +# right is for LabOp names(container ontology) +COMPATIBLE_TIPS = { + "p20_single_gen2": ["opentrons_96_tiprack_10ul", "opentrons_96_filtertiprack_10ul"], + "p300_single_gen2": ["opentrons_96_tiprack_300ul"], + "p1000_single_gen2": [ + "opentrons_96_tiprack_1000ul", + "opentrons_96_filtertiprack_1000ul", + ], + "p300_multi_gen2": [], + "p20_multi_gen2": [], + "p10_single": ["opentrons_96_tiprack_10ul", "opentrons_96_filtertiprack_10ul"], + "p10_multi": ["opentrons_96_tiprack_10ul", "opentrons_96_filtertiprack_10ul"], + "p50_single": [], + "p50_multi": [], + "p300_single": ["opentrons_96_tiprack_300ul"], + "p300_multi": [], + "p1000_single": [ + "opentrons_96_tiprack_1000ul", + "opentrons_96_filtertiprack_1000ul", + ], +} + +# Map terms in the Container ontology of pylabrobot and assign them to LabOP container onthology +# its taking a LabOp term and making a correspondence to a Pylabrobot term +# left is LabOp +# right is container API name on MIcro lab star and starlet (pylabrobot) +# this is for tip carriers, tipracks and 96 well plates of various dimensions + +LABWARE_MAP = { + # this is for TIP carriers (C:\Users\Luiza\pylabrobot\pylabrobot\resources\ml_star\tip_carriers.py) + # HAMILTON ML star tip carriers + ContO[ + "ML STAR Tip carrier with 5 4ml tip with filter racks landscape" + ]: "TIP_CAR_120BC_4mlTF_A00", + ContO[ + "ML STAR Tip carrier with 5 5ml tip racks landscape" + ]: "TIP_CAR_120BC_5mlT_A00", + # ContO["ML STAR Tip carrier for 3 Racks with 96 Tips portrait [revision A00]"]: "TIP_CAR_288_A00", + # ContO["ML STAR Tip carrier for 3 Racks with 96 Tips portrait [revision B00]"]: "TIP_CAR_288_B00", + # ContO["ML STAR Tip carrier for 3 Racks with 96 Tips portrait [revision C00]"]: "TIP_CAR_288_C00", + # ContO["ML STAR Tip carrier with 3 high volume tip with filter racks portrait [revision A00]"]: "TIP_CAR_288_HTF_A00", + # ContO["ML STAR Tip carrier with 3 high volume tip with filter racks portrait [revision B00]"]: "TIP_CAR_288_HTF_B00", + # ContO["ML STAR Tip carrier with 3 high volume tip with filter racks portrait [revision C00]"]: "TIP_CAR_288_HTF_C00", + # ContO["ML STAR Tip carrier with 3 high volume tip racks portrait [revision A00]"]: "TIP_CAR_288_HT_A00", + # ContO["ML STAR Tip carrier with 3 high volume tip racks portrait [revision B00]"]: "TIP_CAR_288_HT_B00", + # ContO["ML STAR Tip carrier with 3 high volume tip racks portrait [revision C00]"]: "TIP_CAR_288_HT_C00", + # ContO["ML STAR Tip carrier with 3 low volume tip with filter racks portrait [revision A00]"]: "TIP_CAR_288_LTF_A00", + # ContO["ML STAR Tip carrier with 3 low volume tip with filter racks portrait [revision B00]"]: "TIP_CAR_288_LTF_B00", + # ContO["ML STAR Tip carrier with 3 low volume tip with filter racks portrait [revision C00]"]: "TIP_CAR_288_LTF_C00", + # ContO["ML STAR Tip carrier with 3 low volume tip racks portrait [revision A00]"]: "TIP_CAR_288_LT_A00", + # ContO["ML STAR Tip carrier with 3 low volume tip racks portrait [revision B00]"]: "TIP_CAR_288_LT_B00", + # ContO["ML STAR Tip carrier with 3 low volume tip racks portrait [revision C00]"]: "TIP_CAR_288_LT_C00", + # ContO["ML STAR Tip carrier with 3 standard volume tip with filter racks portrait [revision A00]"]: "TIP_CAR_288_STF_A00", + # ContO["ML STAR Tip carrier with 3 standard volume tip with filter racks portrait [revision B00]"]: "TIP_CAR_288_STF_B00", + # ContO["ML STAR Tip carrier with 3 standard volume tip with filter racks portrait [revision C00]"]: "TIP_CAR_288_STF_C00", + # ContO["ML STAR Tip carrier with 3 standard volume tip racks portrait [revision A00]"]: "TIP_CAR_288_ST_A00", + # ContO["ML STAR Tip carrier with 3 standard volume tip racks portrait [revision B00]"]: "TIP_CAR_288_ST_B00", + # ContO["ML STAR Tip carrier with 3 standard volume tip racks portrait [revision C00]"]: " TIP_CAR_288_ST_C00", + # ContO["ML STAR Tip carrier with 3 50ul tip with filter racks portrait [revision C00]"]: "TIP_CAR_288_TIP_50ulF_C00", + # ContO["ML STAR Tip carrier with 3 50ul tip racks portrait [revision C00]"]: "TIP_CAR_288_TIP_50ul_C00", + # ContO["ML STAR Tip carrier with 4 empty tip rack positions landscape, with Barcode Identification [revision A00]"]: "TIP_CAR_384BC_A00", + # ContO["ML STAR Tip carrier with 4 high volume tip with filter racks for 12/16 channel instruments"]: "TIP_CAR_384BC_HTF_A00", + # ContO["ML STAR Tip carrier with 4 high volume tip racks for 12/16 channel instruments"]: "TIP_CAR_384BC_HT_A00", + # ContO["ML STAR Tip carrier with 4 low volume tip with filter racks for 12/16 channel instruments"]: "TIP_CAR_384BC_LTF_A00", + # ContO["ML STAR Tip carrier with 4 low volume tip racks for 12/16 channel instruments"]: "TIP_CAR_384BC_LT_A00", + # ContO["ML STAR Tip carrier with 4 standard volume tip with filter racks for 12/16 channel instruments"]: "TIP_CAR_384BC_STF_A00", + # ContO["ML STAR Tip carrier with 4 standard volume tip with filter racks for 12/16 channel instruments"]: "TIP_CAR_384BC_ST_A00", + # ContO["ML STAR Tip carrier with 4 50ul tip with filter racks landscape [revision A00]"]: "TIP_CAR_384BC_TIP_50ulF_A00", + # ContO["ML STAR Tip carrier with 4 50ul tip racks landscape [revision A00]"]: "TIP_CAR_384BC_TIP_50ul_A00", + # ContO["ML STAR TIP Carrier for 4 Racks with 96 Tips landscape [revision A00]"]: "TIP_CAR_384_A00", + # ContO["ML STAR Tip carrier with 4 high volume tip racks for 12/16 channel instruments, no barcode identification"]: "TIP_CAR_384_HT_A00", + # ContO["ML STAR Tip carrier with 4 low volume tip with filter racks for 12/16 channel instruments, no barcode identification"]: "TIP_CAR_384_LTF_A00", + # ContO["ML STAR Tip carrier with 4 low volume tip racks for 12/16 channel instruments, no barcode identification"]: "TIP_CAR_384_LT_A00", + # ContO["ML STAR Tip carrier with 4 standard volume tip with filter racks for 12/16 channel instruments, no barcode identification [revision A00] "]: "TIP_CAR_384_STF_A00", + # ContO["ML STAR Tip carrier with 4 standard volume tip racks for 12/16 channel instruments, no barcode identification [revision A00]"]: "TIP_CAR_384_ST_A00", + # ContO["ML STAR Tip carrier with 4 50ul tip with filter racks landscape [revision A00]"]: "TIP_CAR_384_TIP_50ulF_A00", + # ContO["ML STAR Tip carrier with 4 50ul tip racks landscape [revision A00]"]: "TIP_CAR_384_TIP_50ul_A00", + # ContO["ML STAR Tip Carrier for 5 Racks with 96 Tips landscape [revision A00]"]: "TIP_CAR_480", + # ContO["NEST 96 Well Plate"]: "nest_96_wellplate_200ul_flat", + # #this is for PLATES (C:\Users\Luiza\pylabrobot\pylabrobot\resources\corning_costar\plates.py) + # #"""" Corning Costar plates """ + # ContO["Corning Costar 10 ul plate [1536]"]: "Cos_1536_10ul", + # ContO["Corning Costar deep well plate [384]"]: "Cos_384_DW", + # ContO["Corning Costar PCR plate [384]"]: "Cos_384_PCR", + # ContO["Corning Costar 1 mL deep well plate [96]"]: "Cos_96_DW_1mL", + # ContO["Corning Costar 2 mL deep well plate [96]"]: "Cos_96_DW_2mL", + # ContO["Corning Costar 500ul deep well plate [96]"]: "Cos_96_DW_500ul", + # ContO["Corning Costar EZwash plate [96]"]: "Cos_96_EZWash", + # ContO["Corning Costar FL plate [96]"]: "Cos_96_FL", + # ContO["Corning Costar filter plate [96]"]: "Cos_96_Filter", + # ContO["Corning Costar Half area plate [96]"]: "Cos_96_HalfArea", + # ContO["Corning Costar filter plate [96]"]: "Cos_96_Filter", + # ContO["Corning Costar PCR plate [96]"]: "Cos_96_PCR", + # ContO["Corning Costar ProtCryst plate [96]"]: "Cos_96_ProtCryst", + # ContO["Corning Costar SpecOps plate [96]"]: "Cos_96_SpecOps", + # ContO["Corning Costar RD plate [96]"]: "Cos_96_Rd", + # ContO["Corning Costar UV plate [96]"]: "Cos_96_UV", + # ContO["Corning Costar Vb plate [96]"]: "Cos_96_Vb", + # #this is for TIPRACKS (C:\Users\Luiza\pylabrobot\pylabrobot\resources\corning_costar\plates.py) + # #""" HAMILTON ML Star tips """ + # ContO["Tip Rack 24x 4ml Tip with Filter landscape oriented"]: "FourmlTF_L", + # ContO["Tip Rack 24x 5ml Tip landscape oriented"]: "FivemlT_L", + # ContO["Tip Rack with 96 1000ul High Volume Tip with filter"]: "HTF_L", + # ContO["Tip Rack with 96 1000ul High Volume Tip"]: "HT_L", + # ContO["Tip Rack with 96 10ul Low Volume Tip with filter"]: "LTF_L", + # ContO["Tip Rack with 96 10ul Low Volume Tip"]: "LT_L", + # ContO["Tip Rack with 96 300ul Standard Volume Tip with filter"]: "STF_L", + # ContO["Tip Rack with 96 300ul Standard Volume Tip"]: "ST_L", + # #this is for Plate carriers (C:\Users\Luiza\pylabrobot\pylabrobot\resources\corning_costar\plates.py) + # #""" Hamilton ML Star plate carriers """ + # ContO["Plate Carrier for 5 deep well 96 Well PCR Plates"]: "PLT_CAR_L5AC_A00", + # ContO["Plate Carrier for 5 plates"]: "PLT_CAR_L5AC", + # ContO["Plate Carrier with 5 adjustable (height) portrait positions for archive plates"]: "PLT_CAR_L5FLEX_AC", + # ContO["Plate Carrier with 5 adjustable (height) positions for MTP"]: "PLT_CAR_L5FLEX_MD", + # ContO["Plate Carrier with 5 adjustable (height) positions for MTP "]: "PLT_CAR_L5FLEX_MD_A00", + # ContO["Plate Carrier for 5 plates"]: "PLT_CAR_L5MD", + # ContO["Plate Carrier for 5 96/384-Well Plates"]: "PLT_CAR_L5MD_A00", + # ContO["Plate Carrier for 5 PCR plates"]: "PLT_CAR_L5PCR", + # ContO["Plate Carrier for 5 PCR landscape plates [revision 00]"]: "PLT_CAR_L5PCR_A00", + # ContO["Plate Carrier for 5 PCR landscape plates [revision 01]"]: "PLT_CAR_L5PCR_A01", + # ContO["Plate Carrier for 3 96 Deep Well Plates (portrait)"]: "PLT_CAR_P3AC_A00", + # ContO["Plate Carrier for 3 96 Deep Well Plates (portrait) [revision 01]"]: "PLT_CAR_P3AC_A01", + # ContO["Plate Carrier PLT_CAR_P3HD"]: "PLT_CAR_P3HD", + # ContO["Plate Carrier PLT_CAR_P3MD"]: "PLT_CAR_P3MD", + # ContO["Plate Carrier for 3 96/384-Well Plates (Portrait)"]: "PLT_CAR_P3MD_A00", + # ContO["Plate Carrier PLT_CAR_P3MD"]: "PLT_CAR_P3MD_A01", + # ContO["Carrier for 3 96/384-Well Plates (Portrait)"]: "PLT_CAR_P3MD", + # ContO["Plate Carrier PLT_CAR_P3MD"]: "PLT_CAR_P3MD_A01", +} + +REVERSE_LABWARE_MAP = LABWARE_MAP.__class__(map(reversed, LABWARE_MAP.items())) + + +class PylabrobotSpecialization(BehaviorSpecialization): + def __init__( + self, filename, resolutions: Dict[sbol3.Identified, str] = None + ) -> None: + super().__init__() + self.resolutions = resolutions + self.var_to_entity = {} + self.script = "" + self.script_steps = [] + self.markdown = "" + self.markdown_steps = [] + self.apilevel = "2.11" + self.configuration = {} + self.filename = filename + # Needed for using container ontology + self.container_api_addl_conditions = "(cont:availableAt value )" + + def _init_behavior_func_map(self) -> dict: + """ + This function redirects processing of each primitive to the functions + defined below. Adding additional mappings here is most likely required. + """ + return { + "https://bioprotocols.org/labop/primitives/sample_arrays/EmptyContainer": self.define_container, + "https://bioprotocols.org/labop/primitives/liquid_handling/Provision": self.provision, + "https://bioprotocols.org/labop/primitives/liquid_handling/Transfer": self.transfer_to, + "https://bioprotocols.org/labop/primitives/liquid_handling/TransferByMap": self.transfer_by_map, + "https://bioprotocols.org/labop/primitives/sample_arrays/PlateCoordinates": self.plate_coordinates, + # "https://bioprotocols.org/labop/primitives/spectrophotometry/MeasureAbsorbance": self.measure_absorbance, + "https://bioprotocols.org/labop/primitives/sample_arrays/EmptyRack": self.define_rack, + "https://bioprotocols.org/labop/primitives/sample_arrays/LoadContainerInRack": self.load_container_in_rack, + "https://bioprotocols.org/labop/primitives/sample_arrays/LoadContainerOnInstrument": self.load_container_on_instrument, + # "https://bioprotocols.org/labop/primitives/sample_arrays/LoadRackOnInstrument": self.load_racks, + "https://bioprotocols.org/labop/primitives/sample_arrays/ConfigureRobot": self.configure_robot, + "https://bioprotocols.org/labop/primitives/pcr/PCR": self.pcr, + } + + def _materials(self): + protocol = self.execution.protocol.lookup() + + materials = { + obj.name: obj + for obj in protocol.document.objects + if type(obj) is sbol3.Component + } + markdown = "\n\n## Protocol Materials:\n" + for name, material in materials.items(): + markdown += f"* [{name}]({material.types[0]})\n" + + # Compute container types and quantities + document_objects = [] + protocol.document.traverse(lambda obj: document_objects.append(obj)) + call_behavior_actions = [ + obj for obj in document_objects if type(obj) is uml.CallBehaviorAction + ] + containers = {} + for cba in call_behavior_actions: + input_names = [input.name for input in cba.inputs] + if "specification" in input_names: + container = cba.input_pin("specification").value.value.lookup() + elif "rack" in input_names: + container = cba.input_pin("rack").value.value.lookup() + elif ( + "container" in input_names + and type(cba.input_pin("container")) is uml.ValuePin + ): + container = cba.input_pin("container").value.value.lookup() + else: + continue + container_type = container.queryString + container_name = container.name if container.name else "unnamed" + qty = cba.input_pin("quantity") if "quantity" in input_names else 1 + + if container_type not in containers: + containers[container_type] = {} + containers[container_type][container_name] = qty + + for container_type, container_name_map in containers.items(): + for container_name, qty in container_name_map.items(): + container_str = ContO.get_term_by_uri(container_type) + if "TipRack" in container_type: + text = f"* {container_str}" + elif container_name == "unnamed": + text = f"* unnamed {container_str}" + else: + text = f"* `{container_name}` ({container_str})" + if qty > 1: + text += f" (x {qty})" + text += "\n" + markdown += text + + def handle_process_failure(self, record, exception): + super().handle_process_failure(record, exception) + self.script_steps.append(f"# Failure processing record: {record.identity}") + + def on_begin(self, ex: labop.ProtocolExecution): + protocol = self.execution.protocol.lookup() + apilevel = self.apilevel + self.markdown += f"# {protocol.name}\n" + self.script += ( + "from opentrons import protocol_api\n\n" + f"metadata = {{'apiLevel': '{apilevel}',\n" + f" 'description': '{protocol.description}',\n" + f" 'protocolName': '{protocol.name}'}} \n\n" + "def run(protocol: protocol_api.ProtocolContext):\n" + ) + self.data = [] + + def on_end(self, ex): + self.script += self._compile_script() + self.markdown += self._compile_markdown() + if self.filename: + with open(self.filename + ".py", "w") as f: + f.write(self.script) + with open(self.filename + ".md", "w") as f: + f.write(self.markdown) + print(f"Successful execution. Script dumped to {self.filename}.") + else: + l.warn( + "Writing output of specialization to self.data because no filename specified." + ) + self.data = f"# pylabbot Script\n ```python\n{self.script}```\n # Operator Script\n {self.markdown}" + + def _compile_script(self): + script = "" + for step in self.script_steps: + script += f" {step}\n" + return script + + def _compile_markdown(self): + markdown = self._materials() + markdown += "\n## Steps\n" + for i, step in enumerate(self.markdown_steps): + markdown += str(i + 1) + ". " + step + "\n" + return markdown + + ################################################### + # see about def _tipracks object + ################################################## + def _materials(self): + protocol = self.execution.protocol.lookup() + + materials = { + obj.name: obj + for obj in protocol.document.objects + if type(obj) is sbol3.Component + } + markdown = "\n\n## Protocol Materials:\n" + for name, material in materials.items(): + markdown += f"* [{name}]({material.types[0]})\n" + + # Compute container types and quantities + document_objects = [] + protocol.document.traverse(lambda obj: document_objects.append(obj)) + call_behavior_actions = [ + obj for obj in document_objects if type(obj) is uml.CallBehaviorAction + ] + containers = {} + for cba in call_behavior_actions: + input_names = [input.name for input in cba.inputs] + if "specification" in input_names: + container = cba.input_pin("specification").value.value.lookup() + elif "rack" in input_names: + container = cba.input_pin("rack").value.value.lookup() + elif ( + "container" in input_names + and type(cba.input_pin("container")) is uml.ValuePin + ): + container = cba.input_pin("container").value.value.lookup() + else: + continue + container_type = container.queryString + container_name = container.name if container.name else "unnamed" + qty = cba.input_pin("quantity") if "quantity" in input_names else 1 + + if container_type not in containers: + containers[container_type] = {} + containers[container_type][container_name] = qty + + for container_type, container_name_map in containers.items(): + for container_name, qty in container_name_map.items(): + container_str = ContO.get_term_by_uri(container_type) + if "TipRack" in container_type: + text = f"* {container_str}" + elif container_name == "unnamed": + text = f"* unnamed {container_str}" + else: + text = f"* `{container_name}` ({container_str})" + if qty > 1: + text += f" (x {qty})" + text += "\n" + markdown += text + + return markdown + + def _parameter_value_markdown(self, pv: labop.ParameterValue, is_output=False): + parameter = pv.parameter.lookup().property_value + value = ( + pv.value.lookup().value + if isinstance(pv.value, uml.LiteralReference) + else pv.value.value + ) + units = ( + tyto.OM.get_term_by_uri(value.unit) + if isinstance(value, sbol3.om_unit.Measure) + else None + ) + value = str(f"{value.value} {units}") if units else str(value) + if is_output: + return f"* `{parameter.name}`" + else: + return f"* `{parameter.name}` = {value}" + + def define_container( + self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + ): + call = record.call.lookup() + parameter_value_map = call.parameter_value_map() + + spec = parameter_value_map["specification"]["value"] + samples = parameter_value_map["samples"]["value"] + # SampleArray fields are initialized in primitive_execution.py + + def time_wait( + self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + ): + results = {} + call = record.call.lookup() + parameter_value_map = call.parameter_value_map() + value = parameter_value_map["amount"]["value"].value + units = parameter_value_map["amount"]["value"].unit + self.script_steps += [f"time.sleep(value)"] + + def plate_coordinates( + self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + ): + call = record.call.lookup() + parameter_value_map = call.parameter_value_map() + source = parameter_value_map["source"]["value"] + coords = parameter_value_map["coordinates"]["value"] + samples = parameter_value_map["samples"]["value"] + if not hasattr(samples, "mask") or samples.mask is None: + samples.mask = coords + + # write correspondence for provision primitive + def provision( + self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + ): + results = {} + call = record.call.lookup() + parameter_value_map = call.parameter_value_map() + destination = parameter_value_map["destination"]["value"] + value = parameter_value_map["amount"]["value"].value + units = parameter_value_map["amount"]["value"].unit + units = tyto.OM.get_term_by_uri(units) + resource = parameter_value_map["resource"]["value"] + amount = parameter_value_map["amount"]["value"] + amount = measurement_to_text(amount) + coords = "" + coords = ( + destination.get_parent() + .get_parent() + .token_source.lookup() + .node.lookup() + .input_pin("coordinates") + .value.value + ) + upstream_execution = get_token_source("destination", record) + container = upstream_execution.call.lookup().parameter_value_map()["container"][ + "value" + ] + + behavior_type = get_behavior_type(upstream_execution) + if behavior_type == "LoadContainerInRack": + coords = upstream_execution.call.lookup().parameter_value_map()[ + "coordinates" + ]["value"] + upstream_execution = get_token_source("slots", upstream_execution) + rack = upstream_execution.call.lookup().parameter_value_map()[ + "specification" + ]["value"] + else: + raise NotImplementedError( + f'A "Provision" call cannot follow a "{behavior_type}" call' + ) + + container_str = ( + f"`{container.name}`" if container.name else container.queryString + ) + rack_str = f"`{rack.name}`" if rack.name else rack.queryString + text = f"Fill {amount} of {resource.name} into {container_str} located in {coords} of {rack_str}" + self.markdown_steps += [text] + + # write correspondence for transfer primitive + def transfer_to( + self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + ): + results = {} + call = record.call.lookup() + parameter_value_map = call.parameter_value_map() + destination = parameter_value_map["destination"]["value"] + source = parameter_value_map["source"]["value"] + value = parameter_value_map["amount"]["value"].value + units = parameter_value_map["amount"]["value"].unit + units = tyto.OM.get_term_by_uri(units) + OT2Pipette = "left" + + # Trace the "source" pin back to the EmptyContainer to retrieve the + # ContainerSpec for the destination container + upstream_execution = record.get_token_source( + parameter_value_map["source"]["parameter"].property_value + ) + behavior_type = get_behavior_type(upstream_execution) + if behavior_type == "PlateCoordinates": + upstream_map = upstream_execution.call.lookup().parameter_value_map() + coordinates = upstream_map["coordinates"]["value"] + upstream_execution = upstream_execution.get_token_source( + upstream_map["source"]["parameter"].property_value + ) # EmptyContainer + parameter_value_map = upstream_execution.call.lookup().parameter_value_map() + source_container = parameter_value_map["specification"]["value"] + elif behavior_type == "LoadContainerInRack": + upstream_execution = upstream_execution.get_token_source( + upstream_map["slots"]["parameter"].property_value + ) # EmptyRack + parameter_value_map = upstream_execution.call.lookup().parameter_value_map() + source_container = parameter_value_map["specification"]["value"] + elif behavior_type == "LoadContainerOnInstrument": + upstream_map = upstream_execution.call.lookup().parameter_value_map() + coordinates = upstream_map["slots"]["value"] + upstream_execution = upstream_execution.get_token_source( + upstream_map["container"]["parameter"].property_value + ) # EmptyContainer + parameter_value_map = upstream_execution.call.lookup().parameter_value_map() + source_container = parameter_value_map["specification"]["value"] + + else: + raise Exception(f'Invalid input pin "source" for Transfer.') + + # Map the source container to a variable name in the pylabrobot api script + source_name = None + for deck, labware in self.configuration.items(): + if labware == source_container: + source_name = f"labware{deck}" + break + if not source_name: + raise Exception(f"{source_container} is not loaded.") + + # Trace the "destination" pin back to the EmptyContainer execution + # to retrieve the ContainerSpec for the destination container + parameter_value_map = call.parameter_value_map() + upstream_execution = record.get_token_source( + parameter_value_map["destination"]["parameter"].property_value + ) + behavior_type = get_behavior_type(upstream_execution) + if behavior_type == "PlateCoordinates": + upstream_map = upstream_execution.call.lookup().parameter_value_map() + coordinates = upstream_map["coordinates"]["value"] + upstream_execution = upstream_execution.get_token_source( + upstream_map["source"]["parameter"].property_value + ) # EmptyContainer + parameter_value_map = upstream_execution.call.lookup().parameter_value_map() + destination_container = parameter_value_map["specification"]["value"] + + elif behavior_type == "LoadContainerOnInstrument": + upstream_map = upstream_execution.call.lookup().parameter_value_map() + coordinates = upstream_map["slots"]["value"] + upstream_execution = upstream_execution.get_token_source( + upstream_map["container"]["parameter"].property_value + ) # EmptyContainer + parameter_value_map = upstream_execution.call.lookup().parameter_value_map() + destination_container = parameter_value_map["specification"]["value"] + + else: + raise Exception(f'Invalid input pin "destination" for Transfer.') + destination_name = None + for deck, labware in self.configuration.items(): + if type(labware) is sbol3.Agent and hasattr(labware, "configuration"): + # If labware is a hardware module (i.e. Agent), + # then we need to look further to find out what conta + coordinate = get_sample_list(destination.mask)[0] + if coordinate in labware.configuration: + labware = labware.configuration[coordinate] + if labware == destination_container: + destination_name = f"labware{deck}" + break + if not destination_name: + raise Exception(f"{destination_container} is not loaded.") + + # TODO: automatically choose pipette based on transferred volume + if not self.configuration: + raise Exception( + "Transfer call failed. Use ConfigureInstrument to configure a pipette" + ) + pipette = self.configuration["left"] + + comment = record.node.lookup().name + comment = ( + "# " + comment + if comment + else "# Transfer ActivityNode name is not defined." + ) + + source_str = source.mask + destination_str = destination.mask + for c_source in source.get_coordinates(): + for c_destination in destination.get_coordinates(): + self.script_steps += [ + f"{pipette.display_id}.transfer({value}, {source_name}['{c_source}'], {destination_name}['{c_destination}']) {comment}" + ] + + # write correspondence for transferbymap primitive + def transfer_by_map( + self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + ): + results = {} + call = record.call.lookup() + parameter_value_map = call.parameter_value_map() + destination = parameter_value_map["destination"]["value"] + source = parameter_value_map["source"]["value"] + plan = parameter_value_map["plan"]["value"] + temperature = parameter_value_map["temperature"]["value"] + value = parameter_value_map["amount"]["value"].value + units = parameter_value_map["amount"]["value"].unit + units = tyto.OM.get_term_by_uri(units) + pylabrobot = "left" + + # Trace the "source" pin back to the EmptyContainer to retrieve the + # ContainerSpec for the destination container + upstream_execution = record.get_token_source("source") + behavior_type = get_behavior_type(upstream_execution) + if behavior_type == "LoadContainerInRack": + upstream_execution = upstream_execution.get_token_source( + "slots" + ) # EmptyRack + parameter_value_map = upstream_execution.call.lookup().parameter_value_map() + source_container = parameter_value_map["specification"]["value"] + else: + raise Exception(f'Invalid input pin "source" for Transfer.') + + # Map the source container to a variable name in the OT2 api script + source_name = None + for deck, labware in self.configuration.items(): + if labware == source_container: + source_name = f"labware{deck}" + break + if not source_name: + raise Exception(f"{source_container} is not loaded.") + + # Trace the "destination" pin back to the EmptyContainer execution + # to retrieve the ContainerSpec for the destination container + upstream_execution = record.get_token_source("destination") + behavior_type = get_behavior_type(upstream_execution) + if behavior_type == "PlateCoordinates": + upstream_execution = get_token_source( + "source", upstream_execution + ) # EmptyContainer + parameter_value_map = upstream_execution.call.lookup().parameter_value_map() + destination_container = parameter_value_map["specification"]["value"] + else: + raise Exception(f'Invalid input pin "destination" for Transfer.') + destination_name = None + for deck, labware in self.configuration.items(): + if labware == destination_container: + destination_name = f"labware{deck}" + break + if not destination_name: + raise Exception(f"{destination_container} is not loaded.") + + # TODO: automatically choose pipette based on transferred volume + if not self.configuration: + raise Exception( + "Transfer call failed. Use ConfigureInstrument to configure a pipette" + ) + pipette = self.configuration["left"] + + source_str = source.mask + destination_str = destination.mask + for c_source in get_sample_list(source.mask): + for c_destination in get_sample_list(destination.mask): + self.script_steps += [ + f"{pipette.display_id}.transfer({value}, {source_name}['{c_source}'], {destination_name}['{c_destination}'])" + ] + + def define_rack( + self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + ): + call = record.call.lookup() + parameter_value_map = call.parameter_value_map() + + spec = parameter_value_map["specification"]["value"] + slots = parameter_value_map["slots"]["value"] + + # FIXME the protocol var_to_entity mapping links variables created in + # the execution trace with real values assigned here, such as + # container below. This mapping can be used in later processing to + # reuse bindings. + # + # self.var_to_entity[samples_var] = container + + # OT2Props = json.loads(spec.OT2SpecificProps) + # OT2Deck = OT2Props["deck"] + + def load_container_in_rack( + self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + ): + call = record.call.lookup() + parameter_value_map = call.parameter_value_map() + container: labop.ContainerSpec = parameter_value_map["container"]["value"] + coords: str = ( + parameter_value_map["coordinates"]["value"] + if "coordinates" in parameter_value_map + else "A1" + ) + slots: labop.SampleCollection = parameter_value_map["slots"]["value"] + samples: labop.SampleMask = parameter_value_map["samples"]["value"] + + # TODO: validate coordinates for the given container spec + samples.source = slots + samples.mask = coords + container_str = get_container_name(container) + + rack_str = "" + try: + # TODO: replace this lookup with a call to get_token_source() + rack = ( + slots.get_parent() + .get_parent() + .token_source.lookup() + .node.lookup() + .input_pin("specification") + .value.value.lookup() + ) + rack_str = get_container_name(rack) + except Exception as e: + print(e) + + aliquots = get_sample_list(coords) + if len(aliquots) == 1: + self.markdown_steps += [ + f"Load {container_str} in slot {coords} of {rack_str}" + ] + elif len(aliquots) > 1: + self.markdown_steps += [ + f"Load {container_str}s in slots {coords} of {rack_str}" + ] + + def load_container_on_instrument( + self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + ): + call = record.call.lookup() + parameter_value_map = call.parameter_value_map() + container_spec: labop.ContainerSpec = parameter_value_map["specification"][ + "value" + ] + slots: str = ( + parameter_value_map["slots"]["value"] + if "slots" in parameter_value_map + else "A1" + ) + instrument: sbol3.Agent = parameter_value_map["instrument"]["value"] + samples: labop.SampleArray = parameter_value_map["samples"]["value"] + + # Assume 96 well plate + aliquots = get_sample_list(geometry="A1:H12") + samples.initial_contents = json.dumps( + xr.DataArray(aliquots, dims=("aliquot")).to_dict() + ) + + # upstream_ex = get_token_source('container', record) + # container_spec = upstream_ex.call.lookup().parameter_value_map()['specification']['value'] + + container_types = self.resolve_container_spec(container_spec) + selected_container_type = self.check_lims_inventory(container_types) + container_api_name = LABWARE_MAP[selected_container_type] + container_str = get_container_name(container_spec) + + # TODO: need to specify instrument + deck = self.get_instrument_deck(instrument) + self.markdown_steps += [ + f"Load {container_str} in {slots} of Deck of pylabrobot instrument" + ] + self.script_steps += [ + f"labware{deck} = {instrument.display_id}.load_labware('{container_api_name}')" + ] + + # Keep track of instrument configuration + if not hasattr(instrument, "configuration"): + instrument.configuration = {} + for c in get_sample_list(slots): + instrument.configuration[c] = container_spec From 03696b5de2e0db1ccf6a53a00e2d9fceab142249 Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:41:33 -0500 Subject: [PATCH 07/12] harness work, validation bug fix --- artifacts/DefaultBehaviorSpecialization.json | 1 + artifacts/ludox_protocol.diagram.pdf | Bin 0 -> 34978 bytes artifacts/ludox_protocol.nt | 1792 +++++++++++++++++ artifacts/opentrons_toy_protocol.diagram.pdf | Bin 0 -> 5834 bytes .../opentrons_toy_protocol.diagram.pdf.pdf | Bin 0 -> 29220 bytes artifacts/opentrons_toy_protocol.md | 19 + artifacts/sample_graph_0 | 487 +++++ artifacts/sample_graph_0.pdf | Bin 0 -> 33748 bytes artifacts/sample_graph_1 | 499 +++++ artifacts/sample_graph_1.pdf | Bin 0 -> 35067 bytes artifacts/sample_graph_2 | 615 ++++++ artifacts/sample_graph_2.pdf | Bin 0 -> 37162 bytes .../multicolor-particle-calibration.py | 76 +- examples/protocols/ludox/LUDOX_protocol.py | 151 +- .../opentrons_ludox_example.py | 300 ++- .../opentrons-pcr/opentrons_pcr_example.py | 25 +- .../opentrons-toy/opentrons_toy_protocol.py | 60 +- .../pH_calibration/pH_calibration.py | 2 - labop/constants.py | 16 + labop/container-ontology.ttl | 32 +- labop/lib/plate_handling.py | 7 + labop/lib/plate_handling.ttl | 34 + labop/utils/harness.py | 305 +++ labop_convert/behavior_specialization.py | 5 + .../markdown/markdown_specialization.py | 4 +- .../pylabrobot/pylabrobot_specialization.py | 337 ++-- notebooks/Opentrons.ipynb | 7 +- notebooks/labop_author_demo.ipynb | 13 +- notebooks/labop_demo.ipynb | 13 +- opentrons_toy_protocol_labop.py.md | 11 + opentrons_toy_protocol_labop.py.py | 17 + setup.py | 8 +- test/test_LUDOX_protocol.py | 2 +- test/test_decision_nodes.py | 2 +- test/test_examples.py | 81 + test/test_opentrons.py | 5 +- test/test_sampledata.py | 2 +- uml/activity.py | 7 +- uml/utils.py | 6 +- 39 files changed, 4403 insertions(+), 538 deletions(-) create mode 100644 artifacts/DefaultBehaviorSpecialization.json create mode 100644 artifacts/ludox_protocol.diagram.pdf create mode 100644 artifacts/ludox_protocol.nt create mode 100644 artifacts/opentrons_toy_protocol.diagram.pdf create mode 100644 artifacts/opentrons_toy_protocol.diagram.pdf.pdf create mode 100644 artifacts/opentrons_toy_protocol.md create mode 100644 artifacts/sample_graph_0 create mode 100644 artifacts/sample_graph_0.pdf create mode 100644 artifacts/sample_graph_1 create mode 100644 artifacts/sample_graph_1.pdf create mode 100644 artifacts/sample_graph_2 create mode 100644 artifacts/sample_graph_2.pdf create mode 100644 labop/constants.py create mode 100644 labop/utils/harness.py create mode 100644 opentrons_toy_protocol_labop.py.md create mode 100644 opentrons_toy_protocol_labop.py.py create mode 100644 test/test_examples.py diff --git a/artifacts/DefaultBehaviorSpecialization.json b/artifacts/DefaultBehaviorSpecialization.json new file mode 100644 index 00000000..dc98360b --- /dev/null +++ b/artifacts/DefaultBehaviorSpecialization.json @@ -0,0 +1 @@ +[{"identity": "https://labop.io/examples/protocols/ludox/harness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324/CallBehaviorAction1", "behavior": "https://labop.io/examples/protocols/ludox/iGEM_LUDOX_OD_calibration_2018", "parameters": {}}, {"identity": "https://labop.io/examples/protocols/ludox/iGEM_LUDOX_OD_calibration_2018/CallBehaviorAction1", "behavior": "https://bioprotocols.org/labop/primitives/sample_arrays/EmptyContainer", "parameters": {"specification": "calibration plate"}}, {"identity": "https://labop.io/examples/protocols/ludox/iGEM_LUDOX_OD_calibration_2018/CallBehaviorAction2", "behavior": "https://bioprotocols.org/labop/primitives/sample_arrays/PlateCoordinates", "parameters": {"source": "SampleArray(name=calibration plate, container_type=https://labop.io/examples/protocols/ludox/plateRequirement, initial_contents=%7B%22coords%22%3A%20%7B%22reagent%22%3A%20%7B%22dims%22%3A%20%5B%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5D%7D%2C%20%22container%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22https%3A//labop.io/examples/protocols/ludox/plateRequirement%22%5D%7D%2C%20%22location%22%3A%20%7B%22dims%22%3A%20%5B%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22A1%22%2C%20%22B1%22%2C%20%22C1%22%2C%20%22D1%22%2C%20%22E1%22%2C%20%22F1%22%2C%20%22G1%22%2C%20%22H1%22%2C%20%22A2%22%2C%20%22B2%22%2C%20%22C2%22%2C%20%22D2%22%2C%20%22E2%22%2C%20%22F2%22%2C%20%22G2%22%2C%20%22H2%22%2C%20%22A3%22%2C%20%22B3%22%2C%20%22C3%22%2C%20%22D3%22%2C%20%22E3%22%2C%20%22F3%22%2C%20%22G3%22%2C%20%22H3%22%2C%20%22A4%22%2C%20%22B4%22%2C%20%22C4%22%2C%20%22D4%22%2C%20%22E4%22%2C%20%22F4%22%2C%20%22G4%22%2C%20%22H4%22%2C%20%22A5%22%2C%20%22B5%22%2C%20%22C5%22%2C%20%22D5%22%2C%20%22E5%22%2C%20%22F5%22%2C%20%22G5%22%2C%20%22H5%22%2C%20%22A6%22%2C%20%22B6%22%2C%20%22C6%22%2C%20%22D6%22%2C%20%22E6%22%2C%20%22F6%22%2C%20%22G6%22%2C%20%22H6%22%2C%20%22A7%22%2C%20%22B7%22%2C%20%22C7%22%2C%20%22D7%22%2C%20%22E7%22%2C%20%22F7%22%2C%20%22G7%22%2C%20%22H7%22%2C%20%22A8%22%2C%20%22B8%22%2C%20%22C8%22%2C%20%22D8%22%2C%20%22E8%22%2C%20%22F8%22%2C%20%22G8%22%2C%20%22H8%22%2C%20%22A9%22%2C%20%22B9%22%2C%20%22C9%22%2C%20%22D9%22%2C%20%22E9%22%2C%20%22F9%22%2C%20%22G9%22%2C%20%22H9%22%2C%20%22A10%22%2C%20%22B10%22%2C%20%22C10%22%2C%20%22D10%22%2C%20%22E10%22%2C%20%22F10%22%2C%20%22G10%22%2C%20%22H10%22%2C%20%22A11%22%2C%20%22B11%22%2C%20%22C11%22%2C%20%22D11%22%2C%20%22E11%22%2C%20%22F11%22%2C%20%22G11%22%2C%20%22H11%22%2C%20%22A12%22%2C%20%22B12%22%2C%20%22C12%22%2C%20%22D12%22%2C%20%22E12%22%2C%20%22F12%22%2C%20%22G12%22%2C%20%22H12%22%5D%7D%2C%20%22sample%22%3A%20%7B%22dims%22%3A%20%5B%22sample%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%2C%20%22sample_None_4%22%2C%20%22sample_None_5%22%2C%20%22sample_None_6%22%2C%20%22sample_None_7%22%2C%20%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%2C%20%22sample_None_12%22%2C%20%22sample_None_13%22%2C%20%22sample_None_14%22%2C%20%22sample_None_15%22%2C%20%22sample_None_16%22%2C%20%22sample_None_17%22%2C%20%22sample_None_18%22%2C%20%22sample_None_19%22%2C%20%22sample_None_20%22%2C%20%22sample_None_21%22%2C%20%22sample_None_22%22%2C%20%22sample_None_23%22%2C%20%22sample_None_24%22%2C%20%22sample_None_25%22%2C%20%22sample_None_26%22%2C%20%22sample_None_27%22%2C%20%22sample_None_28%22%2C%20%22sample_None_29%22%2C%20%22sample_None_30%22%2C%20%22sample_None_31%22%2C%20%22sample_None_32%22%2C%20%22sample_None_33%22%2C%20%22sample_None_34%22%2C%20%22sample_None_35%22%2C%20%22sample_None_36%22%2C%20%22sample_None_37%22%2C%20%22sample_None_38%22%2C%20%22sample_None_39%22%2C%20%22sample_None_40%22%2C%20%22sample_None_41%22%2C%20%22sample_None_42%22%2C%20%22sample_None_43%22%2C%20%22sample_None_44%22%2C%20%22sample_None_45%22%2C%20%22sample_None_46%22%2C%20%22sample_None_47%22%2C%20%22sample_None_48%22%2C%20%22sample_None_49%22%2C%20%22sample_None_50%22%2C%20%22sample_None_51%22%2C%20%22sample_None_52%22%2C%20%22sample_None_53%22%2C%20%22sample_None_54%22%2C%20%22sample_None_55%22%2C%20%22sample_None_56%22%2C%20%22sample_None_57%22%2C%20%22sample_None_58%22%2C%20%22sample_None_59%22%2C%20%22sample_None_60%22%2C%20%22sample_None_61%22%2C%20%22sample_None_62%22%2C%20%22sample_None_63%22%2C%20%22sample_None_64%22%2C%20%22sample_None_65%22%2C%20%22sample_None_66%22%2C%20%22sample_None_67%22%2C%20%22sample_None_68%22%2C%20%22sample_None_69%22%2C%20%22sample_None_70%22%2C%20%22sample_None_71%22%2C%20%22sample_None_72%22%2C%20%22sample_None_73%22%2C%20%22sample_None_74%22%2C%20%22sample_None_75%22%2C%20%22sample_None_76%22%2C%20%22sample_None_77%22%2C%20%22sample_None_78%22%2C%20%22sample_None_79%22%2C%20%22sample_None_80%22%2C%20%22sample_None_81%22%2C%20%22sample_None_82%22%2C%20%22sample_None_83%22%2C%20%22sample_None_84%22%2C%20%22sample_None_85%22%2C%20%22sample_None_86%22%2C%20%22sample_None_87%22%2C%20%22sample_None_88%22%2C%20%22sample_None_89%22%2C%20%22sample_None_90%22%2C%20%22sample_None_91%22%2C%20%22sample_None_92%22%2C%20%22sample_None_93%22%2C%20%22sample_None_94%22%2C%20%22sample_None_95%22%5D%7D%7D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22dims%22%3A%20%7B%22reagent%22%3A%200%2C%20%22container%22%3A%201%2C%20%22location%22%3A%2096%2C%20%22sample%22%3A%2096%7D%2C%20%22data_vars%22%3A%20%7B%22contents%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%2C%20%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%5D%5D%7D%2C%20%22sample_location%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%2C%20%22sample_None_4%22%2C%20%22sample_None_5%22%2C%20%22sample_None_6%22%2C%20%22sample_None_7%22%2C%20%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%2C%20%22sample_None_12%22%2C%20%22sample_None_13%22%2C%20%22sample_None_14%22%2C%20%22sample_None_15%22%2C%20%22sample_None_16%22%2C%20%22sample_None_17%22%2C%20%22sample_None_18%22%2C%20%22sample_None_19%22%2C%20%22sample_None_20%22%2C%20%22sample_None_21%22%2C%20%22sample_None_22%22%2C%20%22sample_None_23%22%2C%20%22sample_None_24%22%2C%20%22sample_None_25%22%2C%20%22sample_None_26%22%2C%20%22sample_None_27%22%2C%20%22sample_None_28%22%2C%20%22sample_None_29%22%2C%20%22sample_None_30%22%2C%20%22sample_None_31%22%2C%20%22sample_None_32%22%2C%20%22sample_None_33%22%2C%20%22sample_None_34%22%2C%20%22sample_None_35%22%2C%20%22sample_None_36%22%2C%20%22sample_None_37%22%2C%20%22sample_None_38%22%2C%20%22sample_None_39%22%2C%20%22sample_None_40%22%2C%20%22sample_None_41%22%2C%20%22sample_None_42%22%2C%20%22sample_None_43%22%2C%20%22sample_None_44%22%2C%20%22sample_None_45%22%2C%20%22sample_None_46%22%2C%20%22sample_None_47%22%2C%20%22sample_None_48%22%2C%20%22sample_None_49%22%2C%20%22sample_None_50%22%2C%20%22sample_None_51%22%2C%20%22sample_None_52%22%2C%20%22sample_None_53%22%2C%20%22sample_None_54%22%2C%20%22sample_None_55%22%2C%20%22sample_None_56%22%2C%20%22sample_None_57%22%2C%20%22sample_None_58%22%2C%20%22sample_None_59%22%2C%20%22sample_None_60%22%2C%20%22sample_None_61%22%2C%20%22sample_None_62%22%2C%20%22sample_None_63%22%2C%20%22sample_None_64%22%2C%20%22sample_None_65%22%2C%20%22sample_None_66%22%2C%20%22sample_None_67%22%2C%20%22sample_None_68%22%2C%20%22sample_None_69%22%2C%20%22sample_None_70%22%2C%20%22sample_None_71%22%2C%20%22sample_None_72%22%2C%20%22sample_None_73%22%2C%20%22sample_None_74%22%2C%20%22sample_None_75%22%2C%20%22sample_None_76%22%2C%20%22sample_None_77%22%2C%20%22sample_None_78%22%2C%20%22sample_None_79%22%2C%20%22sample_None_80%22%2C%20%22sample_None_81%22%2C%20%22sample_None_82%22%2C%20%22sample_None_83%22%2C%20%22sample_None_84%22%2C%20%22sample_None_85%22%2C%20%22sample_None_86%22%2C%20%22sample_None_87%22%2C%20%22sample_None_88%22%2C%20%22sample_None_89%22%2C%20%22sample_None_90%22%2C%20%22sample_None_91%22%2C%20%22sample_None_92%22%2C%20%22sample_None_93%22%2C%20%22sample_None_94%22%2C%20%22sample_None_95%22%5D%5D%7D%7D%7D)", "coordinates": "A1:D1"}}, {"identity": "https://labop.io/examples/protocols/ludox/iGEM_LUDOX_OD_calibration_2018/CallBehaviorAction3", "behavior": "https://bioprotocols.org/labop/primitives/liquid_handling/Provision", "parameters": {"resource": "Water, sterile-filtered, BioReagent, suitable for cell culture", "destination": "SampleMask(name=None, source=https://labop.io/examples/protocols/ludox/harness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324/ActivityEdgeFlow9/LiteralIdentified1/SampleArray1, mask=%7B%22coords%22%3A%20%7B%22reagent%22%3A%20%7B%22dims%22%3A%20%5B%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5D%7D%2C%20%22container%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22https%3A//labop.io/examples/protocols/ludox/plateRequirement%22%5D%7D%2C%20%22location%22%3A%20%7B%22dims%22%3A%20%5B%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22A1%22%2C%20%22B1%22%2C%20%22C1%22%2C%20%22D1%22%5D%7D%2C%20%22sample%22%3A%20%7B%22dims%22%3A%20%5B%22sample%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%5D%7D%7D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22dims%22%3A%20%7B%22container%22%3A%201%2C%20%22location%22%3A%204%2C%20%22reagent%22%3A%200%2C%20%22sample%22%3A%204%7D%2C%20%22data_vars%22%3A%20%7B%22contents%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%2C%20%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%5D%5D%7D%2C%20%22sample_location%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%5D%5D%7D%7D%7D)", "amount": "100.0 microliter"}}, {"identity": "https://labop.io/examples/protocols/ludox/iGEM_LUDOX_OD_calibration_2018/CallBehaviorAction4", "behavior": "https://bioprotocols.org/labop/primitives/sample_arrays/PlateCoordinates", "parameters": {"source": "SampleArray(name=calibration plate, container_type=https://labop.io/examples/protocols/ludox/plateRequirement, initial_contents=%7B%22coords%22%3A%20%7B%22reagent%22%3A%20%7B%22dims%22%3A%20%5B%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5D%7D%2C%20%22container%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22https%3A//labop.io/examples/protocols/ludox/plateRequirement%22%5D%7D%2C%20%22location%22%3A%20%7B%22dims%22%3A%20%5B%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22A1%22%2C%20%22B1%22%2C%20%22C1%22%2C%20%22D1%22%2C%20%22E1%22%2C%20%22F1%22%2C%20%22G1%22%2C%20%22H1%22%2C%20%22A2%22%2C%20%22B2%22%2C%20%22C2%22%2C%20%22D2%22%2C%20%22E2%22%2C%20%22F2%22%2C%20%22G2%22%2C%20%22H2%22%2C%20%22A3%22%2C%20%22B3%22%2C%20%22C3%22%2C%20%22D3%22%2C%20%22E3%22%2C%20%22F3%22%2C%20%22G3%22%2C%20%22H3%22%2C%20%22A4%22%2C%20%22B4%22%2C%20%22C4%22%2C%20%22D4%22%2C%20%22E4%22%2C%20%22F4%22%2C%20%22G4%22%2C%20%22H4%22%2C%20%22A5%22%2C%20%22B5%22%2C%20%22C5%22%2C%20%22D5%22%2C%20%22E5%22%2C%20%22F5%22%2C%20%22G5%22%2C%20%22H5%22%2C%20%22A6%22%2C%20%22B6%22%2C%20%22C6%22%2C%20%22D6%22%2C%20%22E6%22%2C%20%22F6%22%2C%20%22G6%22%2C%20%22H6%22%2C%20%22A7%22%2C%20%22B7%22%2C%20%22C7%22%2C%20%22D7%22%2C%20%22E7%22%2C%20%22F7%22%2C%20%22G7%22%2C%20%22H7%22%2C%20%22A8%22%2C%20%22B8%22%2C%20%22C8%22%2C%20%22D8%22%2C%20%22E8%22%2C%20%22F8%22%2C%20%22G8%22%2C%20%22H8%22%2C%20%22A9%22%2C%20%22B9%22%2C%20%22C9%22%2C%20%22D9%22%2C%20%22E9%22%2C%20%22F9%22%2C%20%22G9%22%2C%20%22H9%22%2C%20%22A10%22%2C%20%22B10%22%2C%20%22C10%22%2C%20%22D10%22%2C%20%22E10%22%2C%20%22F10%22%2C%20%22G10%22%2C%20%22H10%22%2C%20%22A11%22%2C%20%22B11%22%2C%20%22C11%22%2C%20%22D11%22%2C%20%22E11%22%2C%20%22F11%22%2C%20%22G11%22%2C%20%22H11%22%2C%20%22A12%22%2C%20%22B12%22%2C%20%22C12%22%2C%20%22D12%22%2C%20%22E12%22%2C%20%22F12%22%2C%20%22G12%22%2C%20%22H12%22%5D%7D%2C%20%22sample%22%3A%20%7B%22dims%22%3A%20%5B%22sample%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%2C%20%22sample_None_4%22%2C%20%22sample_None_5%22%2C%20%22sample_None_6%22%2C%20%22sample_None_7%22%2C%20%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%2C%20%22sample_None_12%22%2C%20%22sample_None_13%22%2C%20%22sample_None_14%22%2C%20%22sample_None_15%22%2C%20%22sample_None_16%22%2C%20%22sample_None_17%22%2C%20%22sample_None_18%22%2C%20%22sample_None_19%22%2C%20%22sample_None_20%22%2C%20%22sample_None_21%22%2C%20%22sample_None_22%22%2C%20%22sample_None_23%22%2C%20%22sample_None_24%22%2C%20%22sample_None_25%22%2C%20%22sample_None_26%22%2C%20%22sample_None_27%22%2C%20%22sample_None_28%22%2C%20%22sample_None_29%22%2C%20%22sample_None_30%22%2C%20%22sample_None_31%22%2C%20%22sample_None_32%22%2C%20%22sample_None_33%22%2C%20%22sample_None_34%22%2C%20%22sample_None_35%22%2C%20%22sample_None_36%22%2C%20%22sample_None_37%22%2C%20%22sample_None_38%22%2C%20%22sample_None_39%22%2C%20%22sample_None_40%22%2C%20%22sample_None_41%22%2C%20%22sample_None_42%22%2C%20%22sample_None_43%22%2C%20%22sample_None_44%22%2C%20%22sample_None_45%22%2C%20%22sample_None_46%22%2C%20%22sample_None_47%22%2C%20%22sample_None_48%22%2C%20%22sample_None_49%22%2C%20%22sample_None_50%22%2C%20%22sample_None_51%22%2C%20%22sample_None_52%22%2C%20%22sample_None_53%22%2C%20%22sample_None_54%22%2C%20%22sample_None_55%22%2C%20%22sample_None_56%22%2C%20%22sample_None_57%22%2C%20%22sample_None_58%22%2C%20%22sample_None_59%22%2C%20%22sample_None_60%22%2C%20%22sample_None_61%22%2C%20%22sample_None_62%22%2C%20%22sample_None_63%22%2C%20%22sample_None_64%22%2C%20%22sample_None_65%22%2C%20%22sample_None_66%22%2C%20%22sample_None_67%22%2C%20%22sample_None_68%22%2C%20%22sample_None_69%22%2C%20%22sample_None_70%22%2C%20%22sample_None_71%22%2C%20%22sample_None_72%22%2C%20%22sample_None_73%22%2C%20%22sample_None_74%22%2C%20%22sample_None_75%22%2C%20%22sample_None_76%22%2C%20%22sample_None_77%22%2C%20%22sample_None_78%22%2C%20%22sample_None_79%22%2C%20%22sample_None_80%22%2C%20%22sample_None_81%22%2C%20%22sample_None_82%22%2C%20%22sample_None_83%22%2C%20%22sample_None_84%22%2C%20%22sample_None_85%22%2C%20%22sample_None_86%22%2C%20%22sample_None_87%22%2C%20%22sample_None_88%22%2C%20%22sample_None_89%22%2C%20%22sample_None_90%22%2C%20%22sample_None_91%22%2C%20%22sample_None_92%22%2C%20%22sample_None_93%22%2C%20%22sample_None_94%22%2C%20%22sample_None_95%22%5D%7D%7D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22dims%22%3A%20%7B%22reagent%22%3A%200%2C%20%22container%22%3A%201%2C%20%22location%22%3A%2096%2C%20%22sample%22%3A%2096%7D%2C%20%22data_vars%22%3A%20%7B%22contents%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%2C%20%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%5D%5D%7D%2C%20%22sample_location%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%2C%20%22sample_None_4%22%2C%20%22sample_None_5%22%2C%20%22sample_None_6%22%2C%20%22sample_None_7%22%2C%20%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%2C%20%22sample_None_12%22%2C%20%22sample_None_13%22%2C%20%22sample_None_14%22%2C%20%22sample_None_15%22%2C%20%22sample_None_16%22%2C%20%22sample_None_17%22%2C%20%22sample_None_18%22%2C%20%22sample_None_19%22%2C%20%22sample_None_20%22%2C%20%22sample_None_21%22%2C%20%22sample_None_22%22%2C%20%22sample_None_23%22%2C%20%22sample_None_24%22%2C%20%22sample_None_25%22%2C%20%22sample_None_26%22%2C%20%22sample_None_27%22%2C%20%22sample_None_28%22%2C%20%22sample_None_29%22%2C%20%22sample_None_30%22%2C%20%22sample_None_31%22%2C%20%22sample_None_32%22%2C%20%22sample_None_33%22%2C%20%22sample_None_34%22%2C%20%22sample_None_35%22%2C%20%22sample_None_36%22%2C%20%22sample_None_37%22%2C%20%22sample_None_38%22%2C%20%22sample_None_39%22%2C%20%22sample_None_40%22%2C%20%22sample_None_41%22%2C%20%22sample_None_42%22%2C%20%22sample_None_43%22%2C%20%22sample_None_44%22%2C%20%22sample_None_45%22%2C%20%22sample_None_46%22%2C%20%22sample_None_47%22%2C%20%22sample_None_48%22%2C%20%22sample_None_49%22%2C%20%22sample_None_50%22%2C%20%22sample_None_51%22%2C%20%22sample_None_52%22%2C%20%22sample_None_53%22%2C%20%22sample_None_54%22%2C%20%22sample_None_55%22%2C%20%22sample_None_56%22%2C%20%22sample_None_57%22%2C%20%22sample_None_58%22%2C%20%22sample_None_59%22%2C%20%22sample_None_60%22%2C%20%22sample_None_61%22%2C%20%22sample_None_62%22%2C%20%22sample_None_63%22%2C%20%22sample_None_64%22%2C%20%22sample_None_65%22%2C%20%22sample_None_66%22%2C%20%22sample_None_67%22%2C%20%22sample_None_68%22%2C%20%22sample_None_69%22%2C%20%22sample_None_70%22%2C%20%22sample_None_71%22%2C%20%22sample_None_72%22%2C%20%22sample_None_73%22%2C%20%22sample_None_74%22%2C%20%22sample_None_75%22%2C%20%22sample_None_76%22%2C%20%22sample_None_77%22%2C%20%22sample_None_78%22%2C%20%22sample_None_79%22%2C%20%22sample_None_80%22%2C%20%22sample_None_81%22%2C%20%22sample_None_82%22%2C%20%22sample_None_83%22%2C%20%22sample_None_84%22%2C%20%22sample_None_85%22%2C%20%22sample_None_86%22%2C%20%22sample_None_87%22%2C%20%22sample_None_88%22%2C%20%22sample_None_89%22%2C%20%22sample_None_90%22%2C%20%22sample_None_91%22%2C%20%22sample_None_92%22%2C%20%22sample_None_93%22%2C%20%22sample_None_94%22%2C%20%22sample_None_95%22%5D%5D%7D%7D%7D)", "coordinates": "A2:D2"}}, {"identity": "https://labop.io/examples/protocols/ludox/iGEM_LUDOX_OD_calibration_2018/CallBehaviorAction5", "behavior": "https://bioprotocols.org/labop/primitives/liquid_handling/Provision", "parameters": {"resource": "LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O", "destination": "SampleMask(name=None, source=https://labop.io/examples/protocols/ludox/harness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324/ActivityEdgeFlow9/LiteralIdentified1/SampleArray1, mask=%7B%22coords%22%3A%20%7B%22reagent%22%3A%20%7B%22dims%22%3A%20%5B%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5D%7D%2C%20%22container%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22https%3A//labop.io/examples/protocols/ludox/plateRequirement%22%5D%7D%2C%20%22location%22%3A%20%7B%22dims%22%3A%20%5B%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22A2%22%2C%20%22B2%22%2C%20%22C2%22%2C%20%22D2%22%5D%7D%2C%20%22sample%22%3A%20%7B%22dims%22%3A%20%5B%22sample%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%5D%7D%7D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22dims%22%3A%20%7B%22container%22%3A%201%2C%20%22location%22%3A%204%2C%20%22reagent%22%3A%200%2C%20%22sample%22%3A%204%7D%2C%20%22data_vars%22%3A%20%7B%22contents%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%2C%20%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%5D%5D%7D%2C%20%22sample_location%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%5D%5D%7D%7D%7D)", "amount": "100.0 microliter"}}, {"identity": "https://labop.io/examples/protocols/ludox/iGEM_LUDOX_OD_calibration_2018/CallBehaviorAction6", "behavior": "https://bioprotocols.org/labop/primitives/sample_arrays/PlateCoordinates", "parameters": {"source": "SampleArray(name=calibration plate, container_type=https://labop.io/examples/protocols/ludox/plateRequirement, initial_contents=%7B%22coords%22%3A%20%7B%22reagent%22%3A%20%7B%22dims%22%3A%20%5B%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5D%7D%2C%20%22container%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22https%3A//labop.io/examples/protocols/ludox/plateRequirement%22%5D%7D%2C%20%22location%22%3A%20%7B%22dims%22%3A%20%5B%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22A1%22%2C%20%22B1%22%2C%20%22C1%22%2C%20%22D1%22%2C%20%22E1%22%2C%20%22F1%22%2C%20%22G1%22%2C%20%22H1%22%2C%20%22A2%22%2C%20%22B2%22%2C%20%22C2%22%2C%20%22D2%22%2C%20%22E2%22%2C%20%22F2%22%2C%20%22G2%22%2C%20%22H2%22%2C%20%22A3%22%2C%20%22B3%22%2C%20%22C3%22%2C%20%22D3%22%2C%20%22E3%22%2C%20%22F3%22%2C%20%22G3%22%2C%20%22H3%22%2C%20%22A4%22%2C%20%22B4%22%2C%20%22C4%22%2C%20%22D4%22%2C%20%22E4%22%2C%20%22F4%22%2C%20%22G4%22%2C%20%22H4%22%2C%20%22A5%22%2C%20%22B5%22%2C%20%22C5%22%2C%20%22D5%22%2C%20%22E5%22%2C%20%22F5%22%2C%20%22G5%22%2C%20%22H5%22%2C%20%22A6%22%2C%20%22B6%22%2C%20%22C6%22%2C%20%22D6%22%2C%20%22E6%22%2C%20%22F6%22%2C%20%22G6%22%2C%20%22H6%22%2C%20%22A7%22%2C%20%22B7%22%2C%20%22C7%22%2C%20%22D7%22%2C%20%22E7%22%2C%20%22F7%22%2C%20%22G7%22%2C%20%22H7%22%2C%20%22A8%22%2C%20%22B8%22%2C%20%22C8%22%2C%20%22D8%22%2C%20%22E8%22%2C%20%22F8%22%2C%20%22G8%22%2C%20%22H8%22%2C%20%22A9%22%2C%20%22B9%22%2C%20%22C9%22%2C%20%22D9%22%2C%20%22E9%22%2C%20%22F9%22%2C%20%22G9%22%2C%20%22H9%22%2C%20%22A10%22%2C%20%22B10%22%2C%20%22C10%22%2C%20%22D10%22%2C%20%22E10%22%2C%20%22F10%22%2C%20%22G10%22%2C%20%22H10%22%2C%20%22A11%22%2C%20%22B11%22%2C%20%22C11%22%2C%20%22D11%22%2C%20%22E11%22%2C%20%22F11%22%2C%20%22G11%22%2C%20%22H11%22%2C%20%22A12%22%2C%20%22B12%22%2C%20%22C12%22%2C%20%22D12%22%2C%20%22E12%22%2C%20%22F12%22%2C%20%22G12%22%2C%20%22H12%22%5D%7D%2C%20%22sample%22%3A%20%7B%22dims%22%3A%20%5B%22sample%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%2C%20%22sample_None_4%22%2C%20%22sample_None_5%22%2C%20%22sample_None_6%22%2C%20%22sample_None_7%22%2C%20%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%2C%20%22sample_None_12%22%2C%20%22sample_None_13%22%2C%20%22sample_None_14%22%2C%20%22sample_None_15%22%2C%20%22sample_None_16%22%2C%20%22sample_None_17%22%2C%20%22sample_None_18%22%2C%20%22sample_None_19%22%2C%20%22sample_None_20%22%2C%20%22sample_None_21%22%2C%20%22sample_None_22%22%2C%20%22sample_None_23%22%2C%20%22sample_None_24%22%2C%20%22sample_None_25%22%2C%20%22sample_None_26%22%2C%20%22sample_None_27%22%2C%20%22sample_None_28%22%2C%20%22sample_None_29%22%2C%20%22sample_None_30%22%2C%20%22sample_None_31%22%2C%20%22sample_None_32%22%2C%20%22sample_None_33%22%2C%20%22sample_None_34%22%2C%20%22sample_None_35%22%2C%20%22sample_None_36%22%2C%20%22sample_None_37%22%2C%20%22sample_None_38%22%2C%20%22sample_None_39%22%2C%20%22sample_None_40%22%2C%20%22sample_None_41%22%2C%20%22sample_None_42%22%2C%20%22sample_None_43%22%2C%20%22sample_None_44%22%2C%20%22sample_None_45%22%2C%20%22sample_None_46%22%2C%20%22sample_None_47%22%2C%20%22sample_None_48%22%2C%20%22sample_None_49%22%2C%20%22sample_None_50%22%2C%20%22sample_None_51%22%2C%20%22sample_None_52%22%2C%20%22sample_None_53%22%2C%20%22sample_None_54%22%2C%20%22sample_None_55%22%2C%20%22sample_None_56%22%2C%20%22sample_None_57%22%2C%20%22sample_None_58%22%2C%20%22sample_None_59%22%2C%20%22sample_None_60%22%2C%20%22sample_None_61%22%2C%20%22sample_None_62%22%2C%20%22sample_None_63%22%2C%20%22sample_None_64%22%2C%20%22sample_None_65%22%2C%20%22sample_None_66%22%2C%20%22sample_None_67%22%2C%20%22sample_None_68%22%2C%20%22sample_None_69%22%2C%20%22sample_None_70%22%2C%20%22sample_None_71%22%2C%20%22sample_None_72%22%2C%20%22sample_None_73%22%2C%20%22sample_None_74%22%2C%20%22sample_None_75%22%2C%20%22sample_None_76%22%2C%20%22sample_None_77%22%2C%20%22sample_None_78%22%2C%20%22sample_None_79%22%2C%20%22sample_None_80%22%2C%20%22sample_None_81%22%2C%20%22sample_None_82%22%2C%20%22sample_None_83%22%2C%20%22sample_None_84%22%2C%20%22sample_None_85%22%2C%20%22sample_None_86%22%2C%20%22sample_None_87%22%2C%20%22sample_None_88%22%2C%20%22sample_None_89%22%2C%20%22sample_None_90%22%2C%20%22sample_None_91%22%2C%20%22sample_None_92%22%2C%20%22sample_None_93%22%2C%20%22sample_None_94%22%2C%20%22sample_None_95%22%5D%7D%7D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22dims%22%3A%20%7B%22reagent%22%3A%200%2C%20%22container%22%3A%201%2C%20%22location%22%3A%2096%2C%20%22sample%22%3A%2096%7D%2C%20%22data_vars%22%3A%20%7B%22contents%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%2C%20%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%5D%5D%7D%2C%20%22sample_location%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%2C%20%22sample_None_4%22%2C%20%22sample_None_5%22%2C%20%22sample_None_6%22%2C%20%22sample_None_7%22%2C%20%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%2C%20%22sample_None_12%22%2C%20%22sample_None_13%22%2C%20%22sample_None_14%22%2C%20%22sample_None_15%22%2C%20%22sample_None_16%22%2C%20%22sample_None_17%22%2C%20%22sample_None_18%22%2C%20%22sample_None_19%22%2C%20%22sample_None_20%22%2C%20%22sample_None_21%22%2C%20%22sample_None_22%22%2C%20%22sample_None_23%22%2C%20%22sample_None_24%22%2C%20%22sample_None_25%22%2C%20%22sample_None_26%22%2C%20%22sample_None_27%22%2C%20%22sample_None_28%22%2C%20%22sample_None_29%22%2C%20%22sample_None_30%22%2C%20%22sample_None_31%22%2C%20%22sample_None_32%22%2C%20%22sample_None_33%22%2C%20%22sample_None_34%22%2C%20%22sample_None_35%22%2C%20%22sample_None_36%22%2C%20%22sample_None_37%22%2C%20%22sample_None_38%22%2C%20%22sample_None_39%22%2C%20%22sample_None_40%22%2C%20%22sample_None_41%22%2C%20%22sample_None_42%22%2C%20%22sample_None_43%22%2C%20%22sample_None_44%22%2C%20%22sample_None_45%22%2C%20%22sample_None_46%22%2C%20%22sample_None_47%22%2C%20%22sample_None_48%22%2C%20%22sample_None_49%22%2C%20%22sample_None_50%22%2C%20%22sample_None_51%22%2C%20%22sample_None_52%22%2C%20%22sample_None_53%22%2C%20%22sample_None_54%22%2C%20%22sample_None_55%22%2C%20%22sample_None_56%22%2C%20%22sample_None_57%22%2C%20%22sample_None_58%22%2C%20%22sample_None_59%22%2C%20%22sample_None_60%22%2C%20%22sample_None_61%22%2C%20%22sample_None_62%22%2C%20%22sample_None_63%22%2C%20%22sample_None_64%22%2C%20%22sample_None_65%22%2C%20%22sample_None_66%22%2C%20%22sample_None_67%22%2C%20%22sample_None_68%22%2C%20%22sample_None_69%22%2C%20%22sample_None_70%22%2C%20%22sample_None_71%22%2C%20%22sample_None_72%22%2C%20%22sample_None_73%22%2C%20%22sample_None_74%22%2C%20%22sample_None_75%22%2C%20%22sample_None_76%22%2C%20%22sample_None_77%22%2C%20%22sample_None_78%22%2C%20%22sample_None_79%22%2C%20%22sample_None_80%22%2C%20%22sample_None_81%22%2C%20%22sample_None_82%22%2C%20%22sample_None_83%22%2C%20%22sample_None_84%22%2C%20%22sample_None_85%22%2C%20%22sample_None_86%22%2C%20%22sample_None_87%22%2C%20%22sample_None_88%22%2C%20%22sample_None_89%22%2C%20%22sample_None_90%22%2C%20%22sample_None_91%22%2C%20%22sample_None_92%22%2C%20%22sample_None_93%22%2C%20%22sample_None_94%22%2C%20%22sample_None_95%22%5D%5D%7D%7D%7D)", "coordinates": "A1:D2"}}, "digraph \"cluster_https://labop.io/examples/protocols/ludox/harness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324\" {\n\tgraph [label=\"https://labop.io/examples/protocols/ludox/harness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324\"]\n\tsubgraph _root {\n\t\tcompound=true\n\t\tsubgraph cluster_iGEM_LUDOX_OD_calibration_2018 {\n\t\t\tgraph [label=\"iGEM 2018 LUDOX OD calibration protocol\" shape=box]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_InitialNode1 -> iGEM_LUDOX_OD_calibration_2018_FinalNode1 [label=\"\" color=blue]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_InitialNode1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction1:\"node\" [label=\"\" color=blue]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_ForkNode1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction2:InputPin1 [label=\"\" color=black]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction1:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction2:\"node\" [label=\"\" color=blue]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction2:OutputPin1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction3:InputPin1 [label=\"\" color=black]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction2:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction3:\"node\" [label=\"\" color=blue]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction1:OutputPin1 -> iGEM_LUDOX_OD_calibration_2018_ForkNode1 [label=\"\" color=black]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_ForkNode1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction4:InputPin1 [label=\"\" color=black]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction3:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction4:\"node\" [label=\"\" color=blue]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction4:OutputPin1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction5:InputPin1 [label=\"\" color=black]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction4:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction5:\"node\" [label=\"\" color=blue]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_ForkNode1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction6:InputPin1 [label=\"\" color=black]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction5:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction6:\"node\" [label=\"\" color=blue]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction6:OutputPin1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction7:InputPin1 [label=\"\" color=black]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_ActivityParameterNode1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction7:InputPin2 [label=\"\" color=black]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction6:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction7:\"node\" [label=\"\" color=blue]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction7:OutputPin1 -> iGEM_LUDOX_OD_calibration_2018_ActivityParameterNode2 [label=\"\" color=black]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction7:\"node\" -> iGEM_LUDOX_OD_calibration_2018_ActivityParameterNode2 [label=\"\" color=blue]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction7:\"node\" -> iGEM_LUDOX_OD_calibration_2018_FinalNode1 [label=\"\" color=blue]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction7:\"node\" -> iGEM_LUDOX_OD_calibration_2018_FinalNode1 [label=\"\" color=blue]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_InitialNode1 [label=\"\" fillcolor=black shape=circle style=filled]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_FinalNode1 [label=\"\" fillcolor=black shape=doublecircle style=filled]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_ActivityParameterNode1 [label=wavelength fillcolor=black peripheries=2 shape=rectangle]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction1 [label=<\n \n \n \n
specification: calibration plate sample_array
EmptyContainer
samples
> fillcolor=white shape=none style=rounded]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction2 [label=<\n \n \n \n
source coordinates: A1:D1
PlateCoordinates
samples
> fillcolor=white shape=none style=rounded]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction3 [label=<\n \n \n
resource: Water, sterile-filtered, BioReagent, suitable for cell culture destination amount: 100.0 microliter dispenseVelocity
Provision
> fillcolor=white shape=none style=rounded]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction4 [label=<\n \n \n \n
source coordinates: A2:D2
PlateCoordinates
samples
> fillcolor=white shape=none style=rounded]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_ForkNode1 [label=\"\" fillcolor=black height=0.02 shape=rectangle style=filled]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction5 [label=<\n \n \n
resource: LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O destination amount: 100.0 microliter dispenseVelocity
Provision
> fillcolor=white shape=none style=rounded]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction6 [label=<\n \n \n \n
source coordinates: A1:D2
PlateCoordinates
samples
> fillcolor=white shape=none style=rounded]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction7 [label=<\n \n \n \n
samples wavelength numFlashes timepoints
MeasureAbsorbance
measurements
> fillcolor=white shape=none style=rounded]\n\t\t\tiGEM_LUDOX_OD_calibration_2018_ActivityParameterNode2 [label=absorbance fillcolor=black peripheries=2 shape=rectangle]\n\t\t}\n\t}\n\tharness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324_InitialNode1 [label=\"\" fillcolor=black shape=circle style=filled]\n\tharness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324_CallBehaviorAction1 [label=<\n \n \n
iGEM_LUDOX_OD_calibration_2018
absorbance
> shape=none style=rounded]\n\tharness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324_InitialNode1 -> harness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324_CallBehaviorAction1:\"node\" [label=\"\" color=blue]\n\tharness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324_CallBehaviorAction1:\"node\" -> harness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324_CallBehaviorAction1:\"node\" [color=invis headport=w taillabel=\"[08:42:53]\" tailport=w]\n\tharness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324_CallBehaviorAction1:\"node\" -> iGEM_LUDOX_OD_calibration_2018_InitialNode1 [label=\"5: uml.ControlFlow\" color=blue]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction1:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction1:\"node\" [color=invis headport=w taillabel=\"[08:42:53]\" tailport=w]\n\tiGEM_LUDOX_OD_calibration_2018_ForkNode1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction1:OutputPin1 [label=\"10: SampleArray1\" color=orange]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction2:InputPin1 -> iGEM_LUDOX_OD_calibration_2018_ForkNode1 [label=\"13: SampleArray1\" color=orange]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction4:InputPin1 -> iGEM_LUDOX_OD_calibration_2018_ForkNode1 [label=\"11: SampleArray1\" color=orange]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction6:InputPin1 -> iGEM_LUDOX_OD_calibration_2018_ForkNode1 [label=\"12: SampleArray1\" color=orange]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction2:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction2:\"node\" [color=invis headport=w taillabel=\"[08:42:53]\" tailport=w]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction3:InputPin1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction2:OutputPin1 [label=\"19: SampleMask1\" color=orange]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction3:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction3:\"node\" [color=invis headport=w taillabel=\"[08:42:54]\" tailport=w]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction4:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction4:\"node\" [color=invis headport=w taillabel=\"[08:42:54]\" tailport=w]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction5:InputPin1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction4:OutputPin1 [label=\"24: SampleMask1\" color=orange]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction5:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction5:\"node\" [color=invis headport=w taillabel=\"[08:42:54]\" tailport=w]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction6:\"node\" -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction6:\"node\" [color=invis headport=w taillabel=\"[08:42:55]\" tailport=w]\n\tiGEM_LUDOX_OD_calibration_2018_CallBehaviorAction7:InputPin1 -> iGEM_LUDOX_OD_calibration_2018_CallBehaviorAction6:OutputPin1 [label=\"29: SampleMask1\" color=orange]\n}\n"] diff --git a/artifacts/ludox_protocol.diagram.pdf b/artifacts/ludox_protocol.diagram.pdf new file mode 100644 index 0000000000000000000000000000000000000000..76fa5fb404d1499947bcd8e76275d2fc5ef4c2d6 GIT binary patch literal 34978 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ⅇj1EL!rUV5`YQsWQwNl7zRP=gQ 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 Q3nQQc?7Q9W^ZVF60N{bui~s-t literal 0 HcmV?d00001 diff --git a/artifacts/ludox_protocol.nt b/artifacts/ludox_protocol.nt new file mode 100644 index 00000000..a95738f8 --- /dev/null +++ b/artifacts/ludox_protocol.nt @@ -0,0 +1,1792 @@ + "LUDOX" . + . + "LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O" . + . + . + "ddH2O" . + . + "Water, sterile-filtered, BioReagent, suitable for cell culture" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "resource" . + . + . + "0"^^ . + . + "OrderedPropertyValue1" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "destination" . + . + . + "1"^^ . + . + "OrderedPropertyValue2" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "amount" . + . + . + "2"^^ . + . + "OrderedPropertyValue3" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "0"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "dispenseVelocity" . + . + . + "3"^^ . + . + "OrderedPropertyValue4" . + . + . + . + . + . + . + "Place a measured amount (mass or volume) of a specified component into a location, where it may then be used in executing the protocol." . + "Provision" . + . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "specification" . + . + . + "0"^^ . + . + "OrderedPropertyValue1" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "0"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "sample_array" . + . + . + "1"^^ . + . + "OrderedPropertyValue2" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "samples" . + . + . + "2"^^ . + . + "OrderedPropertyValue3" . + . + . + . + . + . + "Allocate a sample array with size and type based on an empty container" . + "EmptyContainer" . + . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "source" . + . + . + "0"^^ . + . + "OrderedPropertyValue1" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "coordinates" . + . + . + "1"^^ . + . + "OrderedPropertyValue2" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "samples" . + . + . + "2"^^ . + . + "OrderedPropertyValue3" . + . + . + . + . + . + "Select only the samples with specified row/column combination from a sample collection" . + "PlateCoordinates" . + . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "samples" . + . + . + "0"^^ . + . + "OrderedPropertyValue1" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "wavelength" . + . + . + "1"^^ . + . + "OrderedPropertyValue2" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "0"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "numFlashes" . + . + . + "2"^^ . + . + "OrderedPropertyValue3" . + . + . + "0"^^ . + "LiteralInteger1" . + . + . + . + "true"^^ . + "true"^^ . + . + . + "Parameter1" . + "timepoints" . + . + . + "3"^^ . + . + "OrderedPropertyValue4" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "measurements" . + . + . + "4"^^ . + . + "OrderedPropertyValue5" . + . + . + . + . + . + . + . + "Measure absorbance at a given wavelength from a set of samples" . + "MeasureAbsorbance" . + . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + . + "ParameterValue1" . + . + . + "true"^^ . + . + "execute_0" . + . + . + . + "2023-09-26T08:42:53.127616"^^ . + "2023-09-26T08:42:53.127614"^^ . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue1" . + . + . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue2" . + . + . + "true"^^ . + . + . + "execute_1" . + . + . + . + "2023-09-26T08:42:53.262682"^^ . + "2023-09-26T08:42:53.262675"^^ . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue1" . + . + . + "A1:D1" . + "LiteralString1" . + . + . + . + . + "ParameterValue2" . + . + . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue3" . + . + . + "true"^^ . + . + . + . + "execute_2" . + . + . + . + "2023-09-26T08:42:53.954778"^^ . + "2023-09-26T08:42:53.954760"^^ . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue1" . + . + . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue2" . + . + . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue3" . + . + . + "true"^^ . + . + . + . + "execute_3" . + . + . + . + "2023-09-26T08:42:54.014012"^^ . + "2023-09-26T08:42:54.014004"^^ . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue1" . + . + . + "A2:D2" . + "LiteralString1" . + . + . + . + . + "ParameterValue2" . + . + . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue3" . + . + . + "true"^^ . + . + . + . + "execute_4" . + . + . + . + "2023-09-26T08:42:54.799951"^^ . + "2023-09-26T08:42:54.799931"^^ . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue1" . + . + . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue2" . + . + . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue3" . + . + . + "true"^^ . + . + . + . + "execute_5" . + . + . + . + "2023-09-26T08:42:54.864297"^^ . + "2023-09-26T08:42:54.864289"^^ . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue1" . + . + . + "A1:D2" . + "LiteralString1" . + . + . + . + . + "ParameterValue2" . + . + . + . + "LiteralReference1" . + . + . + . + . + "ParameterValue3" . + . + . + "true"^^ . + . + . + . + "execute_6" . + . + . + . + "2023-09-26T08:42:55.713399"^^ . + "2023-09-26T08:42:55.713382"^^ . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow10" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow11" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow12" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow13" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow14" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow15" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow16" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + . + . + "ActivityEdgeFlow17" . + . + . + "%7B%22coords%22%3A%20%7B%22reagent%22%3A%20%7B%22dims%22%3A%20%5B%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5D%7D%2C%20%22container%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22https%3A//labop.io/examples/protocols/ludox/plateRequirement%22%5D%7D%2C%20%22location%22%3A%20%7B%22dims%22%3A%20%5B%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22A1%22%2C%20%22B1%22%2C%20%22C1%22%2C%20%22D1%22%5D%7D%2C%20%22sample%22%3A%20%7B%22dims%22%3A%20%5B%22sample%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%5D%7D%7D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22dims%22%3A%20%7B%22container%22%3A%201%2C%20%22location%22%3A%204%2C%20%22reagent%22%3A%200%2C%20%22sample%22%3A%204%7D%2C%20%22data_vars%22%3A%20%7B%22contents%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%2C%20%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%5D%5D%7D%2C%20%22sample_location%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%5D%5D%7D%7D%7D" . + . + "SampleMask1" . + . + . + . + "LiteralIdentified1" . + . + . + . + . + . + "ActivityEdgeFlow18" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow19" . + . + . + . + . + . + "ActivityEdgeFlow1" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow20" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + . + . + "ActivityEdgeFlow21" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + . + . + "ActivityEdgeFlow22" . + . + . + "%7B%22coords%22%3A%20%7B%22reagent%22%3A%20%7B%22dims%22%3A%20%5B%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5D%7D%2C%20%22container%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22https%3A//labop.io/examples/protocols/ludox/plateRequirement%22%5D%7D%2C%20%22location%22%3A%20%7B%22dims%22%3A%20%5B%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22A2%22%2C%20%22B2%22%2C%20%22C2%22%2C%20%22D2%22%5D%7D%2C%20%22sample%22%3A%20%7B%22dims%22%3A%20%5B%22sample%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%5D%7D%7D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22dims%22%3A%20%7B%22container%22%3A%201%2C%20%22location%22%3A%204%2C%20%22reagent%22%3A%200%2C%20%22sample%22%3A%204%7D%2C%20%22data_vars%22%3A%20%7B%22contents%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%2C%20%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%5D%5D%7D%2C%20%22sample_location%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%5D%5D%7D%7D%7D" . + . + "SampleMask1" . + . + . + . + "LiteralIdentified1" . + . + . + . + . + . + "ActivityEdgeFlow23" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow24" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow25" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + . + . + "ActivityEdgeFlow26" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + . + . + "ActivityEdgeFlow27" . + . + . + "%7B%22coords%22%3A%20%7B%22reagent%22%3A%20%7B%22dims%22%3A%20%5B%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5D%7D%2C%20%22container%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22https%3A//labop.io/examples/protocols/ludox/plateRequirement%22%5D%7D%2C%20%22location%22%3A%20%7B%22dims%22%3A%20%5B%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22A1%22%2C%20%22A2%22%2C%20%22B1%22%2C%20%22B2%22%2C%20%22C1%22%2C%20%22C2%22%2C%20%22D1%22%2C%20%22D2%22%5D%7D%2C%20%22sample%22%3A%20%7B%22dims%22%3A%20%5B%22sample%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%2C%20%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%5D%7D%7D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22dims%22%3A%20%7B%22container%22%3A%201%2C%20%22location%22%3A%208%2C%20%22reagent%22%3A%200%2C%20%22sample%22%3A%208%7D%2C%20%22data_vars%22%3A%20%7B%22contents%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%2C%20%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%5D%5D%7D%2C%20%22sample_location%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%22sample_None_0%22%2C%20%22sample_None_8%22%2C%20%22sample_None_1%22%2C%20%22sample_None_9%22%2C%20%22sample_None_2%22%2C%20%22sample_None_10%22%2C%20%22sample_None_3%22%2C%20%22sample_None_11%22%5D%5D%7D%7D%7D" . + . + "SampleMask1" . + . + . + . + "LiteralIdentified1" . + . + . + . + . + . + "ActivityEdgeFlow28" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow29" . + . + . + . + . + . + "ActivityEdgeFlow2" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + "LiteralReference1" . + . + . + . + . + . + "ActivityEdgeFlow30" . + . + . + . + . + . + "ActivityEdgeFlow3" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + . + . + "ActivityEdgeFlow4" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + . + . + "ActivityEdgeFlow5" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + . + . + "ActivityEdgeFlow6" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + . + . + "ActivityEdgeFlow7" . + . + . + "uml.ControlFlow" . + "LiteralString1" . + . + . + . + . + . + "ActivityEdgeFlow8" . + . + . + . + "%7B%22coords%22%3A%20%7B%22reagent%22%3A%20%7B%22dims%22%3A%20%5B%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5D%7D%2C%20%22container%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22https%3A//labop.io/examples/protocols/ludox/plateRequirement%22%5D%7D%2C%20%22location%22%3A%20%7B%22dims%22%3A%20%5B%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22A1%22%2C%20%22B1%22%2C%20%22C1%22%2C%20%22D1%22%2C%20%22E1%22%2C%20%22F1%22%2C%20%22G1%22%2C%20%22H1%22%2C%20%22A2%22%2C%20%22B2%22%2C%20%22C2%22%2C%20%22D2%22%2C%20%22E2%22%2C%20%22F2%22%2C%20%22G2%22%2C%20%22H2%22%2C%20%22A3%22%2C%20%22B3%22%2C%20%22C3%22%2C%20%22D3%22%2C%20%22E3%22%2C%20%22F3%22%2C%20%22G3%22%2C%20%22H3%22%2C%20%22A4%22%2C%20%22B4%22%2C%20%22C4%22%2C%20%22D4%22%2C%20%22E4%22%2C%20%22F4%22%2C%20%22G4%22%2C%20%22H4%22%2C%20%22A5%22%2C%20%22B5%22%2C%20%22C5%22%2C%20%22D5%22%2C%20%22E5%22%2C%20%22F5%22%2C%20%22G5%22%2C%20%22H5%22%2C%20%22A6%22%2C%20%22B6%22%2C%20%22C6%22%2C%20%22D6%22%2C%20%22E6%22%2C%20%22F6%22%2C%20%22G6%22%2C%20%22H6%22%2C%20%22A7%22%2C%20%22B7%22%2C%20%22C7%22%2C%20%22D7%22%2C%20%22E7%22%2C%20%22F7%22%2C%20%22G7%22%2C%20%22H7%22%2C%20%22A8%22%2C%20%22B8%22%2C%20%22C8%22%2C%20%22D8%22%2C%20%22E8%22%2C%20%22F8%22%2C%20%22G8%22%2C%20%22H8%22%2C%20%22A9%22%2C%20%22B9%22%2C%20%22C9%22%2C%20%22D9%22%2C%20%22E9%22%2C%20%22F9%22%2C%20%22G9%22%2C%20%22H9%22%2C%20%22A10%22%2C%20%22B10%22%2C%20%22C10%22%2C%20%22D10%22%2C%20%22E10%22%2C%20%22F10%22%2C%20%22G10%22%2C%20%22H10%22%2C%20%22A11%22%2C%20%22B11%22%2C%20%22C11%22%2C%20%22D11%22%2C%20%22E11%22%2C%20%22F11%22%2C%20%22G11%22%2C%20%22H11%22%2C%20%22A12%22%2C%20%22B12%22%2C%20%22C12%22%2C%20%22D12%22%2C%20%22E12%22%2C%20%22F12%22%2C%20%22G12%22%2C%20%22H12%22%5D%7D%2C%20%22sample%22%3A%20%7B%22dims%22%3A%20%5B%22sample%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%2C%20%22sample_None_4%22%2C%20%22sample_None_5%22%2C%20%22sample_None_6%22%2C%20%22sample_None_7%22%2C%20%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%2C%20%22sample_None_12%22%2C%20%22sample_None_13%22%2C%20%22sample_None_14%22%2C%20%22sample_None_15%22%2C%20%22sample_None_16%22%2C%20%22sample_None_17%22%2C%20%22sample_None_18%22%2C%20%22sample_None_19%22%2C%20%22sample_None_20%22%2C%20%22sample_None_21%22%2C%20%22sample_None_22%22%2C%20%22sample_None_23%22%2C%20%22sample_None_24%22%2C%20%22sample_None_25%22%2C%20%22sample_None_26%22%2C%20%22sample_None_27%22%2C%20%22sample_None_28%22%2C%20%22sample_None_29%22%2C%20%22sample_None_30%22%2C%20%22sample_None_31%22%2C%20%22sample_None_32%22%2C%20%22sample_None_33%22%2C%20%22sample_None_34%22%2C%20%22sample_None_35%22%2C%20%22sample_None_36%22%2C%20%22sample_None_37%22%2C%20%22sample_None_38%22%2C%20%22sample_None_39%22%2C%20%22sample_None_40%22%2C%20%22sample_None_41%22%2C%20%22sample_None_42%22%2C%20%22sample_None_43%22%2C%20%22sample_None_44%22%2C%20%22sample_None_45%22%2C%20%22sample_None_46%22%2C%20%22sample_None_47%22%2C%20%22sample_None_48%22%2C%20%22sample_None_49%22%2C%20%22sample_None_50%22%2C%20%22sample_None_51%22%2C%20%22sample_None_52%22%2C%20%22sample_None_53%22%2C%20%22sample_None_54%22%2C%20%22sample_None_55%22%2C%20%22sample_None_56%22%2C%20%22sample_None_57%22%2C%20%22sample_None_58%22%2C%20%22sample_None_59%22%2C%20%22sample_None_60%22%2C%20%22sample_None_61%22%2C%20%22sample_None_62%22%2C%20%22sample_None_63%22%2C%20%22sample_None_64%22%2C%20%22sample_None_65%22%2C%20%22sample_None_66%22%2C%20%22sample_None_67%22%2C%20%22sample_None_68%22%2C%20%22sample_None_69%22%2C%20%22sample_None_70%22%2C%20%22sample_None_71%22%2C%20%22sample_None_72%22%2C%20%22sample_None_73%22%2C%20%22sample_None_74%22%2C%20%22sample_None_75%22%2C%20%22sample_None_76%22%2C%20%22sample_None_77%22%2C%20%22sample_None_78%22%2C%20%22sample_None_79%22%2C%20%22sample_None_80%22%2C%20%22sample_None_81%22%2C%20%22sample_None_82%22%2C%20%22sample_None_83%22%2C%20%22sample_None_84%22%2C%20%22sample_None_85%22%2C%20%22sample_None_86%22%2C%20%22sample_None_87%22%2C%20%22sample_None_88%22%2C%20%22sample_None_89%22%2C%20%22sample_None_90%22%2C%20%22sample_None_91%22%2C%20%22sample_None_92%22%2C%20%22sample_None_93%22%2C%20%22sample_None_94%22%2C%20%22sample_None_95%22%5D%7D%7D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22dims%22%3A%20%7B%22reagent%22%3A%200%2C%20%22container%22%3A%201%2C%20%22location%22%3A%2096%2C%20%22sample%22%3A%2096%7D%2C%20%22data_vars%22%3A%20%7B%22contents%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%2C%20%22reagent%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%2C%20%5B%5D%5D%5D%7D%2C%20%22sample_location%22%3A%20%7B%22dims%22%3A%20%5B%22container%22%2C%20%22location%22%5D%2C%20%22attrs%22%3A%20%7B%7D%2C%20%22data%22%3A%20%5B%5B%22sample_None_0%22%2C%20%22sample_None_1%22%2C%20%22sample_None_2%22%2C%20%22sample_None_3%22%2C%20%22sample_None_4%22%2C%20%22sample_None_5%22%2C%20%22sample_None_6%22%2C%20%22sample_None_7%22%2C%20%22sample_None_8%22%2C%20%22sample_None_9%22%2C%20%22sample_None_10%22%2C%20%22sample_None_11%22%2C%20%22sample_None_12%22%2C%20%22sample_None_13%22%2C%20%22sample_None_14%22%2C%20%22sample_None_15%22%2C%20%22sample_None_16%22%2C%20%22sample_None_17%22%2C%20%22sample_None_18%22%2C%20%22sample_None_19%22%2C%20%22sample_None_20%22%2C%20%22sample_None_21%22%2C%20%22sample_None_22%22%2C%20%22sample_None_23%22%2C%20%22sample_None_24%22%2C%20%22sample_None_25%22%2C%20%22sample_None_26%22%2C%20%22sample_None_27%22%2C%20%22sample_None_28%22%2C%20%22sample_None_29%22%2C%20%22sample_None_30%22%2C%20%22sample_None_31%22%2C%20%22sample_None_32%22%2C%20%22sample_None_33%22%2C%20%22sample_None_34%22%2C%20%22sample_None_35%22%2C%20%22sample_None_36%22%2C%20%22sample_None_37%22%2C%20%22sample_None_38%22%2C%20%22sample_None_39%22%2C%20%22sample_None_40%22%2C%20%22sample_None_41%22%2C%20%22sample_None_42%22%2C%20%22sample_None_43%22%2C%20%22sample_None_44%22%2C%20%22sample_None_45%22%2C%20%22sample_None_46%22%2C%20%22sample_None_47%22%2C%20%22sample_None_48%22%2C%20%22sample_None_49%22%2C%20%22sample_None_50%22%2C%20%22sample_None_51%22%2C%20%22sample_None_52%22%2C%20%22sample_None_53%22%2C%20%22sample_None_54%22%2C%20%22sample_None_55%22%2C%20%22sample_None_56%22%2C%20%22sample_None_57%22%2C%20%22sample_None_58%22%2C%20%22sample_None_59%22%2C%20%22sample_None_60%22%2C%20%22sample_None_61%22%2C%20%22sample_None_62%22%2C%20%22sample_None_63%22%2C%20%22sample_None_64%22%2C%20%22sample_None_65%22%2C%20%22sample_None_66%22%2C%20%22sample_None_67%22%2C%20%22sample_None_68%22%2C%20%22sample_None_69%22%2C%20%22sample_None_70%22%2C%20%22sample_None_71%22%2C%20%22sample_None_72%22%2C%20%22sample_None_73%22%2C%20%22sample_None_74%22%2C%20%22sample_None_75%22%2C%20%22sample_None_76%22%2C%20%22sample_None_77%22%2C%20%22sample_None_78%22%2C%20%22sample_None_79%22%2C%20%22sample_None_80%22%2C%20%22sample_None_81%22%2C%20%22sample_None_82%22%2C%20%22sample_None_83%22%2C%20%22sample_None_84%22%2C%20%22sample_None_85%22%2C%20%22sample_None_86%22%2C%20%22sample_None_87%22%2C%20%22sample_None_88%22%2C%20%22sample_None_89%22%2C%20%22sample_None_90%22%2C%20%22sample_None_91%22%2C%20%22sample_None_92%22%2C%20%22sample_None_93%22%2C%20%22sample_None_94%22%2C%20%22sample_None_95%22%5D%5D%7D%7D%7D" . + "SampleArray1" . + "calibration plate" . + . + . + . + "LiteralIdentified1" . + . + . + . + . + . + "ActivityEdgeFlow9" . + . + . + . + . + "ActivityNodeExecution10" . + . + . + . + . + "ActivityNodeExecution11" . + . + . + . + . + "ActivityNodeExecution12" . + . + . + . + . + "ActivityNodeExecution13" . + . + . + . + "ActivityNodeExecution1" . + . + . + . + . + "ActivityNodeExecution2" . + . + . + . + . + "ActivityNodeExecution3" . + . + . + . + . + "ActivityNodeExecution4" . + . + . + . + . + "ActivityNodeExecution5" . + . + . + . + . + "ActivityNodeExecution6" . + . + . + . + . + "ActivityNodeExecution7" . + . + . + . + . + "ActivityNodeExecution8" . + . + . + . + . + "ActivityNodeExecution9" . + . + . + "Association1" . + . + . + . + . + "true"^^ . + "true"^^ . + "OutputPin1" . + "absorbance" . + . + . + . + . + "CallBehaviorAction1" . + . + . + . + . + . + "CallBehaviorExecution1" . + . + . + . + . + . + "CallBehaviorExecution2" . + . + . + . + . + . + . + "CallBehaviorExecution3" . + . + . + . + . + . + . + "CallBehaviorExecution4" . + . + . + . + . + . + . + "CallBehaviorExecution5" . + . + . + . + . + . + . + "CallBehaviorExecution6" . + . + . + . + . + . + . + "CallBehaviorExecution7" . + . + . + . + . + "ControlFlow1" . + . + . + . + . + "ControlFlow2" . + . + . + . + . + "ControlFlow3" . + . + . + . + . + "ControlFlow4" . + . + . + . + . + "ControlFlow5" . + . + . + "FinalNode1" . + . + . + "InitialNode1" . + . + . + . + . + "ObjectFlow1" . + . + . + . + . + "ObjectFlow2" . + . + . + . + . + . + . + . + . + . + . + . + . + "true"^^ . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "harness_execution_iGEM_LUDOX_OD_calibration_2018_2023_09_26_08_42_53_043324" . + . + . + . + "2023-09-26T08:42:55.777179"^^ . + . + "2023-09-26T08:42:53.112152"^^ . + . + "ActivityParameterNode1" . + . + . + . + "ActivityParameterNode2" . + . + . + "true"^^ . + "true"^^ . + "InputPin1" . + "sample_array" . + . + . + "true"^^ . + "true"^^ . + "OutputPin1" . + "samples" . + . + . + . + "LiteralReference1" . + . + . + "true"^^ . + "true"^^ . + . + "ValuePin1" . + "specification" . + . + . + . + . + . + . + "CallBehaviorAction1" . + "calibration plate" . + . + . + "true"^^ . + "true"^^ . + "InputPin1" . + "source" . + . + . + "true"^^ . + "true"^^ . + "OutputPin1" . + "samples" . + . + . + "A1:D1" . + "LiteralString1" . + . + . + "true"^^ . + "true"^^ . + . + "ValuePin1" . + "coordinates" . + . + . + . + . + . + . + "CallBehaviorAction2" . + . + . + "true"^^ . + "true"^^ . + "InputPin1" . + "destination" . + . + . + "true"^^ . + "true"^^ . + "InputPin2" . + "dispenseVelocity" . + . + . + . + "LiteralReference1" . + . + . + "true"^^ . + "true"^^ . + . + "ValuePin1" . + "resource" . + . + . + "Measure1" . + "100.0"^^ . + . + . + . + . + "LiteralIdentified1" . + . + . + "true"^^ . + "true"^^ . + . + "ValuePin2" . + "amount" . + . + . + . + . + . + . + . + "CallBehaviorAction3" . + . + . + "true"^^ . + "true"^^ . + "InputPin1" . + "source" . + . + . + "true"^^ . + "true"^^ . + "OutputPin1" . + "samples" . + . + . + "A2:D2" . + "LiteralString1" . + . + . + "true"^^ . + "true"^^ . + . + "ValuePin1" . + "coordinates" . + . + . + . + . + . + . + "CallBehaviorAction4" . + . + . + "true"^^ . + "true"^^ . + "InputPin1" . + "destination" . + . + . + "true"^^ . + "true"^^ . + "InputPin2" . + "dispenseVelocity" . + . + . + . + "LiteralReference1" . + . + . + "true"^^ . + "true"^^ . + . + "ValuePin1" . + "resource" . + . + . + "Measure1" . + "100.0"^^ . + . + . + . + . + "LiteralIdentified1" . + . + . + "true"^^ . + "true"^^ . + . + "ValuePin2" . + "amount" . + . + . + . + . + . + . + . + "CallBehaviorAction5" . + . + . + "true"^^ . + "true"^^ . + "InputPin1" . + "source" . + . + . + "true"^^ . + "true"^^ . + "OutputPin1" . + "samples" . + . + . + "A1:D2" . + "LiteralString1" . + . + . + "true"^^ . + "true"^^ . + . + "ValuePin1" . + "coordinates" . + . + . + . + . + . + . + "CallBehaviorAction6" . + . + . + "true"^^ . + "true"^^ . + "InputPin1" . + "samples" . + . + . + "true"^^ . + "true"^^ . + "InputPin2" . + "wavelength" . + . + . + "true"^^ . + "true"^^ . + "InputPin3" . + "numFlashes" . + . + . + "true"^^ . + "true"^^ . + "InputPin4" . + "timepoints" . + . + . + "true"^^ . + "true"^^ . + "OutputPin1" . + "measurements" . + . + . + . + . + . + . + . + . + "CallBehaviorAction7" . + . + . + . + . + "ControlFlow10" . + . + . + . + . + "ControlFlow11" . + . + . + . + . + "ControlFlow1" . + . + . + . + . + "ControlFlow2" . + . + . + . + . + "ControlFlow3" . + . + . + . + . + "ControlFlow4" . + . + . + . + . + "ControlFlow5" . + . + . + . + . + "ControlFlow6" . + . + . + . + . + "ControlFlow7" . + . + . + . + . + "ControlFlow8" . + . + . + . + . + "ControlFlow9" . + . + . + "FinalNode1" . + . + . + "ForkNode1" . + . + . + "InitialNode1" . + . + . + . + . + "ObjectFlow10" . + . + . + . + . + "ObjectFlow11" . + . + . + . + . + "ObjectFlow12" . + . + . + . + . + "ObjectFlow13" . + . + . + . + . + "ObjectFlow14" . + . + . + . + . + "ObjectFlow15" . + . + . + . + . + "ObjectFlow16" . + . + . + . + . + "ObjectFlow17" . + . + . + . + . + "ObjectFlow18" . + . + . + . + . + "ObjectFlow19" . + . + . + . + . + "ObjectFlow1" . + . + . + . + . + "ObjectFlow20" . + . + . + . + . + "ObjectFlow21" . + . + . + . + . + "ObjectFlow22" . + . + . + . + . + "ObjectFlow23" . + . + . + . + . + "ObjectFlow24" . + . + . + . + . + "ObjectFlow25" . + . + . + . + . + "ObjectFlow26" . + . + . + . + . + "ObjectFlow27" . + . + . + . + . + "ObjectFlow28" . + . + . + . + . + "ObjectFlow29" . + . + . + . + . + "ObjectFlow2" . + . + . + . + . + "ObjectFlow30" . + . + . + . + . + "ObjectFlow31" . + . + . + . + . + "ObjectFlow32" . + . + . + . + . + "ObjectFlow33" . + . + . + . + . + "ObjectFlow34" . + . + . + . + . + "ObjectFlow3" . + . + . + . + . + "ObjectFlow4" . + . + . + . + . + "ObjectFlow5" . + . + . + . + . + "ObjectFlow6" . + . + . + . + . + "ObjectFlow7" . + . + . + . + . + "ObjectFlow8" . + . + . + . + . + "ObjectFlow9" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "0"^^ . + "LiteralInteger2" . + . + . + "Measure1" . + "600.0"^^ . + . + . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "wavelength" . + . + . + "0"^^ . + . + "OrderedPropertyValue1" . + . + . + "1"^^ . + "LiteralInteger1" . + . + . + "1"^^ . + "LiteralInteger2" . + . + . + . + "true"^^ . + "true"^^ . + . + . + . + "Parameter1" . + "absorbance" . + . + . + "1"^^ . + . + "OrderedPropertyValue2" . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + . + "\nWith this protocol you will use LUDOX CL-X (a 45% colloidal silica suspension) as a single point reference to\nobtain a conversion factor to transform absorbance (OD600) data from your plate reader into a comparable\nOD600 measurement as would be obtained in a spectrophotometer. This conversion is necessary because plate\nreader measurements of absorbance are volume dependent; the depth of the fluid in the well defines the path\nlength of the light passing through the sample, which can vary slightly from well to well. In a standard\nspectrophotometer, the path length is fixed and is defined by the width of the cuvette, which is constant.\nTherefore this conversion calculation can transform OD600 measurements from a plate reader (i.e. absorbance\nat 600 nm, the basic output of most instruments) into comparable OD600 measurements. The LUDOX solution\nis only weakly scattering and so will give a low absorbance value.\n " . + "iGEM_LUDOX_OD_calibration_2018" . + . + "iGEM 2018 LUDOX OD calibration protocol" . + . + . + "{\"cont\": \"https://sift.net/container-ontology/container-ontology#\", \"om\": \"http://www.ontology-of-units-of-measure.org/resource/om-2/\"}" . + "cont:ClearPlate and\n cont:SLAS-4-2004 and\n (cont:wellVolume some\n ((om:hasUnit value om:microlitre) and\n (om:hasNumericalValue only xsd:decimal[>= \"200\"^^xsd:decimal])))" . + "plateRequirement" . + . + "calibration plate" . + . + . \ No newline at end of file diff --git a/artifacts/opentrons_toy_protocol.diagram.pdf b/artifacts/opentrons_toy_protocol.diagram.pdf new file mode 100644 index 0000000000000000000000000000000000000000..de6bbf42740919111afe2160477d10bb2329f018 GIT binary patch literal 5834 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

u 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%0A({(VOPLtrgY4FavbrZP zO(@+SwcFsY*@Eo!>8JhYh44~gPuv|aDTW@MXju5I_X>H!psogaX(_Ky2t_ZJiLpq2yu&-!A5Llx0Lh<5n^&W0O_SEnx64V$3oZQ$}IWuwvCD^jq zVzGzB5@im`S5;u~BJT5ll37F$0Erz0&+1R#xEQtoml7}F7HwXt!}89CYJYG}Y<4w) zvtA^ul8%osimEW&F}i3e-yqt6zalvKS;@5LE$ZDGdT>or9cYoD%6Hh-wx7!QLU#w- z0aiT_lx9BUxRI=@tRvJpn0%Nmf<&(~QCBdR#>;Dq9%4x>9njz`xZQrRQ>z<`mZEo2 z536I^&g{{S?ZGz)c66cgf`PxNJka<+g|bQIy>e#HzvPu}I%Y;Sy(Gbqf}!UVxoX1O z+a%32ecp7==c_GNtVb30lky^seeo{5Tag*dYk{&jYQe73mYXfv)S8T+^RD?K8_W4o z(Exmv25kBzFTQ{HH`J?$7L~>PLvNvhfUf8Ly%L%qXl=o>m_-4#ezoE5G1n@6K5MV~ zip!46;!Kh;83^u=E(R!Z-^>P4pDv~9AV&*|jv^k|69|mN3^wvzJWU}Q>f4ZUU~lT- zH9>bnX}Cr>A-rNg0bOAj!RR4ed2rU<()iTO9Lyce_@6K19rj$X-EiLkZ$BemP)N|` zMi3Z))Wog)7CcwrUH$4h5vtf`K~@-E;dbJ8vgQ+y<_%)98twa&r8I*W?@uh<78 zN5@khQ4D8DOQw$DQb#zbCR8XgY*om-N@q~jL}Y|TGOpWx?9xocbR&(RVGvtX%TiPc zD{c&SBx!y-K_D*PF%wp4v|u0kXs**Zd2W5`#HBOw2DDb%7(tPJd$n6Os~*_ zzKE2#>n_RCklJNK9)`gBDcZ!_9Yw|J7~QzECxTcm3r&lX@{b(6)}!PmOz0b!~9 z3nA@+xMlTLZX3s={o_#l)J_*Nvc-Fv4&-p^XY|Wvw#64;U6ku68%C?vMkLF9DuguB zEyu#li%lBG8Y(toKN%Jp#;vNEH=I7&w%c~w<{kGN=T~iP?yG7ZH=8kV?~DEJzF3$f zT#FuRP}P5eP$J1Nn_aEDS|rr<#gZp&*3TnH6uT;9HL3Nph}ZOC%mIH#hU zNNL17NSLBKjIRiu$3nc11{*myo7eT?n)}}{^M&vFb>7BGXNOOYaWF4P2%bH;CfTOy zAjJzW;o?I{H?%`a@O#?U)6%DnHH97JXuxs-Ki(vJyt{%U6{Oz8Cp2N%Oy7d$*cLc z=JSmMy#0X@&Cm0}tWn$wLa%$w3t5?43*MOT#4bG&IU4ADcv!Bm9;r9kC5F{jMAn*_ex7Z2RW9N7$*_Qvxxq`&2 z_T#({|Iy;kIc!mK>K!WGfSiy!Nki$2@|UMXJKjOxqN?${jDU3$N+-rA8lm_ZQ^Ija z^NQsgZ6sUd^b)+W!)l;HX)WXd_vo`}x&vMflNv+DwLPa@JME8GxFaIUD4R4rR%yDc zM;*HD?}Oovd)E76lGVVw{EY=Cb(qP{%CLJw;Dln zM&%~&S&l?QwyJs(pRtz{h)GKah7i$XlqJ6Wl)&&QPkj1IQ5Ca&XxWpNqoaExf;Sq7 z1FFo~v;w}E$+YjPdgEF@<|nh!2fpwypZrwa8?JbPiPIqMPx82S?)75OO5xMmH@MEC zy<4H?Sf5?+r%u-lR0x!IrzrTg`uYW#ke=H|4o&q?((BSRQHlO==bR$RiRNs7EZ*BK zraIn)o%FiLtW-~e6|>*DR-b||N~xTnkdh$As7U3jTntS|netbVQiwU&;;E(c=@lXt z_Z4`Q@H|Z2vcO6WhfP%KO)Rh@*sgUgV|%`jn@Ds`KR=BfoZp8R_sET?0KX+Y|_UBXT#wQnIpW?$c`tkNTcoW}49Q zz*E~Nz0n^eq>3G>vfm)1WylOgf1(}2XPY$=ZFpvmEW1l08<;t9CXH4@89o|);Re

0M6f(2~?P5;z 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 Xdj~x`hlhxOw8zeZLO~%aD~9ra6$G5t literal 0 HcmV?d00001 diff --git a/artifacts/opentrons_toy_protocol.md b/artifacts/opentrons_toy_protocol.md new file mode 100644 index 00000000..f66f0ac3 --- /dev/null +++ b/artifacts/opentrons_toy_protocol.md @@ -0,0 +1,19 @@ +# OT2 simple toy demonstration + +Example Opentrons Protocol as LabOP + + +## Protocol Materials: + + +## Protocol Steps: +1. Provision a container named `sample plate` such as: + [Corning96WellPlate360uLFlat](https://sift.net/container-ontology/container-ontology#Corning96WellPlate360uLFlat). +2. Provision a container named `tiprack` such as: + [Opentrons96TipRack300uL](https://sift.net/container-ontology/container-ontology#Opentrons96TipRack300uL). +3. Transfer 100.0 microliter of `sample plate` sample to wells B2 of Corning 96 Well Plate `sample plate`. +4. Import data into the provided Excel file: . + +--- +Timestamp: 2023-09-25 01:21:29.806385 +Protocol version: 1.0 diff --git a/artifacts/sample_graph_0 b/artifacts/sample_graph_0 new file mode 100644 index 00000000..8e478c4a --- /dev/null +++ b/artifacts/sample_graph_0 @@ -0,0 +1,487 @@ +strict digraph sample_graph { + graph [label=SampleGraph rankdir=TB] + node [ordering=out] + subgraph cluster_plateRequirement { + graph [label=plateRequirement] + subgraph cluster_plateRequirement_A1 { + graph [label=plateRequirement_A1] + sample_None_0 [label="sample_None_0 @0 +empty contents"] + } + subgraph cluster_plateRequirement_A2 { + graph [label=plateRequirement_A2] + sample_None_8 [label="sample_None_8 @0 +empty contents"] + } + subgraph cluster_plateRequirement_A3 { + graph [label=plateRequirement_A3] + sample_None_16 [label="sample_None_16 @0 +empty contents"] + } + subgraph cluster_plateRequirement_A4 { + graph [label=plateRequirement_A4] + sample_None_24 [label="sample_None_24 @0 +empty contents"] + } + subgraph cluster_plateRequirement_A5 { + graph [label=plateRequirement_A5] + sample_None_32 [label="sample_None_32 @0 +empty contents"] + } + subgraph cluster_plateRequirement_A6 { + graph [label=plateRequirement_A6] + sample_None_40 [label="sample_None_40 @0 +empty contents"] + } + subgraph cluster_plateRequirement_A7 { + graph [label=plateRequirement_A7] + sample_None_48 [label="sample_None_48 @0 +empty contents"] + } + subgraph cluster_plateRequirement_A8 { + graph [label=plateRequirement_A8] + sample_None_56 [label="sample_None_56 @0 +empty contents"] + } + subgraph cluster_plateRequirement_A9 { + graph [label=plateRequirement_A9] + sample_None_64 [label="sample_None_64 @0 +empty contents"] + } + subgraph cluster_plateRequirement_A10 { + graph [label=plateRequirement_A10] + sample_None_72 [label="sample_None_72 @0 +empty contents"] + } + subgraph cluster_plateRequirement_A11 { + graph [label=plateRequirement_A11] + sample_None_80 [label="sample_None_80 @0 +empty contents"] + } + subgraph cluster_plateRequirement_A12 { + graph [label=plateRequirement_A12] + sample_None_88 [label="sample_None_88 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B1 { + graph [label=plateRequirement_B1] + sample_None_1 [label="sample_None_1 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B2 { + graph [label=plateRequirement_B2] + sample_None_9 [label="sample_None_9 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B3 { + graph [label=plateRequirement_B3] + sample_None_17 [label="sample_None_17 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B4 { + graph [label=plateRequirement_B4] + sample_None_25 [label="sample_None_25 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B5 { + graph [label=plateRequirement_B5] + sample_None_33 [label="sample_None_33 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B6 { + graph [label=plateRequirement_B6] + sample_None_41 [label="sample_None_41 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B7 { + graph [label=plateRequirement_B7] + sample_None_49 [label="sample_None_49 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B8 { + graph [label=plateRequirement_B8] + sample_None_57 [label="sample_None_57 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B9 { + graph [label=plateRequirement_B9] + sample_None_65 [label="sample_None_65 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B10 { + graph [label=plateRequirement_B10] + sample_None_73 [label="sample_None_73 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B11 { + graph [label=plateRequirement_B11] + sample_None_81 [label="sample_None_81 @0 +empty contents"] + } + subgraph cluster_plateRequirement_B12 { + graph [label=plateRequirement_B12] + sample_None_89 [label="sample_None_89 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C1 { + graph [label=plateRequirement_C1] + sample_None_2 [label="sample_None_2 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C2 { + graph [label=plateRequirement_C2] + sample_None_10 [label="sample_None_10 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C3 { + graph [label=plateRequirement_C3] + sample_None_18 [label="sample_None_18 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C4 { + graph [label=plateRequirement_C4] + sample_None_26 [label="sample_None_26 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C5 { + graph [label=plateRequirement_C5] + sample_None_34 [label="sample_None_34 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C6 { + graph [label=plateRequirement_C6] + sample_None_42 [label="sample_None_42 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C7 { + graph [label=plateRequirement_C7] + sample_None_50 [label="sample_None_50 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C8 { + graph [label=plateRequirement_C8] + sample_None_58 [label="sample_None_58 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C9 { + graph [label=plateRequirement_C9] + sample_None_66 [label="sample_None_66 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C10 { + graph [label=plateRequirement_C10] + sample_None_74 [label="sample_None_74 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C11 { + graph [label=plateRequirement_C11] + sample_None_82 [label="sample_None_82 @0 +empty contents"] + } + subgraph cluster_plateRequirement_C12 { + graph [label=plateRequirement_C12] + sample_None_90 [label="sample_None_90 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D1 { + graph [label=plateRequirement_D1] + sample_None_3 [label="sample_None_3 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D2 { + graph [label=plateRequirement_D2] + sample_None_11 [label="sample_None_11 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D3 { + graph [label=plateRequirement_D3] + sample_None_19 [label="sample_None_19 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D4 { + graph [label=plateRequirement_D4] + sample_None_27 [label="sample_None_27 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D5 { + graph [label=plateRequirement_D5] + sample_None_35 [label="sample_None_35 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D6 { + graph [label=plateRequirement_D6] + sample_None_43 [label="sample_None_43 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D7 { + graph [label=plateRequirement_D7] + sample_None_51 [label="sample_None_51 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D8 { + graph [label=plateRequirement_D8] + sample_None_59 [label="sample_None_59 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D9 { + graph [label=plateRequirement_D9] + sample_None_67 [label="sample_None_67 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D10 { + graph [label=plateRequirement_D10] + sample_None_75 [label="sample_None_75 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D11 { + graph [label=plateRequirement_D11] + sample_None_83 [label="sample_None_83 @0 +empty contents"] + } + subgraph cluster_plateRequirement_D12 { + graph [label=plateRequirement_D12] + sample_None_91 [label="sample_None_91 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E1 { + graph [label=plateRequirement_E1] + sample_None_4 [label="sample_None_4 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E2 { + graph [label=plateRequirement_E2] + sample_None_12 [label="sample_None_12 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E3 { + graph [label=plateRequirement_E3] + sample_None_20 [label="sample_None_20 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E4 { + graph [label=plateRequirement_E4] + sample_None_28 [label="sample_None_28 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E5 { + graph [label=plateRequirement_E5] + sample_None_36 [label="sample_None_36 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E6 { + graph [label=plateRequirement_E6] + sample_None_44 [label="sample_None_44 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E7 { + graph [label=plateRequirement_E7] + sample_None_52 [label="sample_None_52 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E8 { + graph [label=plateRequirement_E8] + sample_None_60 [label="sample_None_60 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E9 { + graph [label=plateRequirement_E9] + sample_None_68 [label="sample_None_68 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E10 { + graph [label=plateRequirement_E10] + sample_None_76 [label="sample_None_76 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E11 { + graph [label=plateRequirement_E11] + sample_None_84 [label="sample_None_84 @0 +empty contents"] + } + subgraph cluster_plateRequirement_E12 { + graph [label=plateRequirement_E12] + sample_None_92 [label="sample_None_92 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F1 { + graph [label=plateRequirement_F1] + sample_None_5 [label="sample_None_5 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F2 { + graph [label=plateRequirement_F2] + sample_None_13 [label="sample_None_13 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F3 { + graph [label=plateRequirement_F3] + sample_None_21 [label="sample_None_21 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F4 { + graph [label=plateRequirement_F4] + sample_None_29 [label="sample_None_29 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F5 { + graph [label=plateRequirement_F5] + sample_None_37 [label="sample_None_37 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F6 { + graph [label=plateRequirement_F6] + sample_None_45 [label="sample_None_45 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F7 { + graph [label=plateRequirement_F7] + sample_None_53 [label="sample_None_53 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F8 { + graph [label=plateRequirement_F8] + sample_None_61 [label="sample_None_61 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F9 { + graph [label=plateRequirement_F9] + sample_None_69 [label="sample_None_69 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F10 { + graph [label=plateRequirement_F10] + sample_None_77 [label="sample_None_77 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F11 { + graph [label=plateRequirement_F11] + sample_None_85 [label="sample_None_85 @0 +empty contents"] + } + subgraph cluster_plateRequirement_F12 { + graph [label=plateRequirement_F12] + sample_None_93 [label="sample_None_93 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G1 { + graph [label=plateRequirement_G1] + sample_None_6 [label="sample_None_6 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G2 { + graph [label=plateRequirement_G2] + sample_None_14 [label="sample_None_14 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G3 { + graph [label=plateRequirement_G3] + sample_None_22 [label="sample_None_22 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G4 { + graph [label=plateRequirement_G4] + sample_None_30 [label="sample_None_30 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G5 { + graph [label=plateRequirement_G5] + sample_None_38 [label="sample_None_38 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G6 { + graph [label=plateRequirement_G6] + sample_None_46 [label="sample_None_46 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G7 { + graph [label=plateRequirement_G7] + sample_None_54 [label="sample_None_54 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G8 { + graph [label=plateRequirement_G8] + sample_None_62 [label="sample_None_62 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G9 { + graph [label=plateRequirement_G9] + sample_None_70 [label="sample_None_70 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G10 { + graph [label=plateRequirement_G10] + sample_None_78 [label="sample_None_78 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G11 { + graph [label=plateRequirement_G11] + sample_None_86 [label="sample_None_86 @0 +empty contents"] + } + subgraph cluster_plateRequirement_G12 { + graph [label=plateRequirement_G12] + sample_None_94 [label="sample_None_94 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H1 { + graph [label=plateRequirement_H1] + sample_None_7 [label="sample_None_7 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H2 { + graph [label=plateRequirement_H2] + sample_None_15 [label="sample_None_15 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H3 { + graph [label=plateRequirement_H3] + sample_None_23 [label="sample_None_23 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H4 { + graph [label=plateRequirement_H4] + sample_None_31 [label="sample_None_31 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H5 { + graph [label=plateRequirement_H5] + sample_None_39 [label="sample_None_39 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H6 { + graph [label=plateRequirement_H6] + sample_None_47 [label="sample_None_47 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H7 { + graph [label=plateRequirement_H7] + sample_None_55 [label="sample_None_55 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H8 { + graph [label=plateRequirement_H8] + sample_None_63 [label="sample_None_63 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H9 { + graph [label=plateRequirement_H9] + sample_None_71 [label="sample_None_71 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H10 { + graph [label=plateRequirement_H10] + sample_None_79 [label="sample_None_79 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H11 { + graph [label=plateRequirement_H11] + sample_None_87 [label="sample_None_87 @0 +empty contents"] + } + subgraph cluster_plateRequirement_H12 { + graph [label=plateRequirement_H12] + sample_None_95 [label="sample_None_95 @0 +empty contents"] + } + } +} diff --git a/artifacts/sample_graph_0.pdf b/artifacts/sample_graph_0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3a6156ee16372a0e98ad70f041341c8242566daa GIT binary patch literal 33748 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 "sample_calibration plate_96" + sample_None_1 -> "sample_calibration plate_97" + sample_None_2 -> "sample_calibration plate_98" + sample_None_3 -> "sample_calibration plate_99" + subgraph cluster_plateRequirement { + graph [label=plateRequirement] + subgraph cluster_plateRequirement_A1 { + graph [label=plateRequirement_A1] + "sample_calibration plate_96" [label="sample_calibration plate_96 @1 +ddH2O: 100.0"] + sample_None_0 [label="sample_None_0 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A10 { + graph [label=plateRequirement_A10] + sample_None_72 [label="sample_None_72 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A11 { + graph [label=plateRequirement_A11] + sample_None_80 [label="sample_None_80 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A12 { + graph [label=plateRequirement_A12] + sample_None_88 [label="sample_None_88 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A2 { + graph [label=plateRequirement_A2] + sample_None_8 [label="sample_None_8 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A3 { + graph [label=plateRequirement_A3] + sample_None_16 [label="sample_None_16 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A4 { + graph [label=plateRequirement_A4] + sample_None_24 [label="sample_None_24 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A5 { + graph [label=plateRequirement_A5] + sample_None_32 [label="sample_None_32 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A6 { + graph [label=plateRequirement_A6] + sample_None_40 [label="sample_None_40 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A7 { + graph [label=plateRequirement_A7] + sample_None_48 [label="sample_None_48 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A8 { + graph [label=plateRequirement_A8] + sample_None_56 [label="sample_None_56 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A9 { + graph [label=plateRequirement_A9] + sample_None_64 [label="sample_None_64 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B1 { + graph [label=plateRequirement_B1] + "sample_calibration plate_97" [label="sample_calibration plate_97 @1 +ddH2O: 100.0"] + sample_None_1 [label="sample_None_1 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B10 { + graph [label=plateRequirement_B10] + sample_None_73 [label="sample_None_73 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B11 { + graph [label=plateRequirement_B11] + sample_None_81 [label="sample_None_81 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B12 { + graph [label=plateRequirement_B12] + sample_None_89 [label="sample_None_89 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B2 { + graph [label=plateRequirement_B2] + sample_None_9 [label="sample_None_9 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B3 { + graph [label=plateRequirement_B3] + sample_None_17 [label="sample_None_17 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B4 { + graph [label=plateRequirement_B4] + sample_None_25 [label="sample_None_25 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B5 { + graph [label=plateRequirement_B5] + sample_None_33 [label="sample_None_33 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B6 { + graph [label=plateRequirement_B6] + sample_None_41 [label="sample_None_41 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B7 { + graph [label=plateRequirement_B7] + sample_None_49 [label="sample_None_49 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B8 { + graph [label=plateRequirement_B8] + sample_None_57 [label="sample_None_57 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B9 { + graph [label=plateRequirement_B9] + sample_None_65 [label="sample_None_65 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C1 { + graph [label=plateRequirement_C1] + "sample_calibration plate_98" [label="sample_calibration plate_98 @1 +ddH2O: 100.0"] + sample_None_2 [label="sample_None_2 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C10 { + graph [label=plateRequirement_C10] + sample_None_74 [label="sample_None_74 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C11 { + graph [label=plateRequirement_C11] + sample_None_82 [label="sample_None_82 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C12 { + graph [label=plateRequirement_C12] + sample_None_90 [label="sample_None_90 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C2 { + graph [label=plateRequirement_C2] + sample_None_10 [label="sample_None_10 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C3 { + graph [label=plateRequirement_C3] + sample_None_18 [label="sample_None_18 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C4 { + graph [label=plateRequirement_C4] + sample_None_26 [label="sample_None_26 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C5 { + graph [label=plateRequirement_C5] + sample_None_34 [label="sample_None_34 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C6 { + graph [label=plateRequirement_C6] + sample_None_42 [label="sample_None_42 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C7 { + graph [label=plateRequirement_C7] + sample_None_50 [label="sample_None_50 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C8 { + graph [label=plateRequirement_C8] + sample_None_58 [label="sample_None_58 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C9 { + graph [label=plateRequirement_C9] + sample_None_66 [label="sample_None_66 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D1 { + graph [label=plateRequirement_D1] + "sample_calibration plate_99" [label="sample_calibration plate_99 @1 +ddH2O: 100.0"] + sample_None_3 [label="sample_None_3 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D10 { + graph [label=plateRequirement_D10] + sample_None_75 [label="sample_None_75 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D11 { + graph [label=plateRequirement_D11] + sample_None_83 [label="sample_None_83 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D12 { + graph [label=plateRequirement_D12] + sample_None_91 [label="sample_None_91 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D2 { + graph [label=plateRequirement_D2] + sample_None_11 [label="sample_None_11 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D3 { + graph [label=plateRequirement_D3] + sample_None_19 [label="sample_None_19 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D4 { + graph [label=plateRequirement_D4] + sample_None_27 [label="sample_None_27 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D5 { + graph [label=plateRequirement_D5] + sample_None_35 [label="sample_None_35 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D6 { + graph [label=plateRequirement_D6] + sample_None_43 [label="sample_None_43 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D7 { + graph [label=plateRequirement_D7] + sample_None_51 [label="sample_None_51 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D8 { + graph [label=plateRequirement_D8] + sample_None_59 [label="sample_None_59 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D9 { + graph [label=plateRequirement_D9] + sample_None_67 [label="sample_None_67 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E1 { + graph [label=plateRequirement_E1] + sample_None_4 [label="sample_None_4 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E10 { + graph [label=plateRequirement_E10] + sample_None_76 [label="sample_None_76 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E11 { + graph [label=plateRequirement_E11] + sample_None_84 [label="sample_None_84 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E12 { + graph [label=plateRequirement_E12] + sample_None_92 [label="sample_None_92 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E2 { + graph [label=plateRequirement_E2] + sample_None_12 [label="sample_None_12 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E3 { + graph [label=plateRequirement_E3] + sample_None_20 [label="sample_None_20 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E4 { + graph [label=plateRequirement_E4] + sample_None_28 [label="sample_None_28 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E5 { + graph [label=plateRequirement_E5] + sample_None_36 [label="sample_None_36 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E6 { + graph [label=plateRequirement_E6] + sample_None_44 [label="sample_None_44 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E7 { + graph [label=plateRequirement_E7] + sample_None_52 [label="sample_None_52 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E8 { + graph [label=plateRequirement_E8] + sample_None_60 [label="sample_None_60 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E9 { + graph [label=plateRequirement_E9] + sample_None_68 [label="sample_None_68 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F1 { + graph [label=plateRequirement_F1] + sample_None_5 [label="sample_None_5 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F10 { + graph [label=plateRequirement_F10] + sample_None_77 [label="sample_None_77 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F11 { + graph [label=plateRequirement_F11] + sample_None_85 [label="sample_None_85 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F12 { + graph [label=plateRequirement_F12] + sample_None_93 [label="sample_None_93 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F2 { + graph [label=plateRequirement_F2] + sample_None_13 [label="sample_None_13 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F3 { + graph [label=plateRequirement_F3] + sample_None_21 [label="sample_None_21 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F4 { + graph [label=plateRequirement_F4] + sample_None_29 [label="sample_None_29 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F5 { + graph [label=plateRequirement_F5] + sample_None_37 [label="sample_None_37 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F6 { + graph [label=plateRequirement_F6] + sample_None_45 [label="sample_None_45 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F7 { + graph [label=plateRequirement_F7] + sample_None_53 [label="sample_None_53 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F8 { + graph [label=plateRequirement_F8] + sample_None_61 [label="sample_None_61 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F9 { + graph [label=plateRequirement_F9] + sample_None_69 [label="sample_None_69 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G1 { + graph [label=plateRequirement_G1] + sample_None_6 [label="sample_None_6 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G10 { + graph [label=plateRequirement_G10] + sample_None_78 [label="sample_None_78 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G11 { + graph [label=plateRequirement_G11] + sample_None_86 [label="sample_None_86 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G12 { + graph [label=plateRequirement_G12] + sample_None_94 [label="sample_None_94 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G2 { + graph [label=plateRequirement_G2] + sample_None_14 [label="sample_None_14 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G3 { + graph [label=plateRequirement_G3] + sample_None_22 [label="sample_None_22 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G4 { + graph [label=plateRequirement_G4] + sample_None_30 [label="sample_None_30 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G5 { + graph [label=plateRequirement_G5] + sample_None_38 [label="sample_None_38 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G6 { + graph [label=plateRequirement_G6] + sample_None_46 [label="sample_None_46 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G7 { + graph [label=plateRequirement_G7] + sample_None_54 [label="sample_None_54 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G8 { + graph [label=plateRequirement_G8] + sample_None_62 [label="sample_None_62 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G9 { + graph [label=plateRequirement_G9] + sample_None_70 [label="sample_None_70 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H1 { + graph [label=plateRequirement_H1] + sample_None_7 [label="sample_None_7 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H10 { + graph [label=plateRequirement_H10] + sample_None_79 [label="sample_None_79 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H11 { + graph [label=plateRequirement_H11] + sample_None_87 [label="sample_None_87 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H12 { + graph [label=plateRequirement_H12] + sample_None_95 [label="sample_None_95 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H2 { + graph [label=plateRequirement_H2] + sample_None_15 [label="sample_None_15 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H3 { + graph [label=plateRequirement_H3] + sample_None_23 [label="sample_None_23 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H4 { + graph [label=plateRequirement_H4] + sample_None_31 [label="sample_None_31 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H5 { + graph [label=plateRequirement_H5] + sample_None_39 [label="sample_None_39 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H6 { + graph [label=plateRequirement_H6] + sample_None_47 [label="sample_None_47 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H7 { + graph [label=plateRequirement_H7] + sample_None_55 [label="sample_None_55 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H8 { + graph [label=plateRequirement_H8] + sample_None_63 [label="sample_None_63 @0 +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H9 { + graph [label=plateRequirement_H9] + sample_None_71 [label="sample_None_71 @0 +ddH2O: nan"] + } + } +} diff --git a/artifacts/sample_graph_1.pdf b/artifacts/sample_graph_1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..732f83b8e5daa66721c42f39fe536c0f9c1acdba GIT binary patch literal 35067 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 literal 0 HcmV?d00001 diff --git a/artifacts/sample_graph_2 b/artifacts/sample_graph_2 new file mode 100644 index 00000000..39073830 --- /dev/null +++ b/artifacts/sample_graph_2 @@ -0,0 +1,615 @@ +strict digraph sample_graph { + graph [label=SampleGraph rankdir=TB] + node [ordering=out] + sample_None_8 -> "sample_calibration plate_100" + sample_None_9 -> "sample_calibration plate_101" + sample_None_10 -> "sample_calibration plate_102" + sample_None_11 -> "sample_calibration plate_103" + sample_None_0 -> "sample_calibration plate_96" + sample_None_1 -> "sample_calibration plate_97" + sample_None_2 -> "sample_calibration plate_98" + sample_None_3 -> "sample_calibration plate_99" + subgraph cluster_plateRequirement { + graph [label=plateRequirement] + subgraph cluster_plateRequirement_A1 { + graph [label=plateRequirement_A1] + "sample_calibration plate_96" [label="sample_calibration plate_96 @1 +LUDOX: nan +ddH2O: 100.0"] + sample_None_0 [label="sample_None_0 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A10 { + graph [label=plateRequirement_A10] + sample_None_72 [label="sample_None_72 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A11 { + graph [label=plateRequirement_A11] + sample_None_80 [label="sample_None_80 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A12 { + graph [label=plateRequirement_A12] + sample_None_88 [label="sample_None_88 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A2 { + graph [label=plateRequirement_A2] + "sample_calibration plate_100" [label="sample_calibration plate_100 @2 +LUDOX: 100.0 +ddH2O: nan"] + sample_None_8 [label="sample_None_8 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A3 { + graph [label=plateRequirement_A3] + sample_None_16 [label="sample_None_16 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A4 { + graph [label=plateRequirement_A4] + sample_None_24 [label="sample_None_24 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A5 { + graph [label=plateRequirement_A5] + sample_None_32 [label="sample_None_32 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A6 { + graph [label=plateRequirement_A6] + sample_None_40 [label="sample_None_40 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A7 { + graph [label=plateRequirement_A7] + sample_None_48 [label="sample_None_48 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A8 { + graph [label=plateRequirement_A8] + sample_None_56 [label="sample_None_56 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_A9 { + graph [label=plateRequirement_A9] + sample_None_64 [label="sample_None_64 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B1 { + graph [label=plateRequirement_B1] + "sample_calibration plate_97" [label="sample_calibration plate_97 @1 +LUDOX: nan +ddH2O: 100.0"] + sample_None_1 [label="sample_None_1 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B10 { + graph [label=plateRequirement_B10] + sample_None_73 [label="sample_None_73 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B11 { + graph [label=plateRequirement_B11] + sample_None_81 [label="sample_None_81 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B12 { + graph [label=plateRequirement_B12] + sample_None_89 [label="sample_None_89 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B2 { + graph [label=plateRequirement_B2] + "sample_calibration plate_101" [label="sample_calibration plate_101 @2 +LUDOX: 100.0 +ddH2O: nan"] + sample_None_9 [label="sample_None_9 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B3 { + graph [label=plateRequirement_B3] + sample_None_17 [label="sample_None_17 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B4 { + graph [label=plateRequirement_B4] + sample_None_25 [label="sample_None_25 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B5 { + graph [label=plateRequirement_B5] + sample_None_33 [label="sample_None_33 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B6 { + graph [label=plateRequirement_B6] + sample_None_41 [label="sample_None_41 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B7 { + graph [label=plateRequirement_B7] + sample_None_49 [label="sample_None_49 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B8 { + graph [label=plateRequirement_B8] + sample_None_57 [label="sample_None_57 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_B9 { + graph [label=plateRequirement_B9] + sample_None_65 [label="sample_None_65 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C1 { + graph [label=plateRequirement_C1] + "sample_calibration plate_98" [label="sample_calibration plate_98 @1 +LUDOX: nan +ddH2O: 100.0"] + sample_None_2 [label="sample_None_2 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C10 { + graph [label=plateRequirement_C10] + sample_None_74 [label="sample_None_74 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C11 { + graph [label=plateRequirement_C11] + sample_None_82 [label="sample_None_82 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C12 { + graph [label=plateRequirement_C12] + sample_None_90 [label="sample_None_90 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C2 { + graph [label=plateRequirement_C2] + "sample_calibration plate_102" [label="sample_calibration plate_102 @2 +LUDOX: 100.0 +ddH2O: nan"] + sample_None_10 [label="sample_None_10 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C3 { + graph [label=plateRequirement_C3] + sample_None_18 [label="sample_None_18 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C4 { + graph [label=plateRequirement_C4] + sample_None_26 [label="sample_None_26 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C5 { + graph [label=plateRequirement_C5] + sample_None_34 [label="sample_None_34 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C6 { + graph [label=plateRequirement_C6] + sample_None_42 [label="sample_None_42 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C7 { + graph [label=plateRequirement_C7] + sample_None_50 [label="sample_None_50 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C8 { + graph [label=plateRequirement_C8] + sample_None_58 [label="sample_None_58 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_C9 { + graph [label=plateRequirement_C9] + sample_None_66 [label="sample_None_66 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D1 { + graph [label=plateRequirement_D1] + "sample_calibration plate_99" [label="sample_calibration plate_99 @1 +LUDOX: nan +ddH2O: 100.0"] + sample_None_3 [label="sample_None_3 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D10 { + graph [label=plateRequirement_D10] + sample_None_75 [label="sample_None_75 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D11 { + graph [label=plateRequirement_D11] + sample_None_83 [label="sample_None_83 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D12 { + graph [label=plateRequirement_D12] + sample_None_91 [label="sample_None_91 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D2 { + graph [label=plateRequirement_D2] + "sample_calibration plate_103" [label="sample_calibration plate_103 @2 +LUDOX: 100.0 +ddH2O: nan"] + sample_None_11 [label="sample_None_11 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D3 { + graph [label=plateRequirement_D3] + sample_None_19 [label="sample_None_19 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D4 { + graph [label=plateRequirement_D4] + sample_None_27 [label="sample_None_27 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D5 { + graph [label=plateRequirement_D5] + sample_None_35 [label="sample_None_35 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D6 { + graph [label=plateRequirement_D6] + sample_None_43 [label="sample_None_43 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D7 { + graph [label=plateRequirement_D7] + sample_None_51 [label="sample_None_51 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D8 { + graph [label=plateRequirement_D8] + sample_None_59 [label="sample_None_59 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_D9 { + graph [label=plateRequirement_D9] + sample_None_67 [label="sample_None_67 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E1 { + graph [label=plateRequirement_E1] + sample_None_4 [label="sample_None_4 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E10 { + graph [label=plateRequirement_E10] + sample_None_76 [label="sample_None_76 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E11 { + graph [label=plateRequirement_E11] + sample_None_84 [label="sample_None_84 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E12 { + graph [label=plateRequirement_E12] + sample_None_92 [label="sample_None_92 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E2 { + graph [label=plateRequirement_E2] + sample_None_12 [label="sample_None_12 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E3 { + graph [label=plateRequirement_E3] + sample_None_20 [label="sample_None_20 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E4 { + graph [label=plateRequirement_E4] + sample_None_28 [label="sample_None_28 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E5 { + graph [label=plateRequirement_E5] + sample_None_36 [label="sample_None_36 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E6 { + graph [label=plateRequirement_E6] + sample_None_44 [label="sample_None_44 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E7 { + graph [label=plateRequirement_E7] + sample_None_52 [label="sample_None_52 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E8 { + graph [label=plateRequirement_E8] + sample_None_60 [label="sample_None_60 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_E9 { + graph [label=plateRequirement_E9] + sample_None_68 [label="sample_None_68 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F1 { + graph [label=plateRequirement_F1] + sample_None_5 [label="sample_None_5 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F10 { + graph [label=plateRequirement_F10] + sample_None_77 [label="sample_None_77 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F11 { + graph [label=plateRequirement_F11] + sample_None_85 [label="sample_None_85 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F12 { + graph [label=plateRequirement_F12] + sample_None_93 [label="sample_None_93 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F2 { + graph [label=plateRequirement_F2] + sample_None_13 [label="sample_None_13 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F3 { + graph [label=plateRequirement_F3] + sample_None_21 [label="sample_None_21 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F4 { + graph [label=plateRequirement_F4] + sample_None_29 [label="sample_None_29 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F5 { + graph [label=plateRequirement_F5] + sample_None_37 [label="sample_None_37 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F6 { + graph [label=plateRequirement_F6] + sample_None_45 [label="sample_None_45 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F7 { + graph [label=plateRequirement_F7] + sample_None_53 [label="sample_None_53 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F8 { + graph [label=plateRequirement_F8] + sample_None_61 [label="sample_None_61 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_F9 { + graph [label=plateRequirement_F9] + sample_None_69 [label="sample_None_69 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G1 { + graph [label=plateRequirement_G1] + sample_None_6 [label="sample_None_6 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G10 { + graph [label=plateRequirement_G10] + sample_None_78 [label="sample_None_78 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G11 { + graph [label=plateRequirement_G11] + sample_None_86 [label="sample_None_86 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G12 { + graph [label=plateRequirement_G12] + sample_None_94 [label="sample_None_94 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G2 { + graph [label=plateRequirement_G2] + sample_None_14 [label="sample_None_14 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G3 { + graph [label=plateRequirement_G3] + sample_None_22 [label="sample_None_22 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G4 { + graph [label=plateRequirement_G4] + sample_None_30 [label="sample_None_30 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G5 { + graph [label=plateRequirement_G5] + sample_None_38 [label="sample_None_38 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G6 { + graph [label=plateRequirement_G6] + sample_None_46 [label="sample_None_46 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G7 { + graph [label=plateRequirement_G7] + sample_None_54 [label="sample_None_54 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G8 { + graph [label=plateRequirement_G8] + sample_None_62 [label="sample_None_62 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_G9 { + graph [label=plateRequirement_G9] + sample_None_70 [label="sample_None_70 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H1 { + graph [label=plateRequirement_H1] + sample_None_7 [label="sample_None_7 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H10 { + graph [label=plateRequirement_H10] + sample_None_79 [label="sample_None_79 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H11 { + graph [label=plateRequirement_H11] + sample_None_87 [label="sample_None_87 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H12 { + graph [label=plateRequirement_H12] + sample_None_95 [label="sample_None_95 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H2 { + graph [label=plateRequirement_H2] + sample_None_15 [label="sample_None_15 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H3 { + graph [label=plateRequirement_H3] + sample_None_23 [label="sample_None_23 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H4 { + graph [label=plateRequirement_H4] + sample_None_31 [label="sample_None_31 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H5 { + graph [label=plateRequirement_H5] + sample_None_39 [label="sample_None_39 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H6 { + graph [label=plateRequirement_H6] + sample_None_47 [label="sample_None_47 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H7 { + graph [label=plateRequirement_H7] + sample_None_55 [label="sample_None_55 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H8 { + graph [label=plateRequirement_H8] + sample_None_63 [label="sample_None_63 @0 +LUDOX: nan +ddH2O: nan"] + } + subgraph cluster_plateRequirement_H9 { + graph [label=plateRequirement_H9] + sample_None_71 [label="sample_None_71 @0 +LUDOX: nan +ddH2O: nan"] + } + } +} diff --git a/artifacts/sample_graph_2.pdf b/artifacts/sample_graph_2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..028a7a1047ab7ebbf4005842617976ad609a5cbb GIT binary patch literal 37162 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 G_xcY5R3RJy literal 0 HcmV?d00001 diff --git a/examples/protocols/calibration/multicolor-particle-calibration/multicolor-particle-calibration.py b/examples/protocols/calibration/multicolor-particle-calibration/multicolor-particle-calibration.py index c98fe062..8382c3c6 100644 --- a/examples/protocols/calibration/multicolor-particle-calibration/multicolor-particle-calibration.py +++ b/examples/protocols/calibration/multicolor-particle-calibration/multicolor-particle-calibration.py @@ -13,6 +13,16 @@ from tyto import OM import labop +from labop.utils.harness import ( + ProtocolArtifact, + ProtocolDiagram, + ProtocolExecutionDiagram, + ProtocolHarness, + ProtocolNTuples, + ProtocolSampleTrace, + ProtocolSpecialization, +) +from labop_convert.markdown.markdown_specialization import MarkdownSpecialization NAMESPACE = "http://igem.org/engineering/" PROTOCOL_NAME = "interlab" @@ -322,33 +332,9 @@ def generate_prepare_reagents_subprotocol(doc: sbol3.Document): return subprotocol -def generate_protocol(): +def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol): import labop - doc = sbol3.Document() - sbol3.set_namespace(NAMESPACE) - - ############################################# - # Import the primitive libraries - # print("Importing libraries") - labop.import_library("liquid_handling") - # print("... Imported liquid handling") - labop.import_library("plate_handling") - # print("... Imported plate handling") - labop.import_library("spectrophotometry") - # print("... Imported spectrophotometry") - labop.import_library("sample_arrays") - # print("... Imported sample arrays") - - protocol = labop.Protocol(PROTOCOL_NAME) - protocol.name = PROTOCOL_LONG_NAME - protocol.version = "1.2" - protocol.description = """ -Plate readers report fluorescence values in arbitrary units that vary widely from instrument to instrument. Therefore absolute fluorescence values cannot be directly compared from one instrument to another. In order to compare fluorescence output of biological devices, it is necessary to create a standard fluorescence curve. This variant of the protocol uses two replicates of three colors of dye, plus beads. -Adapted from [https://dx.doi.org/10.17504/protocols.io.bht7j6rn](https://dx.doi.org/10.17504/protocols.io.bht7j6r) and [https://dx.doi.org/10.17504/protocols.io.6zrhf56](https://dx.doi.org/10.17504/protocols.io.6zrhf56) - """ - doc.add(protocol) - prepare_reagents_subprotocol = generate_prepare_reagents_subprotocol(doc) prepare_reagents = protocol.primitive_step(prepare_reagents_subprotocol) prepare_reagents.name = "prepare_reagents" @@ -1124,18 +1110,6 @@ def test_autoprotocol(): lconf.write(json.dumps(response)) -def read_protocol(filename=os.path.join(OUT_DIR, f"{filename}-protocol.nt")): - import labop - - doc = sbol3.Document() - sbol3.set_namespace(NAMESPACE) - - doc.read(filename, "nt") - protocol = doc.find(f"{NAMESPACE}{PROTOCOL_NAME}") - - return protocol, doc - - # Disable def blockPrint(): pass @@ -1147,7 +1121,35 @@ def enablePrint(): sys.stdout = sys.__stdout__ +harness = ProtocolHarness( + entry_point=generate_protocol, + artifacts=[ + ProtocolNTuples(), + ProtocolDiagram(), + ProtocolExecutionDiagram(), + ProtocolSampleTrace(), + ProtocolSpecialization(specialization=MarkdownSpecialization()), + ], + namespace="http://igem.org/engineering/", + protocol_name="interlab", + protocol_long_name="Multicolor fluorescence per bacterial particle calibration", + protocol_version="1.2", + protocol_description=""" +Plate readers report fluorescence values in arbitrary units that vary widely from instrument to instrument. Therefore absolute fluorescence values cannot be directly compared from one instrument to another. In order to compare fluorescence output of biological devices, it is necessary to create a standard fluorescence curve. This variant of the protocol uses two replicates of three colors of dye, plus beads. +Adapted from [https://dx.doi.org/10.17504/protocols.io.bht7j6rn](https://dx.doi.org/10.17504/protocols.io.bht7j6r) and [https://dx.doi.org/10.17504/protocols.io.6zrhf56](https://dx.doi.org/10.17504/protocols.io.6zrhf56) + """, + output_dir="".join(__file__.split(".py")[0].split("/")[-1:]), + libraries=[ + "liquid_handling", + "plate_handling", + "spectrophotometry", + "sample_arrays", + ], +) + + if __name__ == "__main__": + harness.run() parser = argparse.ArgumentParser() parser.add_argument( "-g", diff --git a/examples/protocols/ludox/LUDOX_protocol.py b/examples/protocols/ludox/LUDOX_protocol.py index e23f5a66..7f4d6422 100644 --- a/examples/protocols/ludox/LUDOX_protocol.py +++ b/examples/protocols/ludox/LUDOX_protocol.py @@ -1,77 +1,16 @@ -import json import logging -import os -from typing import Tuple -import rdflib as rdfl import sbol3 import tyto from sbol3 import Document import labop -from labop.execution_engine import ExecutionEngine +from labop.constants import ddh2o, ludox +from labop.strings import Strings +from labop.utils.harness import ProtocolHarness, ProtocolSpecialization from labop_convert.markdown.markdown_specialization import MarkdownSpecialization -logger: logging.Logger = logging.Logger("LUDOX_protocol") - -CONT_NS = rdfl.Namespace("https://sift.net/container-ontology/container-ontology#") -OM_NS = rdfl.Namespace("http://www.ontology-of-units-of-measure.org/resource/om-2/") - - -def prepare_document() -> Document: - logger.info("Setting up document") - doc = sbol3.Document() - sbol3.set_namespace("https://bbn.com/scratch/") - return doc - - -def import_labop_libraries() -> None: - logger.info("Importing libraries") - labop.import_library("liquid_handling") - logger.info("... Imported liquid handling") - labop.import_library("plate_handling") - logger.info("... Imported plate handling") - labop.import_library("spectrophotometry") - logger.info("... Imported spectrophotometry") - labop.import_library("sample_arrays") - logger.info("... Imported sample arrays") - - -DOCSTRING = """ -With this protocol you will use LUDOX CL-X (a 45% colloidal silica suspension) as a single point reference to -obtain a conversion factor to transform absorbance (OD600) data from your plate reader into a comparable -OD600 measurement as would be obtained in a spectrophotometer. This conversion is necessary because plate -reader measurements of absorbance are volume dependent; the depth of the fluid in the well defines the path -length of the light passing through the sample, which can vary slightly from well to well. In a standard -spectrophotometer, the path length is fixed and is defined by the width of the cuvette, which is constant. -Therefore this conversion calculation can transform OD600 measurements from a plate reader (i.e. absorbance -at 600 nm, the basic output of most instruments) into comparable OD600 measurements. The LUDOX solution -is only weakly scattering and so will give a low absorbance value. - """ - - -def create_protocol() -> labop.Protocol: - logger.info("Creating protocol") - protocol: labop.Protocol = labop.Protocol("iGEM_LUDOX_OD_calibration_2018") - protocol.name = "iGEM 2018 LUDOX OD calibration protocol" - protocol.description = DOCSTRING - return protocol - - -def create_h2o() -> sbol3.Component: - ddh2o = sbol3.Component( - "ddH2O", "https://identifiers.org/pubchem.substance:24901740" - ) - ddh2o.name = "Water, sterile-filtered, BioReagent, suitable for cell culture" # TODO get via tyto - return ddh2o - - -def create_ludox() -> sbol3.Component: - ludox = sbol3.Component( - "LUDOX", "https://identifiers.org/pubchem.substance:24866361" - ) - ludox.name = "LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O" - return ludox +logger: logging.Logger = logging.Logger(__name__) PLATE_SPECIFICATION = """cont:ClearPlate and @@ -80,22 +19,20 @@ def create_ludox() -> sbol3.Component: ((om:hasUnit value om:microlitre) and (om:hasNumericalValue only xsd:decimal[>= "200"^^xsd:decimal])))""" -PREFIX_MAP = json.dumps({"cont": CONT_NS, "om": OM_NS}) - def create_plate(protocol: labop.Protocol): spec = labop.ContainerSpec( "plateRequirement", name="calibration plate", queryString=PLATE_SPECIFICATION, - prefixMap=PREFIX_MAP, + prefixMap=labop.constants.PREFIX_MAP, ) plate = protocol.primitive_step("EmptyContainer", specification=spec) plate.name = "calibration plate" return plate -def provision_h2o(protocol: labop.Protocol, plate, ddh2o) -> None: +def provision_h2o(protocol: labop.Protocol, plate) -> None: c_ddh2o = protocol.primitive_step( "PlateCoordinates", source=plate.output_pin("samples"), @@ -109,7 +46,7 @@ def provision_h2o(protocol: labop.Protocol, plate, ddh2o) -> None: ) -def provision_ludox(protocol: labop.Protocol, plate, ludox) -> None: +def provision_ludox(protocol: labop.Protocol, plate) -> None: c_ludox = protocol.primitive_step( "PlateCoordinates", source=plate.output_pin("samples"), @@ -154,25 +91,9 @@ def measure_fluorescence( ) -def ludox_protocol() -> Tuple[labop.Protocol, Document]: - ############################################# - # set up the document - doc: Document = prepare_document() - - ############################################# - # Import the primitive libraries - import_labop_libraries() - - ############################################# - # Create the protocol - protocol: labop.Protocol = create_protocol() - doc.add(protocol) - +def ludox_protocol(doc: Document, protocol: labop.Protocol) -> labop.Protocol: # create the materials to be provisioned - ddh2o = create_h2o() doc.add(ddh2o) - - ludox = create_ludox() doc.add(ludox) # add an optional parameter for specifying the wavelength @@ -188,8 +109,8 @@ def ludox_protocol() -> Tuple[labop.Protocol, Document]: plate = create_plate(protocol) # put ludox and water in selected wells - provision_h2o(protocol, plate, ddh2o) - provision_ludox(protocol, plate, ludox) + provision_h2o(protocol, plate) + provision_ludox(protocol, plate) # measure the absorbance measure = measure_absorbance(protocol, plate, wavelength_param) @@ -202,29 +123,35 @@ def ludox_protocol() -> Tuple[labop.Protocol, Document]: protocol.order(protocol.get_last_step(), protocol.final()) - return protocol, doc - + return protocol -if __name__ == "__main__": - new_protocol: labop.Protocol - new_protocol, doc = ludox_protocol() - print("Validating and writing protocol") - v = doc.validate() - assert len(v) == 0, "".join(f"\n {e}" for e in v) - - rdf_filename = os.path.join( - os.path.dirname(__file__), "iGEM 2018 LUDOX OD calibration protocol.nt" - ) - doc.write(rdf_filename, sbol3.SORTED_NTRIPLES) - print(f"Wrote file as {rdf_filename}") - # render and view the dot - dot = new_protocol.to_dot() - dot.render(f"{new_protocol.name}.gv") - dot.view() +harness = ProtocolHarness( + entry_point=ludox_protocol, + artifacts=[ + ProtocolSpecialization( + specialization=MarkdownSpecialization( + "test_LUDOX_markdown.md", + sample_format=Strings.XARRAY, + ) + ) + ], + namespace="https://labop.io/examples/protocols/ludox/", + protocol_name="iGEM_LUDOX_OD_calibration_2018", + protocol_long_name="iGEM 2018 LUDOX OD calibration protocol", + protocol_version="1.0", + protocol_description=""" +With this protocol you will use LUDOX CL-X (a 45% colloidal silica suspension) as a single point reference to +obtain a conversion factor to transform absorbance (OD600) data from your plate reader into a comparable +OD600 measurement as would be obtained in a spectrophotometer. This conversion is necessary because plate +reader measurements of absorbance are volume dependent; the depth of the fluid in the well defines the path +length of the light passing through the sample, which can vary slightly from well to well. In a standard +spectrophotometer, the path length is fixed and is defined by the width of the cuvette, which is constant. +Therefore this conversion calculation can transform OD600 measurements from a plate reader (i.e. absorbance +at 600 nm, the basic output of most instruments) into comparable OD600 measurements. The LUDOX solution +is only weakly scattering and so will give a low absorbance value. + """, +) - agent = sbol3.Agent("test_agent") - ee = ExecutionEngine( - specializations=[MarkdownSpecialization("test_LUDOX_markdown.md")] - ) - x = ee.execute(new_protocol, agent, id="test_execution", parameter_values=[]) +if __name__ == "__main__": + harness.run() diff --git a/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py b/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py index c821ea33..5b1ae849 100644 --- a/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py +++ b/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py @@ -1,172 +1,150 @@ -import json - -import rdflib as rdfl import sbol3 import tyto import labop -import uml -from labop.execution_engine import ExecutionEngine +from labop.constants import ddh2o, ludox +from labop.protocol import Protocol +from labop.strings import Strings +from labop.utils.harness import ProtocolHarness, ProtocolSpecialization +from labop_convert.markdown.markdown_specialization import MarkdownSpecialization from labop_convert.opentrons.opentrons_specialization import OT2Specialization # Dev Note: This is a test of the initial version of the OT2 specialization. Any specs shown here can be changed in the future. Use at your own risk. Here be dragons. -############################################# -# set up the document -print("Setting up document") -doc = sbol3.Document() -sbol3.set_namespace("https://bbn.com/scratch/") - -############################################# -# Import the primitive libraries -print("Importing libraries") -labop.import_library("liquid_handling") -print("... Imported liquid handling") -labop.import_library("plate_handling") -print("... Imported plate handling") -labop.import_library("spectrophotometry") -print("... Imported spectrophotometry") -labop.import_library("sample_arrays") -print("... Imported sample arrays") - - -# Example of how to generate a template for a new protocol step - -# print(primitives["https://bioprotocols.org/labop/primitives/liquid_handling/Dispense"].template()) - -activity = labop.Protocol("iGEM_LUDOX_OD_calibration_2018") -activity.name = "iGEM 2018 LUDOX OD calibration protocol for OT2" -activity.description = """ -Test Execution -""" -doc.add(activity) - -# create the materials to be provisioned -CONT_NS = rdfl.Namespace("https://sift.net/container-ontology/container-ontology#") -OM_NS = rdfl.Namespace("http://www.ontology-of-units-of-measure.org/resource/om-2/") - -PREFIX_MAP = json.dumps({"cont": CONT_NS, "om": OM_NS}) - - -ddh2o = sbol3.Component("ddH2O", "https://identifiers.org/pubchem.substance:24901740") -ddh2o.name = "Water, sterile-filtered, BioReagent, suitable for cell culture" -doc.add(ddh2o) - -ludox = sbol3.Component("LUDOX", "https://identifiers.org/pubchem.substance:24866361") -ludox.name = "LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O" -doc.add(ludox) - -p300 = sbol3.Agent("p300_single", name="P300 Single") -doc.add(p300) -load = activity.primitive_step("ConfigureInstrument", instrument=p300, mount="left") - -# Define labware -spec_rack = labop.ContainerSpec( - "working_reagents_rack", - name="rack for reagent aliquots", - queryString="cont:Opentrons24TubeRackwithEppendorf1.5mLSafe-LockSnapcap", - prefixMap=PREFIX_MAP, -) -spec_ludox_container = labop.ContainerSpec( - "ludox_working_solution", - name="tube for ludox working solution", - queryString="cont:MicrofugeTube", - prefixMap=PREFIX_MAP, -) -spec_water_container = labop.ContainerSpec( - "water_stock", - name="tube for water aliquot", - queryString="cont:MicrofugeTube", - prefixMap=PREFIX_MAP, -) -spec_plate = labop.ContainerSpec( - "calibration_plate", - name="calibration plate", - queryString="cont:Corning96WellPlate360uLFlat", - prefixMap=PREFIX_MAP, -) -spec_tiprack = labop.ContainerSpec( - "tiprack", queryString="cont:Opentrons96TipRack300uL", prefixMap=PREFIX_MAP -) -doc.add(spec_rack) -doc.add(spec_ludox_container) -doc.add(spec_water_container) -doc.add(spec_plate) -doc.add(spec_tiprack) - -# Load OT2 instrument with labware -load = activity.primitive_step("LoadRackOnInstrument", rack=spec_rack, coordinates="1") -load = activity.primitive_step( - "LoadRackOnInstrument", rack=spec_tiprack, coordinates="2" +def generate_protocol(doc: sbol3.Document, activity: Protocol) -> Protocol: + # create the materials to be provisioned + + doc.add(ddh2o) + doc.add(ludox) + + p300 = sbol3.Agent("p300_single", name="P300 Single") + doc.add(p300) + load = activity.primitive_step("ConfigureInstrument", instrument=p300, mount="left") + + # Define labware + spec_rack = labop.ContainerSpec( + "working_reagents_rack", + name="rack for reagent aliquots", + queryString="cont:Opentrons24TubeRackwithEppendorf1.5mLSafe-LockSnapcap", + prefixMap=labop.constants.PREFIX_MAP, + ) + spec_ludox_container = labop.ContainerSpec( + "ludox_working_solution", + name="tube for ludox working solution", + queryString="cont:MicrofugeTube", + prefixMap=labop.constants.PREFIX_MAP, + ) + spec_water_container = labop.ContainerSpec( + "water_stock", + name="tube for water aliquot", + queryString="cont:MicrofugeTube", + prefixMap=labop.constants.PREFIX_MAP, + ) + spec_plate = labop.ContainerSpec( + "calibration_plate", + name="calibration plate", + queryString="cont:Corning96WellPlate360uLFlat", + prefixMap=labop.constants.PREFIX_MAP, + ) + spec_tiprack = labop.ContainerSpec( + "tiprack", + queryString="cont:Opentrons96TipRack300uL", + prefixMap=labop.constants.PREFIX_MAP, + ) + doc.add(spec_rack) + doc.add(spec_ludox_container) + doc.add(spec_water_container) + doc.add(spec_plate) + doc.add(spec_tiprack) + + # Load OT2 instrument with labware + load = activity.primitive_step( + "LoadRackOnInstrument", rack=spec_rack, coordinates="1" + ) + load = activity.primitive_step( + "LoadRackOnInstrument", rack=spec_tiprack, coordinates="2" + ) + load = activity.primitive_step( + "LoadRackOnInstrument", rack=spec_plate, coordinates="3" + ) + + # Set up reagents + rack = activity.primitive_step("EmptyRack", specification=spec_rack) + load_rack1 = activity.primitive_step( + "LoadContainerInRack", + slots=rack.output_pin("slots"), + container=spec_ludox_container, + coordinates="A1", + ) + load_rack2 = activity.primitive_step( + "LoadContainerInRack", + slots=rack.output_pin("slots"), + container=spec_water_container, + coordinates="A2", + ) + provision = activity.primitive_step( + "Provision", + resource=ludox, + destination=load_rack1.output_pin("samples"), + amount=sbol3.Measure(500, tyto.OM.microliter), + ) + provision = activity.primitive_step( + "Provision", + resource=ddh2o, + destination=load_rack2.output_pin("samples"), + amount=sbol3.Measure(500, tyto.OM.microliter), + ) + + # Set up target samples + plate = activity.primitive_step("EmptyContainer", specification=spec_plate) + water_samples = activity.primitive_step( + "PlateCoordinates", + source=plate.output_pin("samples"), + coordinates="A1:D1", + ) + ludox_samples = activity.primitive_step( + "PlateCoordinates", + source=plate.output_pin("samples"), + coordinates="A2:D2", + ) + + transfer = activity.primitive_step( + "Transfer", + source=load_rack1.output_pin("samples"), + destination=water_samples.output_pin("samples"), + amount=sbol3.Measure(100, tyto.OM.microliter), + ) + transfer = activity.primitive_step( + "Transfer", + source=load_rack1.output_pin("samples"), + destination=ludox_samples.output_pin("samples"), + amount=sbol3.Measure(100, tyto.OM.microliter), + ) + + return activity + + +harness = ProtocolHarness( + entry_point=generate_protocol, + artifacts=[ + ProtocolSpecialization( + specialization=MarkdownSpecialization( + "opentrons_ludox_example_protocol.md", + sample_format=Strings.XARRAY, + ) + ), + ProtocolSpecialization( + specialization=OT2Specialization("opentrons_ludox_example_labop.py") + ), + ], + namespace="https://labop.io/examples/protocols/opentrons/", + protocol_name="iGEM_LUDOX_OD_calibration_2018", + protocol_long_name="iGEM 2018 LUDOX OD calibration protocol for OT2", + protocol_version="1.0", + protocol_description="Test Execution", + agent=sbol3.Agent("ot2_machine", name="OT2 machine"), ) -load = activity.primitive_step("LoadRackOnInstrument", rack=spec_plate, coordinates="3") - - -# Set up reagents -rack = activity.primitive_step("EmptyRack", specification=spec_rack) -load_rack1 = activity.primitive_step( - "LoadContainerInRack", - slots=rack.output_pin("slots"), - container=spec_ludox_container, - coordinates="A1", -) -load_rack2 = activity.primitive_step( - "LoadContainerInRack", - slots=rack.output_pin("slots"), - container=spec_water_container, - coordinates="A2", -) -provision = activity.primitive_step( - "Provision", - resource=ludox, - destination=load_rack1.output_pin("samples"), - amount=sbol3.Measure(500, tyto.OM.microliter), -) -provision = activity.primitive_step( - "Provision", - resource=ddh2o, - destination=load_rack2.output_pin("samples"), - amount=sbol3.Measure(500, tyto.OM.microliter), -) - - -# Set up target samples -plate = activity.primitive_step("EmptyContainer", specification=spec_plate) -water_samples = activity.primitive_step( - "PlateCoordinates", source=plate.output_pin("samples"), coordinates="A1:D1" -) -ludox_samples = activity.primitive_step( - "PlateCoordinates", source=plate.output_pin("samples"), coordinates="A2:D2" -) - - -transfer = activity.primitive_step( - "Transfer", - source=load_rack1.output_pin("samples"), - destination=water_samples.output_pin("samples"), - amount=sbol3.Measure(100, tyto.OM.microliter), -) -transfer = activity.primitive_step( - "Transfer", - source=load_rack1.output_pin("samples"), - destination=ludox_samples.output_pin("samples"), - amount=sbol3.Measure(100, tyto.OM.microliter), -) - - -filename = "ot2_ludox_labop" -agent = sbol3.Agent("ot2_machine", name="OT2 machine") -ee = ExecutionEngine(specializations=[OT2Specialization(filename)]) -parameter_values = [] -execution = ee.execute(activity, agent, id="test_execution") - -# v = doc.validate() -# assert len(v) == 0, "".join(f'\n {e}' for e in v) - -doc.write("foo.ttl", file_format="ttl") -# render and view the dot -# dot = protocol.to_dot() -# dot.render(f'{protocol.name}.gv') -# dot.view() +if __name__ == "__main__": + harness.run() diff --git a/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py b/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py index 78fd56dc..e3a00179 100644 --- a/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py +++ b/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py @@ -1,5 +1,4 @@ import csv -import json import rdflib as rdfl import sbol3 @@ -7,6 +6,7 @@ import labop import uml +from labop.constants import ddh2o, ludox from labop.execution_engine import ExecutionEngine from labop_convert.markdown.markdown_specialization import MarkdownSpecialization from labop_convert.opentrons.opentrons_specialization import OT2Specialization @@ -123,19 +123,8 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): activity.name = "Opentrons PCR Demo" doc.add(activity) -# create the materials to be provisioned -CONT_NS = rdfl.Namespace("https://sift.net/container-ontology/container-ontology#") -OM_NS = rdfl.Namespace("http://www.ontology-of-units-of-measure.org/resource/om-2/") -PREFIX_MAP = json.dumps({"cont": CONT_NS, "om": OM_NS}) - - -ddh2o = sbol3.Component("ddH2O", "https://identifiers.org/pubchem.substance:24901740") -ddh2o.name = "Water, sterile-filtered, BioReagent, suitable for cell culture" doc.add(ddh2o) - -ludox = sbol3.Component("LUDOX", "https://identifiers.org/pubchem.substance:24866361") -ludox.name = "LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O" doc.add(ludox) p300 = sbol3.Agent("p300_single", name="P300 Single") @@ -166,7 +155,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): "reagent_rack", name="Tube rack for reagents", queryString="cont:Opentrons24TubeRackwithEppendorf1.5mLSafe-LockSnapcap", - prefixMap=PREFIX_MAP, + prefixMap=labop.constants.PREFIX_MAP, ) rack = activity.primitive_step("EmptyRack", specification=reagent_rack) load_rack = activity.primitive_step( @@ -178,7 +167,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): "primer_plate", name="primers in 96-well plate", queryString="cont:Corning96WellPlate360uLFlat", - prefixMap=PREFIX_MAP, + prefixMap=labop.constants.PREFIX_MAP, ) load = activity.primitive_step( "LoadRackOnInstrument", rack=primer_plate, coordinates="3" @@ -190,7 +179,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): "polymerase", name="DNA Polymerase", queryString="cont:StockReagent", - prefixMap=PREFIX_MAP, + prefixMap=labop.constants.PREFIX_MAP, ) load_reagents = activity.primitive_step( "LoadContainerInRack", @@ -207,7 +196,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): "water", name="tube for water", queryString="cont:MicrofugeTube", - prefixMap=PREFIX_MAP, + prefixMap=labop.constants.PREFIX_MAP, ), coordinates="B1", ) @@ -228,7 +217,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): template.display_id + "_container", name="container of " + template.name, queryString="cont:MicrofugeTube", - prefixMap=PREFIX_MAP, + prefixMap=labop.constants.PREFIX_MAP, ) load_template = activity.primitive_step( "LoadContainerInRack", @@ -243,7 +232,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): "pcr_plate", name="PCR plate", queryString="cont:Biorad96WellPCRPlate", - prefixMap=PREFIX_MAP, + prefixMap=labop.constants.PREFIX_MAP, ) load_pcr_plate_on_thermocycler = activity.primitive_step( "LoadContainerOnInstrument", diff --git a/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py b/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py index f3df899d..1e586ca1 100644 --- a/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py +++ b/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py @@ -1,6 +1,4 @@ -import json import logging -from typing import Tuple import rdflib as rdfl import sbol3 @@ -10,6 +8,18 @@ import labop import uml from labop.execution_engine import ExecutionEngine +from labop.protocol import Protocol +from labop.strings import Strings +from labop.utils.harness import ( + ProtocolDiagram, + ProtocolExecutionDiagram, + ProtocolExecutionNTuples, + ProtocolHarness, + ProtocolNTuples, + ProtocolSampleTrace, + ProtocolSpecialization, +) +from labop_convert.markdown.markdown_specialization import MarkdownSpecialization from labop_convert.opentrons.opentrons_specialization import ( REVERSE_LABWARE_MAP, OT2Specialization, @@ -17,10 +27,6 @@ logger: logging.Logger = logging.Logger("OT2_demo") -CONT_NS = rdfl.Namespace("https://sift.net/container-ontology/container-ontology#") -OM_NS = rdfl.Namespace("http://www.ontology-of-units-of-measure.org/resource/om-2/") -PREFIX_MAP = json.dumps({"cont": CONT_NS, "om": OM_NS}) - def prepare_document() -> Document: logger.info("Setting up document") @@ -55,7 +61,7 @@ def get_container(protocol: labop.Protocol, container_name: str, container_type: container_name.replace(" ", "_"), name=container_name, queryString=query_string, - prefixMap=PREFIX_MAP, + prefixMap=labop.constants.PREFIX_MAP, ) plate = protocol.primitive_step("EmptyContainer", specification=plate_spec) return plate @@ -67,20 +73,7 @@ def get_samples_from_coordinates(protocol, container, coordinates): ).output_pin("samples") -def opentrons_toy_protocol() -> Tuple[labop.Protocol, Document]: - ############################################# - # set up the document - doc: Document = prepare_document() - - ############################################# - # Import the primitive libraries - import_labop_libraries() - - ############################################# - # Create the protocol - protocol: labop.Protocol = create_protocol() - doc.add(protocol) - +def opentrons_toy_protocol(doc: sbol3.Document, protocol: Protocol) -> Protocol: # plate = protocol.load_labware('corning_96_wellplate_360ul_flat', location='1') create_plate = get_container( protocol, "sample plate", "corning_96_wellplate_360ul_flat" @@ -130,4 +123,27 @@ def opentrons_toy_protocol() -> Tuple[labop.Protocol, Document]: protocol.order(transfer, protocol.final()) - return protocol, doc + return protocol + + +harness = ProtocolHarness( + entry_point=opentrons_toy_protocol, + artifacts=[ + ProtocolSpecialization( + specialization=MarkdownSpecialization( + "opentrons_toy_protocol.md", sample_format=Strings.XARRAY + ) + ), + ProtocolSpecialization( + specialization=OT2Specialization("opentrons_toy_protocol_labop.py") + ), + ], + namespace="https://labop.io/examples/protocols/opentrons/", + protocol_name="opentrons_toy", + protocol_long_name="OT2 simple toy demonstration", + protocol_version="1.0", + protocol_description="Example Opentrons Protocol as LabOP", +) + +if __name__ == "__main__": + harness.run() diff --git a/examples/protocols/pH_calibration/pH_calibration.py b/examples/protocols/pH_calibration/pH_calibration.py index 3b27db95..c3c90d4d 100644 --- a/examples/protocols/pH_calibration/pH_calibration.py +++ b/examples/protocols/pH_calibration/pH_calibration.py @@ -22,8 +22,6 @@ logger: logging.Logger = logging.Logger("pH_calibration") -CONT_NS = rdfl.Namespace("https://sift.net/container-ontology/container-ontology#") -OM_NS = rdfl.Namespace("http://www.ontology-of-units-of-measure.org/resource/om-2/") LIBRARY_NAME = "pH_calibration" DOCSTRING = "This protocol implements a pH calibration protocol with decision nodes." diff --git a/labop/constants.py b/labop/constants.py new file mode 100644 index 00000000..1992f7de --- /dev/null +++ b/labop/constants.py @@ -0,0 +1,16 @@ +import json + +import rdflib as rdfl +import sbol3 + +CONT_NS = rdfl.Namespace("https://sift.net/container-ontology/container-ontology#") +OM_NS = rdfl.Namespace("http://www.ontology-of-units-of-measure.org/resource/om-2/") + +PREFIX_MAP = json.dumps({"cont": CONT_NS, "om": OM_NS}) + + +ddh2o = sbol3.Component("ddH2O", "https://identifiers.org/pubchem.substance:24901740") +ddh2o.name = "Water, sterile-filtered, BioReagent, suitable for cell culture" + +ludox = sbol3.Component("LUDOX", "https://identifiers.org/pubchem.substance:24866361") +ludox.name = "LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O" diff --git a/labop/container-ontology.ttl b/labop/container-ontology.ttl index 0fc0d12b..e1df9ebd 100644 --- a/labop/container-ontology.ttl +++ b/labop/container-ontology.ttl @@ -625,7 +625,29 @@ cont:Rack rdf:type owl:Class ; ############################################################ -### CARRIERS +### PLATES HAMILTON +############################################################ + +### https://github.com/PyLabRobot/pylabrobot/blob/main/pylabrobot/resources/corning_costar/plates.py +cont:Corning_96_EZWash_plate rdf:type owl:Class ; + rdfs:subClassOf cont:Plate ; + rdfs:label "Corning Costar EZwash plate with 96 wells" . + +### https://github.com/PyLabRobot/pylabrobot/blob/main/pylabrobot/resources/corning_costar/plates.py +cont:Corning_96_Filter_plate rdf:type owl:Class ; + rdfs:subClassOf cont:Plate ; + rdfs:label "Corning Costar filter plate with 96 wells" . + +### https://github.com/PyLabRobot/pylabrobot/blob/main/pylabrobot/resources/corning_costar/plates.py +cont:Corning_96_DW_1mL rdf:type owl:Class ; + rdfs:subClassOf cont:Plate ; + rdfs:label "Corning Costar 1 mL deep well plate with 96 wells" . + + + + +############################################################ +### CARRIERS HAMILTON ############################################################ ### https://sift.net/container-ontology/container-ontology#Thermocycler @@ -1229,7 +1251,7 @@ cont:Biorad96WellPCRPlate rdf:type owl:NamedIndividual , cont:Centrifuge rdf:type owl:NamedIndividual . ### https://sift.net/container-ontology/container-ontology#Corning96WellPlate360uLFlat -cont:Corning96WellPlate360uLFlat rdf:type owl:NamedIndividual , +cont:Corning96WellPlate360uL rdf:type owl:NamedIndividual , cont:Plate96Well ; rdfs:label "Corning 96 Well Plate" . @@ -1347,6 +1369,12 @@ cont:MLSTARTipCarrier3rackB rdf:type owl:NamedIndividual , cont:TipCarrier ; rdfs:label "ML STAR Tip carrier for 3 Racks with 96 Tips portrait revision B00" . +### https://github.com/PyLabRobot/pylabrobot/blob/main/pylabrobot/resources/corning_costar/plates.py +cont:TipRack961000ulfilter rdf:type owl:NamedIndividual , + cont:TipRack ; + rdfs:label "ML STAR Tip Rack with 96 1000ul High Volume Tip with filter" . + + diff --git a/labop/lib/plate_handling.py b/labop/lib/plate_handling.py index 012a3371..54c99209 100644 --- a/labop/lib/plate_handling.py +++ b/labop/lib/plate_handling.py @@ -28,6 +28,13 @@ ) # e.g., breathable vs. non-breathable doc.add(p) + +p = labop.Primitive("Filter") +p.description = "Activate vacuum pump to perform filtering in a plate" +p.add_input("location", "http://bioprotocols.org/labop#SampleArray") +doc.add(p) + + p = labop.Primitive("EvaporativeSeal") p.description = "Seal a collection of samples using a user-selected method in order to prevent evaporation" p.add_input("location", "http://bioprotocols.org/labop#SampleArray") diff --git a/labop/lib/plate_handling.ttl b/labop/lib/plate_handling.ttl index 44377d4a..de402ab2 100644 --- a/labop/lib/plate_handling.ttl +++ b/labop/lib/plate_handling.ttl @@ -27,6 +27,13 @@ sbol:displayId "EvaporativeSeal" ; sbol:hasNamespace . + a , + sbol:TopLevel ; + ns1:ownedParameter ; + sbol:description "Activate vacuum pump to perform filtering in a plate" ; + sbol:displayId "Filter" ; + sbol:hasNamespace . + a , sbol:TopLevel ; ns1:ownedParameter , @@ -262,6 +269,33 @@ ns1:integerValue 1 ; sbol:displayId "LiteralInteger2" . + a ns1:OrderedPropertyValue, + sbol:Identified ; + ns1:indexValue 0 ; + ns1:propertyValue ; + sbol:displayId "OrderedPropertyValue1" . + + a ns1:Parameter, + sbol:Identified ; + ns1:direction ns1:in ; + ns1:isOrdered true ; + ns1:isUnique true ; + ns1:lowerValue ; + ns1:type ; + ns1:upperValue ; + sbol:displayId "Parameter1" ; + sbol:name "location" . + + a ns1:LiteralInteger, + sbol:Identified ; + ns1:integerValue 1 ; + sbol:displayId "LiteralInteger1" . + + a ns1:LiteralInteger, + sbol:Identified ; + ns1:integerValue 1 ; + sbol:displayId "LiteralInteger2" . + a ns1:OrderedPropertyValue, sbol:Identified ; ns1:indexValue 0 ; diff --git a/labop/utils/harness.py b/labop/utils/harness.py new file mode 100644 index 00000000..b75d8619 --- /dev/null +++ b/labop/utils/harness.py @@ -0,0 +1,305 @@ +import logging +import os +from abc import ABC +from datetime import datetime +from typing import Callable, List + +import sbol3 +from isort import file + +from labop.execution_engine import ExecutionEngine +from labop.library import import_library +from labop.parameter_value import ParameterValue +from labop.protocol import Protocol +from labop.utils.helpers import prepare_document +from labop_convert import BehaviorSpecialization +from labop_convert.behavior_specialization import BehaviorSpecialization + +l = logging.Logger(__file__) +l.setLevel(logging.INFO) +ConsoleOutputHandler = logging.StreamHandler() +l.addHandler(ConsoleOutputHandler) + + +class ProtocolArtifact(ABC): + summary: str = "" + + def summary(self): + return "" + + def results_summary(self): + return self._summary + + +class ProtocolDiagram(ProtocolArtifact): + pass + + +class ProtocolNTuples(ProtocolArtifact): + pass + + +class ProtocolExecutionNTuples(ProtocolArtifact): + pass + + +class ProtocolExecutionDiagram(ProtocolArtifact): + pass + + +class ProtocolSampleTrace(ProtocolArtifact): + pass + + +class ProtocolSpecialization(ProtocolArtifact): + specialization: BehaviorSpecialization + + def __init__(self, specialization: BehaviorSpecialization) -> None: + super().__init__() + self.specialization = specialization + + def write_output(self, filename_prefix: str): + pass + + +class ProtocolHarness: + entry_point: Callable + artifacts: List[ProtocolArtifact] = [] + base_artifacts: List[ProtocolArtifact] = [ + ProtocolNTuples(), + ProtocolDiagram(), + ProtocolExecutionDiagram(), + ProtocolSampleTrace(), + ProtocolExecutionNTuples(), + ] + namespace: str + protocol_name: str + protocol_long_name: str + protocol_version: str + protocol_description: str + output_dir: str = "artifacts" + libraries: List[str] = [ + "liquid_handling", + "plate_handling", + "spectrophotometry", + "sample_arrays", + ] + parameter_values: List[ParameterValue] = [] + execution_id: str = None + agent: sbol3.Agent = sbol3.Agent("labop_harness") + _doc: sbol3.Document = None + _protocol: Protocol = None + + def __init__(self, *args, **kwargs): + self.entry_point = kwargs["entry_point"] + self.artifacts = ( + kwargs["artifacts"] if "artifacts" in kwargs else self.artifacts + ) + self.artifacts = ( + kwargs["base_artifacts"] + if "base_artifacts" in kwargs + else self.base_artifacts + ) + self.namespace = kwargs["namespace"] + self.protocol_name = kwargs["protocol_name"] + self.protocol_long_name = kwargs["protocol_long_name"] + self.protocol_version = kwargs["protocol_version"] + self.protocol_description = kwargs["protocol_description"] + self.output_dir = ( + kwargs["output_dir"] if "output_dir" in kwargs else self.output_dir + ) + self.libraries = ( + kwargs["libraries"] if "libraries" in kwargs else self.libraries + ) + self.parameter_values = ( + kwargs["parameter_values"] + if "parameter_values" in kwargs + else self.parameter_values + ) + self.execution_id = ( + kwargs["execution_id"] if "execution_id" in kwargs else self.execution_id + ) + self.agent = kwargs["agent"] if "agent" in kwargs else self.agent + self._doc = None + self._protocol = None + + def import_libraries(self): + for library in self.libraries: + import_library(library) + + def generate_protocol(self) -> Protocol: + self.import_libraries() + self._protocol = Protocol(self.protocol_name) + self._protocol.name = self.protocol_long_name + self._protocol.version = self.protocol_version + self._protocol.description = self.protocol_description + self._doc.add(self._protocol) + self._protocol = self.entry_point(self._doc, self._protocol) + l.info("Validating and writing protocol") + v = self._doc.validate() + assert len(v) == 0, "".join(f"\n {e}" for e in v) + + return self._protocol + + def prepare_document(self) -> sbol3.Document: + self._doc = prepare_document(namespace=self.namespace) + return self._doc + + def filename_prefix(self) -> str: + return self.entry_point.__name__ + + def ntuples_filename(self) -> str: + return self.filename_prefix() + ".nt" + + def diagram_filename(self) -> str: + return self.filename_prefix() + ".diagram" + + def dataset_filename(self) -> str: + return self.filename_prefix() + ".data.xslx" + + def read_protocol(self, filename: str = None): + filename = self.ntuples_filename() if filename is None else filename + self.prepare_document() + self._doc.read(filename, "nt") + self._protocol = doc.find(f"{self.namespace}{self.protocol_name}") + + return self._protocol, self._doc + + def execution_engine( + self, + specializations: List[BehaviorSpecialization], + dataset_filename: str, + ) -> ExecutionEngine: + return ExecutionEngine( + out_dir=self.output_dir, + specializations=specializations, + failsafe=False, + sample_format="xarray", + dataset_file=dataset_filename, + ) + + def get_execution_id(self) -> str: + if self.execution_id is None: + self.execution_id = ( + (f"harness_execution_{self.protocol_name}_{datetime.now()}") + .replace(" ", "_") + .replace("-", "_") + .replace(":", "_") + .replace(".", "_") + ) + return self.execution_id + + def artifacts_summary(self) -> str: + summary = "" + for a in self.artifacts: + summary += f" - {a.__class__.__name__}: {a.summary()}\n" + return summary + + def artifacts_results_summary(self) -> str: + summary = "" + for a in self.artifacts: + summary += f" - {a.__class__.__name__}: {a.results_summary()}\n" + return summary + + def run(self, base_dir="."): + l.info( + f""" +{'*'*80} + + LabOP Protocol Harness + + Configuration: + -------------- + Artifacts: +{self.artifacts_summary()} +{'*'*80} + """ + ) + full_output_dir = os.path.join(base_dir, self.output_dir) + # Store outputs in full_output_dir + os.makedirs(full_output_dir, exist_ok=True) + l.info("Writing protocol artifacts to: {full_output_dir}") + + all_artifacts = self.base_artifacts + self.artifacts + + generate_nt_file = any( + a for a in all_artifacts if isinstance(a, ProtocolNTuples) + ) + nt_filename = os.path.join(full_output_dir, self.ntuples_filename()) + + # 1) Get the self._protocol either by generating it or reading it + if generate_nt_file: + self.prepare_document() + self.generate_protocol() + else: + l.info(f"Bypassing Protocol Generation, looking for existing .nt file ...") + if os.path.exists(nt_filename): + l.info(f"Found .nt file: {nt_filename}") + self.read_protocol() + + # 2) Create any protocol-specific artifacts + if generate_nt_file: + with open(nt_filename, "w") as f: + l.info(f"Saving protocol [{nt_filename}].") + f.write(self._doc.write_string(sbol3.SORTED_NTRIPLES).strip()) + if any(a for a in all_artifacts if isinstance(a, ProtocolDiagram)): + self._protocol.to_dot().render( + os.path.join(full_output_dir, self.diagram_filename()), + cleanup=True, + ) + + # 3) Generate execution-specific artifacts + sample_trace = any( + a for a in all_artifacts if isinstance(a, ProtocolSampleTrace) + ) + dataset_filename = ( + os.path.join(full_output_dir, self.dataset_filename()) + if sample_trace + else None + ) + + specializations = [ + a for a in all_artifacts if isinstance(a, ProtocolSpecialization) + ] + + ee = self.execution_engine( + [s.specialization for s in specializations], dataset_filename + ) + + execution = ee.execute( + self._protocol, + self.agent, + id=self.get_execution_id(), + parameter_values=self.parameter_values, + ) + + if any(a for a in all_artifacts if isinstance(a, ProtocolExecutionNTuples)): + with open(nt_filename, "w") as f: + f.write(self._doc.write_string(sbol3.SORTED_NTRIPLES).strip()) + + for specialization in specializations: + results = specialization.output() + specialization_classname = specialization.__class__.__name__ + specialization_dir = os.path.join(full_output_dir, specialization_classname) + os.makedirs(specialization_dir, exist_ok=True) + for i, result in enumerate(results): + # extension = mimetypes.guess_extension(magic.Magic(mime=True).from_file(result)) + extension = "json" + result_file = os.path.join( + specialization_dir, + f"{specialization_classname}_result_{i}.{extension}", + ) + with open(result_file, "w") as f: + f.write(result) + + l.info( + f""" +{'*'*80} + + Harness Results Summary + + Artifacts: +{self.artifacts_results_summary()} +{'*'*80} + """ + ) diff --git a/labop_convert/behavior_specialization.py b/labop_convert/behavior_specialization.py index 53185392..03671da2 100644 --- a/labop_convert/behavior_specialization.py +++ b/labop_convert/behavior_specialization.py @@ -2,6 +2,7 @@ import logging import os from abc import ABC +from typing import Any, List import tyto @@ -77,6 +78,10 @@ def on_end(self, execution: "ProtocolExecution"): ) as f: f.write(self.data) + def output(self) -> List[Any]: + results = self.data + return results + def process(self, record, execution: ProtocolExecution, timepoint="start"): try: node = record.node.lookup() diff --git a/labop_convert/markdown/markdown_specialization.py b/labop_convert/markdown/markdown_specialization.py index ef501657..7c1f2aa5 100644 --- a/labop_convert/markdown/markdown_specialization.py +++ b/labop_convert/markdown/markdown_specialization.py @@ -754,7 +754,9 @@ def transfer( # Get destination container type container_spec = destination.get_container_type() container_class = ( - ContainerOntology.uri + "#" + container_spec.queryString.split(":")[-1] + (ContainerOntology.uri + "#" + container_spec.queryString.split(":")[-1]) + if not container_spec.queryString.startswith(ContainerOntology.uri) + else container_spec.queryString ) container_str = ContainerOntology.get_term_by_uri(container_class) diff --git a/labop_convert/pylabrobot/pylabrobot_specialization.py b/labop_convert/pylabrobot/pylabrobot_specialization.py index 53b60d53..c6e1be75 100644 --- a/labop_convert/pylabrobot/pylabrobot_specialization.py +++ b/labop_convert/pylabrobot/pylabrobot_specialization.py @@ -17,7 +17,8 @@ container_ontology_path = os.path.join( - os.path.dirname(os.path.realpath(__file__)), "../../labop/container-ontology.ttl" + os.path.dirname(os.path.realpath(__file__)), + "../../labop/container-ontology.ttl", ) ContO = tyto.Ontology( path=container_ontology_path, @@ -27,26 +28,6 @@ # Map pylabrobot pipette names to compatible tipracks # left is for Pylabrobot names # right is for LabOp names(container ontology) -COMPATIBLE_TIPS = { - "p20_single_gen2": ["opentrons_96_tiprack_10ul", "opentrons_96_filtertiprack_10ul"], - "p300_single_gen2": ["opentrons_96_tiprack_300ul"], - "p1000_single_gen2": [ - "opentrons_96_tiprack_1000ul", - "opentrons_96_filtertiprack_1000ul", - ], - "p300_multi_gen2": [], - "p20_multi_gen2": [], - "p10_single": ["opentrons_96_tiprack_10ul", "opentrons_96_filtertiprack_10ul"], - "p10_multi": ["opentrons_96_tiprack_10ul", "opentrons_96_filtertiprack_10ul"], - "p50_single": [], - "p50_multi": [], - "p300_single": ["opentrons_96_tiprack_300ul"], - "p300_multi": [], - "p1000_single": [ - "opentrons_96_tiprack_1000ul", - "opentrons_96_filtertiprack_1000ul", - ], -} # Map terms in the Container ontology of pylabrobot and assign them to LabOP container onthology # its taking a LabOp term and making a correspondence to a Pylabrobot term @@ -58,12 +39,12 @@ # this is for TIP carriers (C:\Users\Luiza\pylabrobot\pylabrobot\resources\ml_star\tip_carriers.py) # HAMILTON ML star tip carriers ContO[ - "ML STAR Tip carrier with 5 4ml tip with filter racks landscape" + "ML STAR Tip Carrier with 5 4ml tip with filter racks landscape" ]: "TIP_CAR_120BC_4mlTF_A00", ContO[ "ML STAR Tip carrier with 5 5ml tip racks landscape" ]: "TIP_CAR_120BC_5mlT_A00", - # ContO["ML STAR Tip carrier for 3 Racks with 96 Tips portrait [revision A00]"]: "TIP_CAR_288_A00", + ContO["Corning 96 Well Plate"]: "TIP_CAR_288_A00", # ContO["ML STAR Tip carrier for 3 Racks with 96 Tips portrait [revision B00]"]: "TIP_CAR_288_B00", # ContO["ML STAR Tip carrier for 3 Racks with 96 Tips portrait [revision C00]"]: "TIP_CAR_288_C00", # ContO["ML STAR Tip carrier with 3 high volume tip with filter racks portrait [revision A00]"]: "TIP_CAR_288_HTF_A00", @@ -110,12 +91,12 @@ # ContO["Corning Costar 10 ul plate [1536]"]: "Cos_1536_10ul", # ContO["Corning Costar deep well plate [384]"]: "Cos_384_DW", # ContO["Corning Costar PCR plate [384]"]: "Cos_384_PCR", - # ContO["Corning Costar 1 mL deep well plate [96]"]: "Cos_96_DW_1mL", + ContO["Corning Costar 1 mL deep well plate with 96 wells"]: "Cos_96_DW_1mL", # ContO["Corning Costar 2 mL deep well plate [96]"]: "Cos_96_DW_2mL", # ContO["Corning Costar 500ul deep well plate [96]"]: "Cos_96_DW_500ul", - # ContO["Corning Costar EZwash plate [96]"]: "Cos_96_EZWash", - # ContO["Corning Costar FL plate [96]"]: "Cos_96_FL", - # ContO["Corning Costar filter plate [96]"]: "Cos_96_Filter", + ContO["Corning Costar EZwash plate with 96 wells"]: "Cos_96_EZWash", + ContO["Corning 96 Well Plate 360 uL Flat"]: "Cos_96_FL", + ContO["Corning Costar filter plate with 96 wells"]: "Cos_96_Filter", # ContO["Corning Costar Half area plate [96]"]: "Cos_96_HalfArea", # ContO["Corning Costar filter plate [96]"]: "Cos_96_Filter", # ContO["Corning Costar PCR plate [96]"]: "Cos_96_PCR", @@ -128,7 +109,7 @@ # #""" HAMILTON ML Star tips """ # ContO["Tip Rack 24x 4ml Tip with Filter landscape oriented"]: "FourmlTF_L", # ContO["Tip Rack 24x 5ml Tip landscape oriented"]: "FivemlT_L", - # ContO["Tip Rack with 96 1000ul High Volume Tip with filter"]: "HTF_L", + ContO["ML STAR Tip Rack with 96 1000ul High Volume Tip with filter"]: "HTF_L", # ContO["Tip Rack with 96 1000ul High Volume Tip"]: "HT_L", # ContO["Tip Rack with 96 10ul Low Volume Tip with filter"]: "LTF_L", # ContO["Tip Rack with 96 10ul Low Volume Tip"]: "LT_L", @@ -192,63 +173,65 @@ def _init_behavior_func_map(self) -> dict: "https://bioprotocols.org/labop/primitives/sample_arrays/LoadContainerInRack": self.load_container_in_rack, "https://bioprotocols.org/labop/primitives/sample_arrays/LoadContainerOnInstrument": self.load_container_on_instrument, # "https://bioprotocols.org/labop/primitives/sample_arrays/LoadRackOnInstrument": self.load_racks, - "https://bioprotocols.org/labop/primitives/sample_arrays/ConfigureRobot": self.configure_robot, - "https://bioprotocols.org/labop/primitives/pcr/PCR": self.pcr, + # "https://bioprotocols.org/labop/primitives/sample_arrays/ConfigureRobot": self.configure_robot, + # "https://bioprotocols.org/labop/primitives/pcr/PCR": self.pcr, + "https://bioprotocols.org/labop/primitives/plate_handling/Filter": self.activate_airpump, } - - def _materials(self): - protocol = self.execution.protocol.lookup() - - materials = { - obj.name: obj - for obj in protocol.document.objects - if type(obj) is sbol3.Component - } - markdown = "\n\n## Protocol Materials:\n" - for name, material in materials.items(): - markdown += f"* [{name}]({material.types[0]})\n" - - # Compute container types and quantities - document_objects = [] - protocol.document.traverse(lambda obj: document_objects.append(obj)) - call_behavior_actions = [ - obj for obj in document_objects if type(obj) is uml.CallBehaviorAction - ] - containers = {} - for cba in call_behavior_actions: - input_names = [input.name for input in cba.inputs] - if "specification" in input_names: - container = cba.input_pin("specification").value.value.lookup() - elif "rack" in input_names: - container = cba.input_pin("rack").value.value.lookup() - elif ( - "container" in input_names - and type(cba.input_pin("container")) is uml.ValuePin - ): - container = cba.input_pin("container").value.value.lookup() - else: - continue - container_type = container.queryString - container_name = container.name if container.name else "unnamed" - qty = cba.input_pin("quantity") if "quantity" in input_names else 1 - - if container_type not in containers: - containers[container_type] = {} - containers[container_type][container_name] = qty - - for container_type, container_name_map in containers.items(): - for container_name, qty in container_name_map.items(): - container_str = ContO.get_term_by_uri(container_type) - if "TipRack" in container_type: - text = f"* {container_str}" - elif container_name == "unnamed": - text = f"* unnamed {container_str}" - else: - text = f"* `{container_name}` ({container_str})" - if qty > 1: - text += f" (x {qty})" - text += "\n" - markdown += text + # the protocol should have the namespace + + # def _materials(self): + # protocol = self.execution.protocol.lookup() + + # materials = { + # obj.name: obj + # for obj in protocol.document.objects + # if type(obj) is sbol3.Component + # } + # markdown = "\n\n## Protocol Materials:\n" + # for name, material in materials.items(): + # markdown += f"* [{name}]({material.types[0]})\n" + + # Compute container types and quantities + # document_objects = [] + # protocol.document.traverse(lambda obj: document_objects.append(obj)) + # call_behavior_actions = [ + # obj for obj in document_objects if type(obj) is uml.CallBehaviorAction + # ] + # containers = {} + # for cba in call_behavior_actions: + # input_names = [input.name for input in cba.inputs] + # if "specification" in input_names: + # container = cba.input_pin("specification").value.value.lookup() + # elif "rack" in input_names: + # container = cba.input_pin("rack").value.value.lookup() + # elif ( + # "container" in input_names + # and type(cba.input_pin("container")) is uml.ValuePin + # ): + # container = cba.input_pin("container").value.value.lookup() + # else: + # continue + # container_type = container.queryString + ## container_name = container.name if container.name else "unnamed" + # qty = cba.input_pin("quantity") if "quantity" in input_names else 1 + + # if container_type not in containers: + # containers[container_type] = {} + # containers[container_type][container_name] = qty + + # for container_type, container_name_map in containers.items(): + # for container_name, qty in container_name_map.items(): + # container_str = ContO.get_term_by_uri(container_type) + # if "TipRack" in container_type: + # text = f"* {container_str}" + # elif container_name == "unnamed": + # text = f"* unnamed {container_str}" + # else: + # text = f"* `{container_name}` ({container_str})" + # if qty > 1: + # text += f" (x {qty})" + # text += "\n" + # markdown += text def handle_process_failure(self, record, exception): super().handle_process_failure(record, exception) @@ -258,13 +241,27 @@ def on_begin(self, ex: labop.ProtocolExecution): protocol = self.execution.protocol.lookup() apilevel = self.apilevel self.markdown += f"# {protocol.name}\n" - self.script += ( - "from opentrons import protocol_api\n\n" - f"metadata = {{'apiLevel': '{apilevel}',\n" - f" 'description': '{protocol.description}',\n" - f" 'protocolName': '{protocol.name}'}} \n\n" - "def run(protocol: protocol_api.ProtocolContext):\n" - ) + self.script += """import asyncio + +from pylabrobot.liquid_handling import LiquidHandler +from pylabrobot.liquid_handling.backends.simulation.simulator_backend import ( + SimulatorBackend, +) +from pylabrobot.resources import Cos_96_EZWash, Cos_96_PCR, HTF_L, Coordinate +from pylabrobot.resources.hamilton import STARLetDeck +from pylabrobot import MPE +from pylabrobot import mpebackend + + +backend = SimulatorBackend() +deck = STARLetDeck() +sb = SimulatorBackend(open_browser=False) +lh = LiquidHandler(backend=sb, deck=STARLetDeck()) + + +async def LiquidHandler_setup(): + await lh.setup() +""" self.data = [] def on_end(self, ex): @@ -295,10 +292,10 @@ def _compile_markdown(self): markdown += str(i + 1) + ". " + step + "\n" return markdown - ################################################### - # see about def _tipracks object - ################################################## - def _materials(self): + ################################################### + # see about def _tipracks object + ################################################## + # def _materials(self): protocol = self.execution.protocol.lookup() materials = { @@ -378,8 +375,8 @@ def define_container( call = record.call.lookup() parameter_value_map = call.parameter_value_map() - spec = parameter_value_map["specification"]["value"] - samples = parameter_value_map["samples"]["value"] + spec = parameter_value_map["specification"] + samples = parameter_value_map["samples"] # SampleArray fields are initialized in primitive_execution.py def time_wait( @@ -388,8 +385,8 @@ def time_wait( results = {} call = record.call.lookup() parameter_value_map = call.parameter_value_map() - value = parameter_value_map["amount"]["value"].value - units = parameter_value_map["amount"]["value"].unit + value = parameter_value_map["amount"].value + units = parameter_value_map["amount"].unit self.script_steps += [f"time.sleep(value)"] def plate_coordinates( @@ -397,9 +394,9 @@ def plate_coordinates( ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - source = parameter_value_map["source"]["value"] - coords = parameter_value_map["coordinates"]["value"] - samples = parameter_value_map["samples"]["value"] + source = parameter_value_map["source"] + coords = parameter_value_map["coordinates"] + samples = parameter_value_map["samples"] if not hasattr(samples, "mask") or samples.mask is None: samples.mask = coords @@ -410,12 +407,12 @@ def provision( results = {} call = record.call.lookup() parameter_value_map = call.parameter_value_map() - destination = parameter_value_map["destination"]["value"] - value = parameter_value_map["amount"]["value"].value - units = parameter_value_map["amount"]["value"].unit + destination = parameter_value_map["destination"] + value = parameter_value_map["amount"].value + units = parameter_value_map["amount"].unit units = tyto.OM.get_term_by_uri(units) - resource = parameter_value_map["resource"]["value"] - amount = parameter_value_map["amount"]["value"] + resource = parameter_value_map["resource"] + amount = parameter_value_map["amount"] amount = measurement_to_text(amount) coords = "" coords = ( @@ -427,19 +424,17 @@ def provision( .value.value ) upstream_execution = get_token_source("destination", record) - container = upstream_execution.call.lookup().parameter_value_map()["container"][ - "value" - ] + container = upstream_execution.call.lookup().parameter_value_map()["container"] behavior_type = get_behavior_type(upstream_execution) if behavior_type == "LoadContainerInRack": coords = upstream_execution.call.lookup().parameter_value_map()[ "coordinates" - ]["value"] + ] upstream_execution = get_token_source("slots", upstream_execution) rack = upstream_execution.call.lookup().parameter_value_map()[ "specification" - ]["value"] + ] else: raise NotImplementedError( f'A "Provision" call cannot follow a "{behavior_type}" call' @@ -451,6 +446,7 @@ def provision( rack_str = f"`{rack.name}`" if rack.name else rack.queryString text = f"Fill {amount} of {resource.name} into {container_str} located in {coords} of {rack_str}" self.markdown_steps += [text] + # write pylabrobot correspondence # write correspondence for transfer primitive def transfer_to( @@ -459,10 +455,10 @@ def transfer_to( results = {} call = record.call.lookup() parameter_value_map = call.parameter_value_map() - destination = parameter_value_map["destination"]["value"] - source = parameter_value_map["source"]["value"] - value = parameter_value_map["amount"]["value"].value - units = parameter_value_map["amount"]["value"].unit + destination = parameter_value_map["destination"] + source = parameter_value_map["source"] + value = parameter_value_map["amount"].value + units = parameter_value_map["amount"].unit units = tyto.OM.get_term_by_uri(units) OT2Pipette = "left" @@ -474,26 +470,26 @@ def transfer_to( behavior_type = get_behavior_type(upstream_execution) if behavior_type == "PlateCoordinates": upstream_map = upstream_execution.call.lookup().parameter_value_map() - coordinates = upstream_map["coordinates"]["value"] + coordinates = upstream_map["coordinates"] upstream_execution = upstream_execution.get_token_source( upstream_map["source"]["parameter"].property_value ) # EmptyContainer parameter_value_map = upstream_execution.call.lookup().parameter_value_map() - source_container = parameter_value_map["specification"]["value"] + source_container = parameter_value_map["specification"] elif behavior_type == "LoadContainerInRack": upstream_execution = upstream_execution.get_token_source( upstream_map["slots"]["parameter"].property_value ) # EmptyRack parameter_value_map = upstream_execution.call.lookup().parameter_value_map() - source_container = parameter_value_map["specification"]["value"] + source_container = parameter_value_map["specification"] elif behavior_type == "LoadContainerOnInstrument": upstream_map = upstream_execution.call.lookup().parameter_value_map() - coordinates = upstream_map["slots"]["value"] + coordinates = upstream_map["slots"] upstream_execution = upstream_execution.get_token_source( upstream_map["container"]["parameter"].property_value ) # EmptyContainer parameter_value_map = upstream_execution.call.lookup().parameter_value_map() - source_container = parameter_value_map["specification"]["value"] + source_container = parameter_value_map["specification"] else: raise Exception(f'Invalid input pin "source" for Transfer.') @@ -516,7 +512,7 @@ def transfer_to( behavior_type = get_behavior_type(upstream_execution) if behavior_type == "PlateCoordinates": upstream_map = upstream_execution.call.lookup().parameter_value_map() - coordinates = upstream_map["coordinates"]["value"] + coordinates = upstream_map["coordinates"] upstream_execution = upstream_execution.get_token_source( upstream_map["source"]["parameter"].property_value ) # EmptyContainer @@ -525,7 +521,7 @@ def transfer_to( elif behavior_type == "LoadContainerOnInstrument": upstream_map = upstream_execution.call.lookup().parameter_value_map() - coordinates = upstream_map["slots"]["value"] + coordinates = upstream_map["slots"] upstream_execution = upstream_execution.get_token_source( upstream_map["container"]["parameter"].property_value ) # EmptyContainer @@ -566,7 +562,7 @@ def transfer_to( destination_str = destination.mask for c_source in source.get_coordinates(): for c_destination in destination.get_coordinates(): - self.script_steps += [ + self.script_steps += [ # make it a list with 5 elements (pick up, aspirate, dispense, return tips) f"{pipette.display_id}.transfer({value}, {source_name}['{c_source}'], {destination_name}['{c_destination}']) {comment}" ] @@ -577,12 +573,16 @@ def transfer_by_map( results = {} call = record.call.lookup() parameter_value_map = call.parameter_value_map() - destination = parameter_value_map["destination"]["value"] - source = parameter_value_map["source"]["value"] - plan = parameter_value_map["plan"]["value"] - temperature = parameter_value_map["temperature"]["value"] - value = parameter_value_map["amount"]["value"].value - units = parameter_value_map["amount"]["value"].unit + destination = parameter_value_map["destination"][ + "value" + ] # those are gonna be sample arrays + source = parameter_value_map["source"][ + "value" + ] # those are gonna be sample arrays + plan = parameter_value_map["plan"] + temperature = parameter_value_map["temperature"] + value = parameter_value_map["amount"].value + units = parameter_value_map["amount"].unit units = tyto.OM.get_term_by_uri(units) pylabrobot = "left" @@ -595,11 +595,11 @@ def transfer_by_map( "slots" ) # EmptyRack parameter_value_map = upstream_execution.call.lookup().parameter_value_map() - source_container = parameter_value_map["specification"]["value"] + source_container = parameter_value_map["specification"] else: raise Exception(f'Invalid input pin "source" for Transfer.') - # Map the source container to a variable name in the OT2 api script + #############trace the source container to a variable name in the pylabrobot script######## source_name = None for deck, labware in self.configuration.items(): if labware == source_container: @@ -635,22 +635,36 @@ def transfer_by_map( ) pipette = self.configuration["left"] + source.container_type + destination.container_type + source.container_type.lookup + + # make it a list with 5 elements (pick up, aspirate, dispense, return tips) this string when constructed will substitute variables declared by values on the protocol source_str = source.mask destination_str = destination.mask for c_source in get_sample_list(source.mask): for c_destination in get_sample_list(destination.mask): - self.script_steps += [ - f"{pipette.display_id}.transfer({value}, {source_name}['{c_source}'], {destination_name}['{c_destination}'])" - ] - + self.script_steps += f"""async def liquid_handling_sequence(): + await lh.pick_up_tips({primitive_tip_rack}[{source_str}]) + lh + await lh.aspirate({source}[{source_str}], + vols={value}, + flow_rates={100}, + end_delay=0.5, + offsets=Coordinate(1, 2, 3)) + await lh.dispense({destination}[{destination_str}], vols={value}) + await lh.return_tips() """ + + # take information present in the primitive and construct string to be + # make it a list with 5 elements (pick up, aspirate, dispense, return tips) def define_rack( self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - spec = parameter_value_map["specification"]["value"] - slots = parameter_value_map["slots"]["value"] + spec = parameter_value_map["specification"] + slots = parameter_value_map["slots"] # FIXME the protocol var_to_entity mapping links variables created in # the execution trace with real values assigned here, such as @@ -669,12 +683,12 @@ def load_container_in_rack( parameter_value_map = call.parameter_value_map() container: labop.ContainerSpec = parameter_value_map["container"]["value"] coords: str = ( - parameter_value_map["coordinates"]["value"] + parameter_value_map["coordinates"] if "coordinates" in parameter_value_map else "A1" ) - slots: labop.SampleCollection = parameter_value_map["slots"]["value"] - samples: labop.SampleMask = parameter_value_map["samples"]["value"] + slots: labop.SampleCollection = parameter_value_map["slots"] + samples: labop.SampleMask = parameter_value_map["samples"] # TODO: validate coordinates for the given container spec samples.source = slots @@ -711,16 +725,12 @@ def load_container_on_instrument( ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - container_spec: labop.ContainerSpec = parameter_value_map["specification"][ - "value" - ] + container_spec: labop.ContainerSpec = parameter_value_map["specification"] slots: str = ( - parameter_value_map["slots"]["value"] - if "slots" in parameter_value_map - else "A1" + parameter_value_map["slots"] if "slots" in parameter_value_map else "A1" ) - instrument: sbol3.Agent = parameter_value_map["instrument"]["value"] - samples: labop.SampleArray = parameter_value_map["samples"]["value"] + instrument: sbol3.Agent = parameter_value_map["instrument"] + samples: labop.SampleArray = parameter_value_map["samples"] # Assume 96 well plate aliquots = get_sample_list(geometry="A1:H12") @@ -750,3 +760,32 @@ def load_container_on_instrument( instrument.configuration = {} for c in get_sample_list(slots): instrument.configuration[c] = container_spec + + def activate_airpump( + self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + ): + output_string = """ + comPort = 12 + BaudRate = 921600 + SimulationMode = 0 + options = 0 + FilterHeight = 14.9 + NozzleHeight = 14.9 + + ControlPoints = "pressure, 0, 5;pressure, 10, 5;pressure, 15, 5;pressure, 20, 5;pressure, 30, 5;pressure, 40, 5;pressure, 50, 5; pressure, 60, 5" + ReturnPlateToIntegrationArea = 1 + WasteContainerID = 0 + DisableVacuumCheck = 1 + + + + async def MPE_overpressure(): + await MPE.mpe2_FilterPlatePlaced(MPE, 1, FilterHeight, NozzleHeight) + await MPE.mpe2_ProcessFilterToWasteContainer(MPE, 1, ControlPoints,ReturnPlateToIntegrationArea, WasteContainerID, DisableVacuumCheck) + await MPE.mpe2_FilterPlateRemoved(MPE, 1) + + + + asyncio .run(__init__()) + asyncio .run(MPE_overpressure())""" + self.script_steps += [output_string] diff --git a/notebooks/Opentrons.ipynb b/notebooks/Opentrons.ipynb index 128f9190..b3d4fdf8 100644 --- a/notebooks/Opentrons.ipynb +++ b/notebooks/Opentrons.ipynb @@ -94,19 +94,16 @@ "protocol.name = \"OT2 demo\"\n", "doc.add(protocol)\n", "\n", - "CONT_NS = rdfl.Namespace('https://sift.net/container-ontology/container-ontology#')\n", - "OM_NS = rdfl.Namespace('http://www.ontology-of-units-of-measure.org/resource/om-2/')\n", - "PREFIX_MAP = json.dumps({\"cont\": CONT_NS, \"om\": OM_NS})\n", "\n", "# plate = protocol.load_labware('corning_96_wellplate_360ul_flat', location='1')\n", "plate_spec = labop.ContainerSpec('sample_plate', name='sample plate', \n", " queryString='cont:Corning96WellPlate360uLFlat', \n", - " prefixMap=PREFIX_MAP)\n", + " prefixMap=labop.constants.PREFIX_MAP)\n", "plate = protocol.primitive_step('EmptyContainer', specification=plate_spec)\n", "load_plate = protocol.primitive_step('LoadRackOnInstrument', rack=plate_spec, coordinates='1')\n", "\n", "# tiprack = protocol.load_labware('opentrons_96_tiprack_300ul', location='2')\n", - "tiprack_spec = labop.ContainerSpec('tiprack', queryString='cont:Opentrons96TipRack300uL', prefixMap=PREFIX_MAP)\n", + "tiprack_spec = labop.ContainerSpec('tiprack', queryString='cont:Opentrons96TipRack300uL', prefixMap=labop.constants.PREFIX_MAP)\n", "tiprack = protocol.primitive_step('LoadRackOnInstrument', rack=tiprack_spec, coordinates='2')\n", "\n", "# left_pipette = protocol.load_instrument(\n", diff --git a/notebooks/labop_author_demo.ipynb b/notebooks/labop_author_demo.ipynb index 08fa89ce..2c8098e4 100644 --- a/notebooks/labop_author_demo.ipynb +++ b/notebooks/labop_author_demo.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "id": "999d9675", "metadata": { @@ -55,6 +56,7 @@ "import json\n", "import rdflib as rdfl\n", "from IPython.display import Markdown\n", + "from labop.constants import ddh2o, ludox\n", "\n", "\n", "from labop.execution_engine import ExecutionEngine\n", @@ -188,12 +190,7 @@ "outputs": [], "source": [ "# create the materials to be provisioned\n", - "ddh2o = sbol3.Component('ddH2O', 'https://identifiers.org/pubchem.substance:24901740')\n", - "ddh2o.name = 'Water, sterile-filtered, BioReagent, suitable for cell culture' \n", "doc.add(ddh2o)\n", - "\n", - "ludox = sbol3.Component('LUDOX', 'https://identifiers.org/pubchem.substance:24866361')\n", - "ludox.name = 'LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O'\n", "doc.add(ludox)" ] }, @@ -215,12 +212,8 @@ " ((om:hasUnit value om:microlitre) and\n", " (om:hasNumericalValue only xsd:decimal[>= \"200\"^^xsd:decimal])))\"\"\"\n", "\n", - "CONT_NS = rdfl.Namespace('https://sift.net/container-ontology/container-ontology#')\n", - "OM_NS = rdfl.Namespace('http://www.ontology-of-units-of-measure.org/resource/om-2/')\n", - "\n", - "PREFIX_MAP = json.dumps({\"cont\": CONT_NS, \"om\": OM_NS})\n", "\n", - "spec = labop.ContainerSpec(queryString=PLATE_SPECIFICATION, prefixMap=PREFIX_MAP, name='plateRequirement')" + "spec = labop.ContainerSpec(queryString=PLATE_SPECIFICATION, prefixMap=labop.constants.labop.constants.PREFIX_MAP, name='plateRequirement')" ] }, { diff --git a/notebooks/labop_demo.ipynb b/notebooks/labop_demo.ipynb index ecb3e73e..8ab6c8ed 100644 --- a/notebooks/labop_demo.ipynb +++ b/notebooks/labop_demo.ipynb @@ -22,6 +22,7 @@ "from labop.execution_engine import ExecutionEngine\n", "# from labop_check.labop_check import check_doc\n", "from labop_convert.markdown.markdown_specialization import MarkdownSpecialization\n", + "from labop.constants import ddh2o, ludox\n", "\n", "%load_ext autoreload\n", "%autoreload 2" @@ -147,12 +148,7 @@ "outputs": [], "source": [ "# create the materials to be provisioned\n", - "ddh2o = sbol3.Component('ddH2O', 'https://identifiers.org/pubchem.substance:24901740')\n", - "ddh2o.name = 'Water, sterile-filtered, BioReagent, suitable for cell culture' \n", "doc.add(ddh2o)\n", - "\n", - "ludox = sbol3.Component('LUDOX', 'https://identifiers.org/pubchem.substance:24866361')\n", - "ludox.name = 'LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O'\n", "doc.add(ludox)" ] }, @@ -172,12 +168,7 @@ " ((om:hasUnit value om:microlitre) and\n", " (om:hasNumericalValue only xsd:decimal[>= \"200\"^^xsd:decimal])))\"\"\"\n", "\n", - "CONT_NS = rdfl.Namespace('https://sift.net/container-ontology/container-ontology#')\n", - "OM_NS = rdfl.Namespace('http://www.ontology-of-units-of-measure.org/resource/om-2/')\n", - "\n", - "PREFIX_MAP = json.dumps({\"cont\": CONT_NS, \"om\": OM_NS})\n", - "\n", - "spec = labop.ContainerSpec('plate_requirement', name='plateRequirement', queryString=PLATE_SPECIFICATION, prefixMap=PREFIX_MAP)" + "spec = labop.ContainerSpec('plate_requirement', name='plateRequirement', queryString=PLATE_SPECIFICATION, prefixMap=labop.constants.PREFIX_MAP)" ] }, { diff --git a/opentrons_toy_protocol_labop.py.md b/opentrons_toy_protocol_labop.py.md new file mode 100644 index 00000000..f90cb5a7 --- /dev/null +++ b/opentrons_toy_protocol_labop.py.md @@ -0,0 +1,11 @@ +# OT2 simple toy demonstration + + +## Protocol Materials: +* `sample plate` (Corning 96 Well Plate) +* Opentrons 96 Tip Rack 300 µL + +## Steps +1. Load `sample plate` in Deck 1 of OT2 instrument +2. Load `tiprack` in Deck 2 of OT2 instrument +3. Mount `P300 Single` in left mount of the OT2 instrument diff --git a/opentrons_toy_protocol_labop.py.py b/opentrons_toy_protocol_labop.py.py new file mode 100644 index 00000000..5bceba73 --- /dev/null +++ b/opentrons_toy_protocol_labop.py.py @@ -0,0 +1,17 @@ +from opentrons import protocol_api + +metadata = { + "apiLevel": "2.11", + "description": "Example Opentrons Protocol as LabOP", + "protocolName": "OT2 simple toy demonstration", +} + + +def run(protocol: protocol_api.ProtocolContext): + labware1 = protocol.load_labware("corning_96_wellplate_360ul_flat", "1") + labware2 = protocol.load_labware("opentrons_96_tiprack_300ul", "2") + p300_single = protocol.load_instrument("p300_single", "left") + p300_single.tip_racks.append(labware2) + p300_single.transfer( + 100.0, labware1["A1"], labware1["B2"] + ) # Transfer ActivityNode name is not defined. diff --git a/setup.py b/setup.py index 9e1eae15..bfd46608 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,12 @@ from setuptools import setup -test_deps = ["nbmake", "pytest-xdist", "pre-commit", "nbstripout"] +test_deps = [ + "nbmake", + "pytest-xdist", + "pre-commit", + "nbstripout", + "parameterized", +] notebook_deps = ["ipython", "ipywidgets"] autoprotocol_deps = ["autoprotocol", "transcriptic"] extras = { diff --git a/test/test_LUDOX_protocol.py b/test/test_LUDOX_protocol.py index d4ae9949..a80e8169 100644 --- a/test/test_LUDOX_protocol.py +++ b/test/test_LUDOX_protocol.py @@ -24,7 +24,7 @@ os.mkdir(OUT_DIR) protocol_def_file = os.path.join( - os.path.dirname(__file__), "../examples/LUDOX_protocol.py" + os.path.dirname(__file__), "../examples/protocols/ludox/LUDOX_protocol.py" ) diff --git a/test/test_decision_nodes.py b/test/test_decision_nodes.py index 06234918..515da976 100644 --- a/test/test_decision_nodes.py +++ b/test/test_decision_nodes.py @@ -25,7 +25,7 @@ protocol_def_file = os.path.join( - os.path.dirname(__file__), "../examples/LUDOX_protocol.py" + os.path.dirname(__file__), "../examples/protocols/ludox/LUDOX_protocol.py" ) diff --git a/test/test_examples.py b/test/test_examples.py new file mode 100644 index 00000000..821a8999 --- /dev/null +++ b/test/test_examples.py @@ -0,0 +1,81 @@ +import glob +import logging +import os +import re +import unittest +from importlib.machinery import SourceFileLoader +from importlib.util import module_from_spec, spec_from_loader +from types import ModuleType +from typing import List + +from parameterized import parameterized + +from labop.utils.harness import ProtocolHarness + +l = logging.Logger(__file__) +l.setLevel(logging.INFO) + + +def load_protocol(testfile_path) -> ModuleType: + module_name = testfile_path.rsplit("/", 1)[1].rsplit(".py")[0].replace("-", "_") + loader = SourceFileLoader(module_name, testfile_path) + spec = spec_from_loader(loader.name, loader) + module = module_from_spec(spec) + loader.exec_module(module) + return module + + +def discover_example_protocols(example_directory: str) -> List[str]: + candidate_protocols = glob.glob(f"{example_directory}/**/*py", recursive=True) + actual_protocols = [] + for p in candidate_protocols: + with open(p, "r") as f: + lines = f.readlines() + try: + if next(l for l in lines if re.match(".*Protocol\(.*\)", l)): + actual_protocols.append(p) + except: + # Cannot find a Protocol + continue + return actual_protocols + + +example_directory = os.path.join(os.path.dirname(__file__), f"../examples/") +test_files = discover_example_protocols(example_directory) +expected_failures = { + "../examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py": { + "description": "Fails because there is a missing primer layout csv." + } +} + + +class TestModels(unittest.TestCase): + @parameterized.expand(test_files) + def test_protocol(self, test_file): + test_file_abs_path = test_file.split(os.path.dirname(__file__))[1][1:] + try: + module = load_protocol(test_file) + model_protocol_harnesses = { + k: v + for k, v in module.__dict__.items() + if isinstance(v, ProtocolHarness) + } + output_base_dir = os.path.join( + os.path.dirname(__file__), + "out", + test_file_abs_path.split("../examples/protocols/")[1].split(".py")[0], + ) + for id, harness in model_protocol_harnesses.items(): + l.info(f"Running ProtocolHarness '{id}' ...") + harness.run(base_dir=output_base_dir) + except Exception as e: + assert ( + test_file_abs_path in expected_failures + ), f"({test_file}) Example unexpectedly failed: {e}" + l.info( + f"({test_file}) Example failed as expected: {expected_failures[test_file_abs_path]['description']}" + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/test_opentrons.py b/test/test_opentrons.py index 382f5510..f5833c67 100644 --- a/test/test_opentrons.py +++ b/test/test_opentrons.py @@ -34,7 +34,10 @@ def load_protocol(protocol_def_fn, protocol_filename): CWD = os.path.split(os.path.realpath(__file__))[0] -protocol_def_file = os.path.join(CWD, "../examples/opentrons_toy_protocol.py") +protocol_def_file = os.path.join( + CWD, + "../examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py", +) protocol_def = load_protocol("opentrons_toy_protocol", protocol_def_file) diff --git a/test/test_sampledata.py b/test/test_sampledata.py index d08df379..3d210a59 100644 --- a/test/test_sampledata.py +++ b/test/test_sampledata.py @@ -32,7 +32,7 @@ TMPDIR = tempfile.gettempdir() protocol_def_file = os.path.join( - os.path.dirname(__file__), "../examples/LUDOX_protocol.py" + os.path.dirname(__file__), "../examples/protocols/ludox/LUDOX_protocol.py" ) diff --git a/uml/activity.py b/uml/activity.py index 199bacd0..d33bbfee 100644 --- a/uml/activity.py +++ b/uml/activity.py @@ -395,7 +395,12 @@ def validate(self, report: sbol3.ValidationReport = None) -> sbol3.ValidationRep multi_targets = { n: c for n, c in source_counts.items() - if c > 1 and not (isinstance(n, ForkNode) or isinstance(n, DecisionNode)) + if c > 1 + and not ( + isinstance(n, ForkNode) + or isinstance(n, DecisionNode) + or isinstance(n, CallBehaviorAction) + ) } for n, c in multi_targets.items(): report.addWarning( diff --git a/uml/utils.py b/uml/utils.py index 27b72184..f7115ef2 100644 --- a/uml/utils.py +++ b/uml/utils.py @@ -206,7 +206,6 @@ def is_in_labop(self, cf): def get_defn_stack(self, cf, last=False): parent_frame_info = [] if cf.f_back: - if not last: # looking for outer call still # stop recursion after next frame if the current frame is in labop, but the next is not. @@ -231,7 +230,10 @@ def get_defn_stack(self, cf, last=False): def frameinfo(self, cf, last=False): frameinfo = getframeinfo(cf) - context = "\n" + "\n".join(frameinfo.code_context) if last else "" + if frameinfo.code_context is not None: + context = "\n" + "\n".join(frameinfo.code_context) if last else "" + else: + context = "" return f"{frameinfo.filename}:{frameinfo.lineno}{context}" def get_where_defined(self): From 997210b1ff24383a2707826fca439389ba417719 Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:42:44 -0500 Subject: [PATCH 08/12] setup protocol harness --- .gitignore | 1 + challenging-interlab-growth-curve.py | 2 +- docs/reference/library.md | 4 +- .../multicolor-particle-calibration.py | 130 +- .../multicolor-particle-calibration-small.py | 3 +- .../single-particle-calibration.py | 15 +- .../singlecolor-particle-calibration.py | 15 +- .../golden_gate_assembly.py | 286 ++-- .../protocols/growth-curve/growth_curve.py | 797 +++++----- .../iGEM/challenging-interlab-growth-curve.py | 24 +- examples/protocols/iGEM/interlab-endpoint.py | 1230 +++++++-------- examples/protocols/iGEM/interlab-exp1.py | 1220 +++++++-------- examples/protocols/iGEM/interlab-exp1_MI.py | 2 +- examples/protocols/iGEM/interlab-exp2.py | 1226 +++++++-------- examples/protocols/iGEM/interlab-exp2_MI.py | 2 +- .../protocols/iGEM/interlab-exp2_from1.py | 2 +- .../protocols/iGEM/interlab-exp3_challenge.py | 1342 +++++++++-------- .../iGEM/interlab-growth-curve.ipynb | 2 +- .../protocols/iGEM/interlab-growth-curve.py | 2 +- .../protocols/iGEM/interlab-timepoint-B.py | 2 +- .../protocols/iGEM/interlab-timepoint-B_AV.py | 2 +- .../iGEM/revised-interlab-growth-curve.py | 19 +- examples/protocols/ludox/LUDOX_protocol.py | 71 +- .../ludox/artifacts/test_LUDOX_markdown.md | 115 +- .../opentrons_ludox_example.py | 55 +- .../opentrons-pcr/opentrons_pcr_example.py | 17 +- .../opentrons-toy/opentrons_toy_protocol.py | 53 +- .../pH_calibration/pH_calibration.py | 7 +- interlab-growth-curve.ipynb | 2 +- interlab-growth-curve.py | 2 +- labop/__init__.py | 11 +- labop/activity_edge_flow.py | 3 +- labop/call_behavior_execution.py | 22 +- labop/constants.py | 35 + labop/execution/__init__.py | 4 + .../execution}/behavior_dynamics.py | 4 +- labop/{ => execution}/execution_context.py | 7 +- labop/{ => execution}/execution_engine.py | 29 +- .../{ => execution}/execution_engine_utils.py | 3 +- labop/execution/harness.py | 728 +++++++++ labop/{ => execution}/lab_interface.py | 4 +- labop/lib/liquid_handling.py | 1 + labop/lib/liquid_handling.ttl | 30 +- labop/parameter_value.py | 3 + labop/primitive.py | 15 +- labop/protocol.py | 89 +- labop/protocol_execution.py | 20 +- labop/sample_mask.py | 2 +- labop/utils/harness.py | 305 ---- labop_convert/behavior_specialization.py | 5 +- .../emeraldcloud/ecl_specialization.py | 202 ++- .../markdown/markdown_specialization.py | 170 ++- .../opentrons/opentrons_specialization.py | 3 +- notebooks/Autoprotocol.ipynb | 2 +- notebooks/ExecutionRecord.ipynb | 2 +- notebooks/Opentrons.ipynb | 7 +- notebooks/UItemplate.ipynb | 2 +- notebooks/data_link.ipynb | 2 +- notebooks/labop_author_demo.ipynb | 6 +- notebooks/labop_demo.ipynb | 6 +- notebooks/markdown.ipynb | 2 +- notebooks/ph_calibration.ipynb | 2 +- revised-interlab-growth-curve.py | 2 +- test/DISABLED_execution.py | 7 +- test/test_LUDOX_protocol.py | 95 +- test/test_decision_nodes.py | 160 +- test/test_examples.py | 31 +- test/test_igem_examples.py | 89 +- test/test_inputs.py | 2 +- test/test_opentrons.py | 97 +- test/test_outputs.py | 2 +- test/test_protocol_outputs.py | 50 +- test/test_sampledata.py | 2 +- test/test_samplemap.py | 2 +- test/test_subprotocols.py | 51 +- test/testfiles/decision_node_test.nt | 10 +- uml/activity_edge.py | 8 +- uml/behavior.py | 24 +- uml/object_node.py | 3 + 79 files changed, 4850 insertions(+), 4161 deletions(-) create mode 100644 labop/execution/__init__.py rename {labop_convert => labop/execution}/behavior_dynamics.py (99%) rename labop/{ => execution}/execution_context.py (99%) rename labop/{ => execution}/execution_engine.py (97%) rename labop/{ => execution}/execution_engine_utils.py (96%) create mode 100644 labop/execution/harness.py rename labop/{ => execution}/lab_interface.py (96%) delete mode 100644 labop/utils/harness.py diff --git a/.gitignore b/.gitignore index 289276f3..7b8bdb22 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ container-ontology .coverage cov.xml site/* +**/artifacts/* diff --git a/challenging-interlab-growth-curve.py b/challenging-interlab-growth-curve.py index a68db89b..78d012de 100644 --- a/challenging-interlab-growth-curve.py +++ b/challenging-interlab-growth-curve.py @@ -9,7 +9,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert.markdown.markdown_specialization import MarkdownSpecialization doc = sbol3.Document() diff --git a/docs/reference/library.md b/docs/reference/library.md index 90f97193..e8614584 100644 --- a/docs/reference/library.md +++ b/docs/reference/library.md @@ -4,8 +4,8 @@ ::: labop.data ::: labop.lab_interface ::: labop.library -::: labop.execution_engine -::: labop.execution_engine_utils +::: labop.execution.execution_engine +::: labop.execution.execution_engine_utils ::: labop.execution_context ::: uml.uml_graphviz ::: uml.utils \ No newline at end of file diff --git a/examples/protocols/calibration/multicolor-particle-calibration/multicolor-particle-calibration.py b/examples/protocols/calibration/multicolor-particle-calibration/multicolor-particle-calibration.py index 8382c3c6..8c56329d 100644 --- a/examples/protocols/calibration/multicolor-particle-calibration/multicolor-particle-calibration.py +++ b/examples/protocols/calibration/multicolor-particle-calibration/multicolor-particle-calibration.py @@ -9,19 +9,10 @@ import sys import sbol3 -from pint import Measurement from tyto import OM import labop -from labop.utils.harness import ( - ProtocolArtifact, - ProtocolDiagram, - ProtocolExecutionDiagram, - ProtocolHarness, - ProtocolNTuples, - ProtocolSampleTrace, - ProtocolSpecialization, -) +from labop.execution.harness import ProtocolHarness, ProtocolSpecialization from labop_convert.markdown.markdown_specialization import MarkdownSpecialization NAMESPACE = "http://igem.org/engineering/" @@ -126,38 +117,14 @@ def generate_prepare_reagents_subprotocol(doc: sbol3.Document): import labop solution_subprotocol = generate_solution_subprotocol(doc) - - # Define buffers - ddh2o = sbol3.Component( - "ddH2O", "https://identifiers.org/pubchem.substance:24901740" - ) - ddh2o.name = "Water, sterile-filtered, BioReagent, suitable for cell culture" - - pbs = sbol3.Component("pbs", "https://pubchem.ncbi.nlm.nih.gov/compound/24978514") - pbs.name = "Phosphate Buffered Saline" - - # Define calibrants - silica_beads = sbol3.Component( - "silica_beads", - "https://nanocym.com/wp-content/uploads/2018/07/NanoCym-All-Datasheets-.pdf", - ) - silica_beads.name = "NanoCym 950 nm monodisperse silica nanoparticles" - silica_beads.description = "3e9 NanoCym microspheres" # where does this go? - - fluorescein = sbol3.Component( - "fluorescein", "https://pubchem.ncbi.nlm.nih.gov/substance/329753341" - ) - fluorescein.name = "Fluorescein" - - cascade_blue = sbol3.Component( - "cascade_blue", "https://pubchem.ncbi.nlm.nih.gov/substance/57269662" + from labop.constants import ( + cascade_blue, + ddh2o, + fluorescein, + pbs, + silica_beads, + sulforhodamine, ) - cascade_blue.name = "Cascade Blue" - - sulforhodamine = sbol3.Component( - "sulforhodamine", "https://pubchem.ncbi.nlm.nih.gov/compound/139216224" - ) - sulforhodamine.name = "Sulforhodamine" doc.add(ddh2o) doc.add(silica_beads) @@ -332,8 +299,9 @@ def generate_prepare_reagents_subprotocol(doc: sbol3.Document): return subprotocol -def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol): +def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol) -> labop.Protocol: import labop + from labop.constants import ddh2o, pbs prepare_reagents_subprotocol = generate_prepare_reagents_subprotocol(doc) prepare_reagents = protocol.primitive_step(prepare_reagents_subprotocol) @@ -561,6 +529,8 @@ def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol): samples=dilution_series1.output_pin("samples"), amount=sbol3.Measure(100, OM.microlitre), direction=labop.Strings.ROW_DIRECTION, + diluent=pbs, + dilution_factor=2, ) serial_dilution1.description = "For each 100.0 microliter transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously." @@ -580,6 +550,8 @@ def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol): samples=dilution_series2.output_pin("samples"), amount=sbol3.Measure(100, OM.microlitre), direction=labop.Strings.ROW_DIRECTION, + diluent=pbs, + dilution_factor=2, ) serial_dilution2.description = "For each 100.0 microliter transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously." @@ -588,6 +560,8 @@ def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol): samples=dilution_series3.output_pin("samples"), amount=sbol3.Measure(100, OM.microlitre), direction=labop.Strings.ROW_DIRECTION, + diluent=pbs, + dilution_factor=2, ) serial_dilution3.description = "For each 100.0 microliter transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously." @@ -596,6 +570,8 @@ def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol): samples=dilution_series4.output_pin("samples"), amount=sbol3.Measure(100, OM.microlitre), direction=labop.Strings.ROW_DIRECTION, + diluent=pbs, + dilution_factor=2, ) serial_dilution4.description = "For each 100.0 microliter transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously." @@ -604,6 +580,8 @@ def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol): samples=dilution_series5.output_pin("samples"), amount=sbol3.Measure(100, OM.microlitre), direction=labop.Strings.ROW_DIRECTION, + diluent=ddh2o, + dilution_factor=2, ) serial_dilution5.description = "For each 100.0 microliter transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously." @@ -612,6 +590,8 @@ def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol): samples=dilution_series6.output_pin("samples"), amount=sbol3.Measure(100, OM.microlitre), direction=labop.Strings.ROW_DIRECTION, + diluent=ddh2o, + dilution_factor=2, ) serial_dilution6.description = "For each 100.0 microliter transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously." @@ -620,6 +600,8 @@ def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol): samples=dilution_series7.output_pin("samples"), amount=sbol3.Measure(100, OM.microlitre), direction=labop.Strings.ROW_DIRECTION, + diluent=ddh2o, + dilution_factor=2, ) serial_dilution7.description = "For each 100.0 microliter transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously." @@ -628,6 +610,8 @@ def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol): samples=dilution_series8.output_pin("samples"), amount=sbol3.Measure(100, OM.microlitre), direction=labop.Strings.ROW_DIRECTION, + diluent=ddh2o, + dilution_factor=2, ) serial_dilution8.description = "For each 100.0 microliter transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously." @@ -812,12 +796,12 @@ def generate_protocol(doc: sbol3.Document, protocol: labop.Protocol): print(f"Saving protocol [{protocol_file}].") f.write(doc.write_string(sbol3.SORTED_NTRIPLES).strip()) - return protocol, doc + return protocol def compute_sample_trajectory(protocol, doc): import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop.strings import Strings from labop_convert import DefaultBehaviorSpecialization @@ -844,7 +828,7 @@ def compute_sample_trajectory(protocol, doc): def generate_markdown_specialization(protocol, doc): import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop.strings import Strings from labop_convert import MarkdownSpecialization @@ -894,7 +878,7 @@ def generate_markdown_specialization(protocol, doc): def generate_ecl_specialization(protocol, doc): import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop.strings import Strings from labop_convert import ECLSpecialization @@ -925,7 +909,7 @@ def generate_ecl_specialization(protocol, doc): def generate_autoprotocol_specialization(protocol, doc): blockPrint() import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop_convert.autoprotocol.autoprotocol_specialization import ( AutoprotocolSpecialization, ) @@ -1028,7 +1012,7 @@ def generate_autoprotocol_specialization(protocol, doc): def generate_emeraldcloud_specialization(protocol, doc, stock_solutions=None): blockPrint() import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop_convert.emeraldcloud.ecl_specialization import ECLSpecialization ecl_output = os.path.join(OUT_DIR, f"{filename}-emeraldcloud.nb") @@ -1121,34 +1105,30 @@ def enablePrint(): sys.stdout = sys.__stdout__ -harness = ProtocolHarness( - entry_point=generate_protocol, - artifacts=[ - ProtocolNTuples(), - ProtocolDiagram(), - ProtocolExecutionDiagram(), - ProtocolSampleTrace(), - ProtocolSpecialization(specialization=MarkdownSpecialization()), - ], - namespace="http://igem.org/engineering/", - protocol_name="interlab", - protocol_long_name="Multicolor fluorescence per bacterial particle calibration", - protocol_version="1.2", - protocol_description=""" -Plate readers report fluorescence values in arbitrary units that vary widely from instrument to instrument. Therefore absolute fluorescence values cannot be directly compared from one instrument to another. In order to compare fluorescence output of biological devices, it is necessary to create a standard fluorescence curve. This variant of the protocol uses two replicates of three colors of dye, plus beads. -Adapted from [https://dx.doi.org/10.17504/protocols.io.bht7j6rn](https://dx.doi.org/10.17504/protocols.io.bht7j6r) and [https://dx.doi.org/10.17504/protocols.io.6zrhf56](https://dx.doi.org/10.17504/protocols.io.6zrhf56) - """, - output_dir="".join(__file__.split(".py")[0].split("/")[-1:]), - libraries=[ - "liquid_handling", - "plate_handling", - "spectrophotometry", - "sample_arrays", - ], -) - - if __name__ == "__main__": + harness = ProtocolHarness( + entry_point=generate_protocol, + artifacts=[ + ProtocolSpecialization( + specialization=MarkdownSpecialization(filename + ".md") + ), + ], + namespace="http://igem.org/engineering/", + protocol_name="interlab", + protocol_long_name="Multicolor fluorescence per bacterial particle calibration", + protocol_version="1.2", + protocol_description=""" + Plate readers report fluorescence values in arbitrary units that vary widely from instrument to instrument. Therefore absolute fluorescence values cannot be directly compared from one instrument to another. In order to compare fluorescence output of biological devices, it is necessary to create a standard fluorescence curve. This variant of the protocol uses two replicates of three colors of dye, plus beads. + Adapted from [https://dx.doi.org/10.17504/protocols.io.bht7j6rn](https://dx.doi.org/10.17504/protocols.io.bht7j6r) and [https://dx.doi.org/10.17504/protocols.io.6zrhf56](https://dx.doi.org/10.17504/protocols.io.6zrhf56) + """, + output_dir="".join(__file__.split(".py")[0].split("/")[-1:]), + libraries=[ + "liquid_handling", + "plate_handling", + "spectrophotometry", + "sample_arrays", + ], + ) harness.run() parser = argparse.ArgumentParser() parser.add_argument( diff --git a/examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py b/examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py index 1bd71012..728a28d7 100644 --- a/examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py +++ b/examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py @@ -16,7 +16,7 @@ import labop from labop import SampleArray, SampleMask -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop.strings import Strings from labop_convert.emeraldcloud.ecl_specialization import ECLSpecialization from labop_convert.markdown.markdown_specialization import MarkdownSpecialization @@ -196,6 +196,7 @@ samples=dilution_series1.output_pin("samples"), direction=labop.Strings.COLUMN_DIRECTION, amount=sbol3.Measure(100, OM.microlitre), + diluent=pbs, ) serial_dilution1.description = "For each 100.0 microliter transfer, pipette up and down 3X to ensure the dilution is mixed homogeneously." diff --git a/examples/protocols/calibration/single-particle-calibration/single-particle-calibration.py b/examples/protocols/calibration/single-particle-calibration/single-particle-calibration.py index 5b0d760c..c698c999 100644 --- a/examples/protocols/calibration/single-particle-calibration/single-particle-calibration.py +++ b/examples/protocols/calibration/single-particle-calibration/single-particle-calibration.py @@ -373,7 +373,7 @@ def generate_protocol(): def compute_sample_trajectory(protocol, doc): import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop.strings import Strings from labop_convert import DefaultBehaviorSpecialization @@ -400,12 +400,11 @@ def compute_sample_trajectory(protocol, doc): def generate_markdown_specialization(protocol, doc): import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop.strings import Strings from labop_convert import MarkdownSpecialization if REGENERATE_ARTIFACTS: - dataset_file = f"{filename}_template" # name of xlsx md_file = filename + ".md" else: @@ -450,7 +449,7 @@ def generate_markdown_specialization(protocol, doc): def generate_ecl_specialization(protocol, doc): import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop.strings import Strings from labop_convert import ECLSpecialization @@ -481,7 +480,7 @@ def generate_ecl_specialization(protocol, doc): def generate_autoprotocol_specialization(protocol, doc): blockPrint() import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop_convert.autoprotocol.autoprotocol_specialization import ( AutoprotocolSpecialization, ) @@ -553,7 +552,9 @@ def generate_autoprotocol_specialization(protocol, doc): ) ee = ExecutionEngine( - specializations=[autoprotocol_specialization], out_dir=OUT_DIR, failsafe=False + specializations=[autoprotocol_specialization], + out_dir=OUT_DIR, + failsafe=False, ) execution = ee.execute( protocol, @@ -587,7 +588,7 @@ def generate_emeraldcloud_specialization(protocol, doc, stock_solutions=None): blockPrint() import labop import uml - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop_convert.emeraldcloud.ecl_specialization import ECLSpecialization ddh2o = doc.find(f"{NAMESPACE}ddH2O") diff --git a/examples/protocols/calibration/singlecolor-particle-calibration/singlecolor-particle-calibration.py b/examples/protocols/calibration/singlecolor-particle-calibration/singlecolor-particle-calibration.py index 04c10d17..49632138 100644 --- a/examples/protocols/calibration/singlecolor-particle-calibration/singlecolor-particle-calibration.py +++ b/examples/protocols/calibration/singlecolor-particle-calibration/singlecolor-particle-calibration.py @@ -673,7 +673,7 @@ def generate_protocol(): def compute_sample_trajectory(protocol, doc): import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop.strings import Strings from labop_convert import DefaultBehaviorSpecialization @@ -700,12 +700,11 @@ def compute_sample_trajectory(protocol, doc): def generate_markdown_specialization(protocol, doc): import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop.strings import Strings from labop_convert import MarkdownSpecialization if REGENERATE_ARTIFACTS: - dataset_file = f"{filename}_template" # name of xlsx md_file = filename + ".md" else: @@ -750,7 +749,7 @@ def generate_markdown_specialization(protocol, doc): def generate_ecl_specialization(protocol, doc): import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop.strings import Strings from labop_convert import ECLSpecialization @@ -781,7 +780,7 @@ def generate_ecl_specialization(protocol, doc): def generate_autoprotocol_specialization(protocol, doc): blockPrint() import labop - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop_convert.autoprotocol.autoprotocol_specialization import ( AutoprotocolSpecialization, ) @@ -853,7 +852,9 @@ def generate_autoprotocol_specialization(protocol, doc): ) ee = ExecutionEngine( - specializations=[autoprotocol_specialization], out_dir=OUT_DIR, failsafe=False + specializations=[autoprotocol_specialization], + out_dir=OUT_DIR, + failsafe=False, ) execution = ee.execute( protocol, @@ -887,7 +888,7 @@ def generate_emeraldcloud_specialization(protocol, doc, stock_solutions=None): blockPrint() import labop import uml - from labop.execution_engine import ExecutionEngine + from labop.execution.execution_engine import ExecutionEngine from labop_convert.emeraldcloud.ecl_specialization import ECLSpecialization ddh2o = doc.find(f"{NAMESPACE}ddH2O") diff --git a/examples/protocols/golden-gate-assembly/golden_gate_assembly.py b/examples/protocols/golden-gate-assembly/golden_gate_assembly.py index fdc636ef..a7675a1e 100644 --- a/examples/protocols/golden-gate-assembly/golden_gate_assembly.py +++ b/examples/protocols/golden-gate-assembly/golden_gate_assembly.py @@ -1,5 +1,4 @@ import os -import tempfile import sbol3 import tyto @@ -8,149 +7,148 @@ # import labop_md import uml - -############################################# -# set up the document -print("Setting up document") -doc = sbol3.Document() -sbol3.set_namespace("https://bbn.com/scratch/") - -############################################# -# Import the primitive libraries -print("Importing libraries") -labop.import_library("liquid_handling") -print("... Imported liquid handling") -labop.import_library("plate_handling") -print("... Imported plate handling") -labop.import_library("spectrophotometry") -print("... Imported spectrophotometry") -labop.import_library("sample_arrays") -print("... Imported sample arrays") - -############################################# -# Create the protocol -print("Creating protocol") -protocol = labop.Protocol("GoldenGate_assembly") -protocol.name = "Golden Gate Assembly" -protocol.description = """ -This protocol is for Golden Gate Assembly of pairs of DNA fragments into plasmids using the New England Biolabs -Golden Gate Assembly Kit (BsaI-HFv2), product ID NEB #E1601. -Protocol implements the specific case of two part assembly for the NEB-provided protocol: -https://www.neb.com/protocols/2018/10/02/golden-gate-assembly-protocol-for-using-neb-golden-gate-assembly-mix-e1601 -""" -doc.add(protocol) - -# create the materials to be provisioned -nf_h2o = sbol3.Component( - "nuclease_free_H2O", "https://identifiers.org/pubchem.compound:962" -) -nf_h2o.name = "Nuclease-free Water" -doc.add(nf_h2o) - -gg_buf = sbol3.Component("NEB_GoldenGate_Buffer", tyto.SBO.functional_entity) -gg_buf.name = "NEB T4 DNA Ligase Buffer (10X)" -gg_buf.derived_from.append( - "https://www.neb.com/products/e1601-neb-golden-gate-assembly-mix" -) -doc.add(gg_buf) - -gg_mix = sbol3.Component("NEB_GoldenGate_AssemblyMix", tyto.SBO.functional_entity) -gg_mix.name = "NEB Golden Gate Assembly Mix" -gg_mix.derived_from.append( - "https://www.neb.com/products/e1601-neb-golden-gate-assembly-mix" -) -doc.add(gg_mix) - -# add an parameters for specifying the layout of the DNA source plate and build plate -dna_sources = protocol.input_value( - "source_samples", "http://bioprotocols.org/labop#SampleCollection" -) -# TODO: add_input should be returning a usable ActivityNode! -dna_build_layout = protocol.input_value( - "build_layout", "http://bioprotocols.org/labop#SampleData" -) - -# actual steps of the protocol -# get a plate space for building -build_wells = protocol.primitive_step("DuplicateCollection", source=dna_build_layout) - -# put DNA into the selected wells following the build plan -protocol.primitive_step( - "TransferByMap", - source=dna_sources, - destination=build_wells.output_pin("samples"), - plan=dna_build_layout, -) - -# put buffer, assembly mix, and water into build wells too -protocol.primitive_step( - "Provision", - resource=gg_buf, - destination=build_wells.output_pin("samples"), - amount=sbol3.Measure(2, tyto.OM.microliter), -) -protocol.primitive_step( - "Provision", - resource=gg_mix, - destination=build_wells.output_pin("samples"), - amount=sbol3.Measure(1, tyto.OM.microliter), -) -protocol.primitive_step( - "Provision", - resource=nf_h2o, - destination=build_wells.output_pin("samples"), - amount=sbol3.Measure(15, tyto.OM.microliter), +from labop.execution.harness import ProtocolHarness, ProtocolSpecialization +from labop.strings import Strings +from labop_convert.markdown.markdown_specialization import ( + MarkdownSpecialization, ) -# seal and spin to mix -protocol.primitive_step( - "Seal", location=build_wells.output_pin("samples") -) # TODO: add type -protocol.primitive_step( - "Spin", - acceleration=sbol3.Measure( - 300, "http://bioprotocols.org/temporary/unit/g" - ), # TODO: replace with OM-2 unit on resolution of https://github.com/HajoRijgersberg/OM/issues/54 - duration=sbol3.Measure(3, tyto.OM.minute), -) -protocol.primitive_step("Unseal", location=build_wells.output_pin("samples")) - -# incubation steps -protocol.primitive_step( - "Incubate", - location=build_wells.output_pin("samples"), - duration=sbol3.Measure(60, tyto.OM.minute), - temperature=sbol3.Measure(37, tyto.OM.get_uri_by_term("degree Celsius")), -) # TODO: replace after resolution of https://github.com/SynBioDex/tyto/issues/29 -protocol.primitive_step( - "Incubate", - location=build_wells.output_pin("samples"), - duration=sbol3.Measure(5, tyto.OM.minute), - temperature=sbol3.Measure(60, tyto.OM.get_uri_by_term("degree Celsius")), -) # TODO: replace after resolution of https://github.com/SynBioDex/tyto/issues/29 - - -output = protocol.designate_output( - "constructs", - "http://bioprotocols.org/labop#SampleCollection", - build_wells.output_pin("samples"), -) -protocol.order( - protocol.get_last_step(), output -) # don't return until all else is complete - - -######################################## -# Validate and write the document -print("Validating and writing protocol") -v = doc.validate() -assert len(v) == 0, "".join(f"\n {e}" for e in v) - -temp_name = os.path.join(tempfile.gettempdir(), "golden_gate_assembly.nt") -doc.write(temp_name, sbol3.SORTED_NTRIPLES) -print(f"Wrote file as {temp_name}") -# render and view the dot -dot = protocol.to_dot() -dot.render(f"{protocol.name}.gv") -dot.view() +def generate_protocol( + doc: sbol3.Document, protocol: labop.Protocol +) -> labop.Protocol: + # create the materials to be provisioned + nf_h2o = sbol3.Component( + "nuclease_free_H2O", "https://identifiers.org/pubchem.compound:962" + ) + nf_h2o.name = "Nuclease-free Water" + doc.add(nf_h2o) + + gg_buf = sbol3.Component( + "NEB_GoldenGate_Buffer", tyto.SBO.functional_entity + ) + gg_buf.name = "NEB T4 DNA Ligase Buffer (10X)" + gg_buf.derived_from.append( + "https://www.neb.com/products/e1601-neb-golden-gate-assembly-mix" + ) + doc.add(gg_buf) + + gg_mix = sbol3.Component( + "NEB_GoldenGate_AssemblyMix", tyto.SBO.functional_entity + ) + gg_mix.name = "NEB Golden Gate Assembly Mix" + gg_mix.derived_from.append( + "https://www.neb.com/products/e1601-neb-golden-gate-assembly-mix" + ) + doc.add(gg_mix) + + # add an parameters for specifying the layout of the DNA source plate and build plate + dna_sources = protocol.input_value( + "source_samples", "http://bioprotocols.org/labop#SampleCollection" + ) + # TODO: add_input should be returning a usable ActivityNode! + dna_build_layout = protocol.input_value( + "build_layout", "http://bioprotocols.org/labop#SampleData" + ) + + # actual steps of the protocol + # get a plate space for building + build_wells = protocol.primitive_step( + "DuplicateCollection", source=dna_build_layout + ) + + # put DNA into the selected wells following the build plan + protocol.primitive_step( + "TransferByMap", + source=dna_sources, + destination=build_wells.output_pin("samples"), + plan=dna_build_layout, + ) + + # put buffer, assembly mix, and water into build wells too + protocol.primitive_step( + "Provision", + resource=gg_buf, + destination=build_wells.output_pin("samples"), + amount=sbol3.Measure(2, tyto.OM.microliter), + ) + protocol.primitive_step( + "Provision", + resource=gg_mix, + destination=build_wells.output_pin("samples"), + amount=sbol3.Measure(1, tyto.OM.microliter), + ) + protocol.primitive_step( + "Provision", + resource=nf_h2o, + destination=build_wells.output_pin("samples"), + amount=sbol3.Measure(15, tyto.OM.microliter), + ) + + # seal and spin to mix + protocol.primitive_step( + "Seal", location=build_wells.output_pin("samples") + ) # TODO: add type + protocol.primitive_step( + "Spin", + acceleration=sbol3.Measure( + 300, "http://bioprotocols.org/temporary/unit/g" + ), # TODO: replace with OM-2 unit on resolution of https://github.com/HajoRijgersberg/OM/issues/54 + duration=sbol3.Measure(3, tyto.OM.minute), + ) + protocol.primitive_step( + "Unseal", location=build_wells.output_pin("samples") + ) + + # incubation steps + protocol.primitive_step( + "Incubate", + location=build_wells.output_pin("samples"), + duration=sbol3.Measure(60, tyto.OM.minute), + temperature=sbol3.Measure( + 37, tyto.OM.get_uri_by_term("degree Celsius") + ), + ) # TODO: replace after resolution of https://github.com/SynBioDex/tyto/issues/29 + protocol.primitive_step( + "Incubate", + location=build_wells.output_pin("samples"), + duration=sbol3.Measure(5, tyto.OM.minute), + temperature=sbol3.Measure( + 60, tyto.OM.get_uri_by_term("degree Celsius") + ), + ) # TODO: replace after resolution of https://github.com/SynBioDex/tyto/issues/29 + + output = protocol.designate_output( + "constructs", + "http://bioprotocols.org/labop#SampleCollection", + build_wells.output_pin("samples"), + ) + protocol.order( + protocol.get_last_step(), output + ) # don't return until all else is complete + return protocol + + +if __name__ == "__main__": + harness = ProtocolHarness( + entry_point=generate_protocol, + artifacts=[ + ProtocolSpecialization( + specialization=MarkdownSpecialization( + "test_golden_gate_markdown.md", + sample_format=Strings.XARRAY, + ) + ) + ], + namespace="https://labop.io/examples/protocols/golden-gate-assembly/", + protocol_name="GoldenGate_assembly", + protocol_long_name="Golden Gate Assembly", + protocol_version="1.0", + protocol_description=""" + This protocol is for Golden Gate Assembly of pairs of DNA fragments into plasmids using the New England Biolabs + Golden Gate Assembly Kit (BsaI-HFv2), product ID NEB #E1601. + Protocol implements the specific case of two part assembly for the NEB-provided protocol: + https://www.neb.com/protocols/2018/10/02/golden-gate-assembly-protocol-for-using-neb-golden-gate-assembly-mix-e1601 + """, + ) + harness.run(base_dir=os.path.dirname(__file__)) diff --git a/examples/protocols/growth-curve/growth_curve.py b/examples/protocols/growth-curve/growth_curve.py index 40f2e562..9d2b0afe 100644 --- a/examples/protocols/growth-curve/growth_curve.py +++ b/examples/protocols/growth-curve/growth_curve.py @@ -2,413 +2,420 @@ import tyto import labop +from labop.constants import rpm +from labop.execution.harness import ProtocolHarness, ProtocolSpecialization +from labop.strings import Strings +from labop_convert.markdown.markdown_specialization import MarkdownSpecialization -############################################# -# Helper functions - -# set up the document -doc = sbol3.Document() -sbol3.set_namespace("https://sd2e.org/LabOP/") - -############################################# -# Import the primitive libraries -print("Importing libraries") -labop.import_library("liquid_handling") -labop.import_library("plate_handling") -labop.import_library("spectrophotometry") - -# this should really get pulled into a common library somewhere -rpm = sbol3.UnitDivision( - "rpm", - name="rpm", - symbol="rpm", - label="revolutions per minute", - numerator=tyto.OM.revolution, - denominator=tyto.OM.minute, -) -doc.add(rpm) - - -############################################# -# Create the protocols - -print("Constructing measurement sub-protocols") -# This will be used 10 times generating "OD_Plate_1" .. "OD_Plate_9" - -split_and_measure = labop.Protocol( - "SplitAndMeasure", name="Split samples, dilute, and measure" -) -split_and_measure.description = """ -Subprotocol to split a portion of each sample in a plate into another plate, diluting -with PBS, then measure OD and fluorescence from that other plate -""" -doc.add(split_and_measure) - -# plate for split-and-measure subroutine -od_plate = labop.Container( - name="OD Plate", type=tyto.NCIT.Microplate, max_coordinate="H12" -) -split_and_measure.locations = {od_plate} - -# Inputs: collection of samples, pbs_source -samples = split_and_measure.add_input( - name="samples", - description="Samples to measure", - type="http://bioprotocols.org/labop#LocatedSamples", -) -pbs_source = split_and_measure.add_input( - name="pbs", - description="Source for PBS", - type="http://bioprotocols.org/labop#LocatedSamples", -) - -# subprotocol steps -s_p = split_and_measure.execute_primitive( - "Dispense", - source=pbs_source, - destination=od_plate, - amount=sbol3.Measure(90, tyto.OM.microliter), -) -split_and_measure.add_flow( - split_and_measure.initial(), s_p -) # dispensing OD can be a first action -s_u = split_and_measure.execute_primitive("Unseal", location=samples) -split_and_measure.add_flow( - split_and_measure.initial(), s_u -) # unsealing the growth plate can be a first action -s_t = split_and_measure.execute_primitive( - "TransferInto", - source=samples, - destination=s_p.output_pin("samples"), - amount=sbol3.Measure(10, tyto.OM.microliter), - mixCycles=sbol3.Measure(10, tyto.OM.number), -) -split_and_measure.add_flow( - s_u, s_t -) # transfer can't happen until growth plate is unsealed - -# add the measurements, in parallel -ready_to_measure = labop.Fork() -split_and_measure.activities.append(ready_to_measure) -split_and_measure.add_flow(s_t.output_pin("samples"), ready_to_measure) -measurement_complete = labop.Join() -split_and_measure.activities.append(measurement_complete) - -s_a = split_and_measure.execute_primitive( - "MeasureAbsorbance", - samples=ready_to_measure, - wavelength=sbol3.Measure(600, tyto.OM.nanometer), - numFlashes=sbol3.Measure(25, tyto.OM.number), -) -v_a = split_and_measure.add_output("absorbance", s_a.output_pin("measurements")) -split_and_measure.add_flow(v_a, measurement_complete) - -gains = {0.1, 0.2, 0.16} -for g in gains: - s_f = split_and_measure.execute_primitive( - "MeasureFluorescence", + +def generate_protocol(doc, protocol: labop.Protocol) -> labop.Protocol: + doc.add(rpm) + ############################################# + # Create the protocols + + print("Constructing measurement sub-protocols") + # This will be used 10 times generating "OD_Plate_1" .. "OD_Plate_9" + + split_and_measure = labop.Protocol( + "SplitAndMeasure", name="Split samples, dilute, and measure" + ) + split_and_measure.description = """ + Subprotocol to split a portion of each sample in a plate into another plate, diluting + with PBS, then measure OD and fluorescence from that other plate + """ + doc.add(split_and_measure) + + # plate for split-and-measure subroutine + od_plate = labop.Container( + name="OD Plate", type=tyto.NCIT.Microplate, max_coordinate="H12" + ) + split_and_measure.locations = {od_plate} + + # Inputs: collection of samples, pbs_source + samples = split_and_measure.add_input( + name="samples", + description="Samples to measure", + type="http://bioprotocols.org/labop#LocatedSamples", + ) + pbs_source = split_and_measure.add_input( + name="pbs", + description="Source for PBS", + type="http://bioprotocols.org/labop#LocatedSamples", + ) + + # subprotocol steps + s_p = split_and_measure.execute_primitive( + "Dispense", + source=pbs_source, + destination=od_plate, + amount=sbol3.Measure(90, tyto.OM.microliter), + ) + split_and_measure.add_flow( + split_and_measure.initial(), s_p + ) # dispensing OD can be a first action + s_u = split_and_measure.execute_primitive("Unseal", location=samples) + split_and_measure.add_flow( + split_and_measure.initial(), s_u + ) # unsealing the growth plate can be a first action + s_t = split_and_measure.execute_primitive( + "TransferInto", + source=samples, + destination=s_p.output_pin("samples"), + amount=sbol3.Measure(10, tyto.OM.microliter), + mixCycles=sbol3.Measure(10, tyto.OM.number), + ) + split_and_measure.add_flow( + s_u, s_t + ) # transfer can't happen until growth plate is unsealed + + # add the measurements, in parallel + ready_to_measure = labop.Fork() + split_and_measure.activities.append(ready_to_measure) + split_and_measure.add_flow(s_t.output_pin("samples"), ready_to_measure) + measurement_complete = labop.Join() + split_and_measure.activities.append(measurement_complete) + + s_a = split_and_measure.execute_primitive( + "MeasureAbsorbance", samples=ready_to_measure, - excitationWavelength=sbol3.Measure(488, tyto.OM.nanometer), - emissionBandpassWavelength=sbol3.Measure(530, tyto.OM.nanometer), + wavelength=sbol3.Measure(600, tyto.OM.nanometer), numFlashes=sbol3.Measure(25, tyto.OM.number), - gain=sbol3.Measure(g, tyto.OM.number), ) - v_f = split_and_measure.add_output( - "fluorescence_" + str(g), s_f.output_pin("measurements") + v_a = split_and_measure.add_output("absorbance", s_a.output_pin("measurements")) + split_and_measure.add_flow(v_a, measurement_complete) + + gains = {0.1, 0.2, 0.16} + for g in gains: + s_f = split_and_measure.execute_primitive( + "MeasureFluorescence", + samples=ready_to_measure, + excitationWavelength=sbol3.Measure(488, tyto.OM.nanometer), + emissionBandpassWavelength=sbol3.Measure(530, tyto.OM.nanometer), + numFlashes=sbol3.Measure(25, tyto.OM.number), + gain=sbol3.Measure(g, tyto.OM.number), + ) + v_f = split_and_measure.add_output( + "fluorescence_" + str(g), s_f.output_pin("measurements") + ) + split_and_measure.add_flow(v_f, measurement_complete) + + s_c = split_and_measure.execute_primitive("Cover", location=od_plate) + split_and_measure.add_flow(measurement_complete, s_c) + split_and_measure.add_flow(s_c, split_and_measure.final()) + + s_s = split_and_measure.execute_primitive( + "Seal", location=samples, type="http://autoprotocol.org/lids/breathable" + ) # need to turn this into a proper ontology + split_and_measure.add_flow(measurement_complete, s_s) + split_and_measure.add_flow(s_s, split_and_measure.final()) + + print("Measurement sub-protocol construction complete") + + overnight_od_measure = labop.Protocol( + "OvernightODMeasure", name="Split samples and measure, without dilution" ) - split_and_measure.add_flow(v_f, measurement_complete) - -s_c = split_and_measure.execute_primitive("Cover", location=od_plate) -split_and_measure.add_flow(measurement_complete, s_c) -split_and_measure.add_flow(s_c, split_and_measure.final()) - -s_s = split_and_measure.execute_primitive( - "Seal", location=samples, type="http://autoprotocol.org/lids/breathable" -) # need to turn this into a proper ontology -split_and_measure.add_flow(measurement_complete, s_s) -split_and_measure.add_flow(s_s, split_and_measure.final()) - -print("Measurement sub-protocol construction complete") - - -overnight_od_measure = labop.Protocol( - "OvernightODMeasure", name="Split samples and measure, without dilution" -) -overnight_od_measure.description = """ -Subprotocol to split a portion of each sample in an unsealed plate into another plate, then measure OD and fluorescence from that other plate -""" -doc.add(overnight_od_measure) - -# plate for split-and-measure subroutine -od_plate = labop.Container( - name="OD Plate", type=tyto.NCIT.Microplate, max_coordinate="H12" -) -overnight_od_measure.locations = {od_plate} - -# Input: collection of samples -samples = overnight_od_measure.add_input( - name="samples", - description="Samples to measure", - type="http://bioprotocols.org/labop#LocatedSamples", -) - -# subprotocol steps -s_t = overnight_od_measure.execute_primitive( - "Transfer", - source=samples, - destination=od_plate, - amount=sbol3.Measure(200, tyto.OM.microliter), -) -overnight_od_measure.add_flow(overnight_od_measure.initial(), s_t) # first action - -# add the measurements, in parallel -ready_to_measure = labop.Fork() -overnight_od_measure.activities.append(ready_to_measure) -overnight_od_measure.add_flow(s_t.output_pin("samples"), ready_to_measure) -measurement_complete = labop.Join() -overnight_od_measure.activities.append(measurement_complete) - -s_a = overnight_od_measure.execute_primitive( - "MeasureAbsorbance", - samples=ready_to_measure, - wavelength=sbol3.Measure(600, tyto.OM.nanometer), - numFlashes=sbol3.Measure(25, tyto.OM.number), -) -v_a = overnight_od_measure.add_output("absorbance", s_a.output_pin("measurements")) -overnight_od_measure.add_flow(v_a, measurement_complete) - -gains = {0.1, 0.2, 0.16} -for g in gains: - s_f = overnight_od_measure.execute_primitive( - "MeasureFluorescence", + overnight_od_measure.description = """ + Subprotocol to split a portion of each sample in an unsealed plate into another plate, then measure OD and fluorescence from that other plate + """ + doc.add(overnight_od_measure) + + # plate for split-and-measure subroutine + od_plate = labop.Container( + name="OD Plate", type=tyto.NCIT.Microplate, max_coordinate="H12" + ) + overnight_od_measure.locations = {od_plate} + + # Input: collection of samples + samples = overnight_od_measure.add_input( + name="samples", + description="Samples to measure", + type="http://bioprotocols.org/labop#LocatedSamples", + ) + + # subprotocol steps + s_t = overnight_od_measure.execute_primitive( + "Transfer", + source=samples, + destination=od_plate, + amount=sbol3.Measure(200, tyto.OM.microliter), + ) + overnight_od_measure.add_flow(overnight_od_measure.initial(), s_t) # first action + + # add the measurements, in parallel + ready_to_measure = labop.Fork() + overnight_od_measure.activities.append(ready_to_measure) + overnight_od_measure.add_flow(s_t.output_pin("samples"), ready_to_measure) + measurement_complete = labop.Join() + overnight_od_measure.activities.append(measurement_complete) + + s_a = overnight_od_measure.execute_primitive( + "MeasureAbsorbance", samples=ready_to_measure, - excitationWavelength=sbol3.Measure(488, tyto.OM.nanometer), - emissionBandpassWavelength=sbol3.Measure(530, tyto.OM.nanometer), + wavelength=sbol3.Measure(600, tyto.OM.nanometer), numFlashes=sbol3.Measure(25, tyto.OM.number), - gain=sbol3.Measure(g, tyto.OM.number), ) - v_f = overnight_od_measure.add_output( - "fluorescence_" + str(g), s_f.output_pin("measurements") + v_a = overnight_od_measure.add_output("absorbance", s_a.output_pin("measurements")) + overnight_od_measure.add_flow(v_a, measurement_complete) + + gains = {0.1, 0.2, 0.16} + for g in gains: + s_f = overnight_od_measure.execute_primitive( + "MeasureFluorescence", + samples=ready_to_measure, + excitationWavelength=sbol3.Measure(488, tyto.OM.nanometer), + emissionBandpassWavelength=sbol3.Measure(530, tyto.OM.nanometer), + numFlashes=sbol3.Measure(25, tyto.OM.number), + gain=sbol3.Measure(g, tyto.OM.number), + ) + v_f = overnight_od_measure.add_output( + "fluorescence_" + str(g), s_f.output_pin("measurements") + ) + overnight_od_measure.add_flow(v_f, measurement_complete) + + s_c = overnight_od_measure.execute_primitive("Cover", location=od_plate) + overnight_od_measure.add_flow(measurement_complete, s_c) + overnight_od_measure.add_flow(s_c, overnight_od_measure.final()) + + overnight_od_measure.add_flow(measurement_complete, overnight_od_measure.final()) + + print("Overnight measurement sub-protocol construction complete") + ############################################# + # Now the full protocol + + print("Making protocol") + + activity = labop.Protocol("GrowthCurve", name="SD2 Yeast growth curve protocol") + activity.description = """ + Protocol from SD2 Yeast States working group for studying growth curves: + Grow up cells and read with plate reader at n-hour intervals + """ + doc.add(activity) + + # Create the materials to be provisioned + PBS = sbol3.Component("PBS", "https://identifiers.org/pubchem.compound:24978514") + PBS.name = ( + "Phosphate-Buffered Saline" # I'd like to get this name from PubChem with tyto + ) + doc.add(PBS) + # need to retrieve and convert this one + SC_media = sbol3.Component("SC_Media", "TBD", name="Synthetic Complete Media") + doc.add(SC_media) + SC_plus_dox = sbol3.Component( + "SC_Media_plus_dox", + "TBD", + name="Synthetic Complete Media plus 40nM Doxycycline", + ) + doc.add(SC_plus_dox) + activity.material += {PBS, SC_media, SC_plus_dox} + + ## create the containers + # provisioning sources + pbs_source = labop.Container(name="PBS Source", type=tyto.NCIT.Bottle) + sc_source = labop.Container( + name="SC Media + 40nM Doxycycline Source", type=tyto.NCIT.Bottle + ) + om_source = labop.Container(name="Overnight SC Media Source", type=tyto.NCIT.Bottle) + # plates for the general protocol + overnight_plate = labop.Container( + name="Overnight Growth Plate", + type=tyto.NCIT.Microplate, + max_coordinate="H12", + ) + overnight_od_plate = labop.Container( + name="Overnight Growth Plate", + type=tyto.NCIT.Microplate, + max_coordinate="H12", ) - overnight_od_measure.add_flow(v_f, measurement_complete) - -s_c = overnight_od_measure.execute_primitive("Cover", location=od_plate) -overnight_od_measure.add_flow(measurement_complete, s_c) -overnight_od_measure.add_flow(s_c, overnight_od_measure.final()) - -overnight_od_measure.add_flow(measurement_complete, overnight_od_measure.final()) - -print("Overnight measurement sub-protocol construction complete") -############################################# -# Now the full protocol - -print("Making protocol") - -activity = labop.Protocol("GrowthCurve", name="SD2 Yeast growth curve protocol") -activity.description = """ -Protocol from SD2 Yeast States working group for studying growth curves: -Grow up cells and read with plate reader at n-hour intervals -""" -doc.add(activity) - -# Create the materials to be provisioned -PBS = sbol3.Component("PBS", "https://identifiers.org/pubchem.compound:24978514") -PBS.name = ( - "Phosphate-Buffered Saline" # I'd like to get this name from PubChem with tyto -) -doc.add(PBS) -# need to retrieve and convert this one -SC_media = sbol3.Component("SC_Media", "TBD", name="Synthetic Complete Media") -doc.add(SC_media) -SC_plus_dox = sbol3.Component( - "SC_Media_plus_dox", - "TBD", - name="Synthetic Complete Media plus 40nM Doxycycline", -) -doc.add(SC_plus_dox) -activity.material += {PBS, SC_media, SC_plus_dox} - -## create the containers -# provisioning sources -pbs_source = labop.Container(name="PBS Source", type=tyto.NCIT.Bottle) -sc_source = labop.Container( - name="SC Media + 40nM Doxycycline Source", type=tyto.NCIT.Bottle -) -om_source = labop.Container(name="Overnight SC Media Source", type=tyto.NCIT.Bottle) -# plates for the general protocol -overnight_plate = labop.Container( - name="Overnight Growth Plate", - type=tyto.NCIT.Microplate, - max_coordinate="H12", -) -overnight_od_plate = labop.Container( - name="Overnight Growth Plate", - type=tyto.NCIT.Microplate, - max_coordinate="H12", -) -growth_plate = labop.Container( - name="Growth Curve Plate", type=tyto.NCIT.Microplate, max_coordinate="H12" -) -activity.locations = { - pbs_source, - sc_source, - om_source, - overnight_plate, - growth_plate, -} - -# One input: a microplate full of strains -# TODO: change this to allow alternative places -strain_plate = activity.add_input( - name="strain_plate", - description="Plate of strains to grow", - type="http://bioprotocols.org/labop#LocatedSamples", -) -# input_plate = labop.Container(name='497943_4_UWBF_to_stratoes', type=tyto.NCIT.Microplate, max_coordinate='H12') - -print("Constructing protocol steps") - -# set up the sources -p_pbs = activity.execute_primitive( - "Provision", - resource=PBS, - destination=pbs_source, - amount=sbol3.Measure(117760, tyto.OM.microliter), -) -activity.add_flow(activity.initial(), p_pbs) # start with provisioning -p_om = activity.execute_primitive( - "Provision", - resource=SC_media, - destination=om_source, - amount=sbol3.Measure(98, tyto.OM.milliliter), -) -activity.add_flow(activity.initial(), p_om) # start with provisioning -p_scm = activity.execute_primitive( - "Provision", - resource=SC_plus_dox, - destination=sc_source, - amount=sbol3.Measure(117200, tyto.OM.microliter), -) -activity.add_flow(activity.initial(), p_scm) # start with provisioning - -# prep the overnight culture, then seal away the source plate again -s_d = activity.execute_primitive( - "Dispense", - source=p_om.output_pin("samples"), - destination=overnight_plate, - amount=sbol3.Measure(500, tyto.OM.microliter), -) -s_u = activity.execute_primitive("Unseal", location=strain_plate) -s_t = activity.execute_primitive( - "TransferInto", - source=strain_plate, - destination=s_d.output_pin("samples"), - amount=sbol3.Measure(5, tyto.OM.microliter), - mixCycles=sbol3.Measure(10, tyto.OM.number), -) -s_s = activity.execute_primitive( - "Seal", - location=strain_plate, - type="http://autoprotocol.org/lids/breathable", -) # need to turn this into a proper ontology -activity.add_flow(s_u, s_t) # transfer can't happen until strain plate is unsealed ... -activity.add_flow(s_t, s_s) # ... and must complete before we re-seal it - -# run the overnight culture -overnight_samples = s_t.output_pin("samples") -s_s = activity.execute_primitive( - "Seal", - location=overnight_samples, - type="http://autoprotocol.org/lids/breathable", -) # need to turn this into a proper ontology -s_i = activity.execute_primitive( - "Incubate", - location=overnight_samples, - temperature=sbol3.Measure(30, tyto.OM.get_uri_by_term("degree Celsius")), - duration=sbol3.Measure(16, tyto.OM.hour), - shakingFrequency=sbol3.Measure(350, rpm.identity), -) -activity.add_flow(s_t, s_s) # sealing after transfer -activity.add_flow(s_s, s_i) # incubation after sealing - -# Check the OD after running overnight; note that this is NOT the same measurement process as for the during-growth measurements -s_u = activity.execute_primitive( - "Unseal", location=overnight_samples -) # added because using the subprotocol leaves a sealed plate -activity.add_flow(s_i, s_u) # growth plate after measurement -s_m = activity.execute_subprotocol(overnight_od_measure, samples=overnight_samples) -activity.add_flow(s_u, s_m) # measurement after incubation and unsealing - -# Set up the growth plate -s_d = activity.execute_primitive( - "Dispense", - source=p_scm.output_pin("samples"), - destination=growth_plate, - amount=sbol3.Measure(700, tyto.OM.microliter), -) -s_t = activity.execute_primitive( - doc.find("TransferInto"), - source=overnight_samples, - destination=s_d.output_pin("samples"), - amount=sbol3.Measure(2, tyto.OM.microliter), - mixCycles=sbol3.Measure(10, tyto.OM.number), -) -s_s = activity.execute_primitive( - "Seal", - location=overnight_samples, - type="http://autoprotocol.org/lids/breathable", -) # need to turn this into a proper ontology -activity.add_flow( - s_u, s_t -) # transfer can't happen until overnight plate is unsealed ... -activity.add_flow(s_t, s_s) # ... and must complete before we re-seal it -activity.add_flow(s_m, s_s) # ... as must its measurement - -# run the step-by-step culture -growth_samples = s_t.output_pin("samples") -last_round = None -# sample_hours = [1, 3, 6, 9, 12, 15, 18, 21, 24] # Original: modified to be friendly to human execution -sample_hours = [1, 3, 6, 9, 18, 21, 24] -for i in range(0, len(sample_hours)): - incubation_hours = sample_hours[i] - (sample_hours[i - 1] if i > 0 else 0) + growth_plate = labop.Container( + name="Growth Curve Plate", + type=tyto.NCIT.Microplate, + max_coordinate="H12", + ) + activity.locations = { + pbs_source, + sc_source, + om_source, + overnight_plate, + growth_plate, + } + + # One input: a microplate full of strains + # TODO: change this to allow alternative places + strain_plate = activity.add_input( + name="strain_plate", + description="Plate of strains to grow", + type="http://bioprotocols.org/labop#LocatedSamples", + ) + # input_plate = labop.Container(name='497943_4_UWBF_to_stratoes', type=tyto.NCIT.Microplate, max_coordinate='H12') + + print("Constructing protocol steps") + + # set up the sources + p_pbs = activity.execute_primitive( + "Provision", + resource=PBS, + destination=pbs_source, + amount=sbol3.Measure(117760, tyto.OM.microliter), + ) + activity.add_flow(activity.initial(), p_pbs) # start with provisioning + p_om = activity.execute_primitive( + "Provision", + resource=SC_media, + destination=om_source, + amount=sbol3.Measure(98, tyto.OM.milliliter), + ) + activity.add_flow(activity.initial(), p_om) # start with provisioning + p_scm = activity.execute_primitive( + "Provision", + resource=SC_plus_dox, + destination=sc_source, + amount=sbol3.Measure(117200, tyto.OM.microliter), + ) + activity.add_flow(activity.initial(), p_scm) # start with provisioning + + # prep the overnight culture, then seal away the source plate again + s_d = activity.execute_primitive( + "Dispense", + source=p_om.output_pin("samples"), + destination=overnight_plate, + amount=sbol3.Measure(500, tyto.OM.microliter), + ) + s_u = activity.execute_primitive("Unseal", location=strain_plate) + s_t = activity.execute_primitive( + "TransferInto", + source=strain_plate, + destination=s_d.output_pin("samples"), + amount=sbol3.Measure(5, tyto.OM.microliter), + mixCycles=sbol3.Measure(10, tyto.OM.number), + ) + s_s = activity.execute_primitive( + "Seal", + location=strain_plate, + type="http://autoprotocol.org/lids/breathable", + ) # need to turn this into a proper ontology + activity.add_flow( + s_u, s_t + ) # transfer can't happen until strain plate is unsealed ... + activity.add_flow(s_t, s_s) # ... and must complete before we re-seal it + + # run the overnight culture + overnight_samples = s_t.output_pin("samples") + s_s = activity.execute_primitive( + "Seal", + location=overnight_samples, + type="http://autoprotocol.org/lids/breathable", + ) # need to turn this into a proper ontology s_i = activity.execute_primitive( "Incubate", - location=growth_samples, + location=overnight_samples, temperature=sbol3.Measure(30, tyto.OM.get_uri_by_term("degree Celsius")), - duration=sbol3.Measure(incubation_hours, tyto.OM.hour), + duration=sbol3.Measure(16, tyto.OM.hour), shakingFrequency=sbol3.Measure(350, rpm.identity), ) - s_m = activity.execute_subprotocol( - split_and_measure, - samples=growth_samples, - pbs=p_pbs.output_pin("samples"), + activity.add_flow(s_t, s_s) # sealing after transfer + activity.add_flow(s_s, s_i) # incubation after sealing + + # Check the OD after running overnight; note that this is NOT the same measurement process as for the during-growth measurements + s_u = activity.execute_primitive( + "Unseal", location=overnight_samples + ) # added because using the subprotocol leaves a sealed plate + activity.add_flow(s_i, s_u) # growth plate after measurement + s_m = activity.execute_subprotocol(overnight_od_measure, samples=overnight_samples) + activity.add_flow(s_u, s_m) # measurement after incubation and unsealing + + # Set up the growth plate + s_d = activity.execute_primitive( + "Dispense", + source=p_scm.output_pin("samples"), + destination=growth_plate, + amount=sbol3.Measure(700, tyto.OM.microliter), ) - if last_round: - activity.add_flow(last_round, s_i) # measurement after incubation - activity.add_flow(s_i, s_m) # measurement after incubation - last_round = s_m - -activity.add_flow(last_round, activity.final()) - -print("Protocol construction complete") - - -###################### -# Invocation of protocol on a plate:; - -# plate for invoking the protocol -# input_plate = labop.Container(name='497943_4_UWBF_to_stratoes', type=tyto.NCIT.Microplate, max_coordinate='H12') - - -print("Validating document") -for e in doc.validate().errors: - print(e) -for w in doc.validate().warnings: - print(w) - -print("Writing document") - -doc.write("test/testfiles/growth_curve.json", "json-ld") -doc.write("test/testfiles/growth_curve.ttl", "turtle") - -print("Complete") + s_t = activity.execute_primitive( + doc.find("TransferInto"), + source=overnight_samples, + destination=s_d.output_pin("samples"), + amount=sbol3.Measure(2, tyto.OM.microliter), + mixCycles=sbol3.Measure(10, tyto.OM.number), + ) + s_s = activity.execute_primitive( + "Seal", + location=overnight_samples, + type="http://autoprotocol.org/lids/breathable", + ) # need to turn this into a proper ontology + activity.add_flow( + s_u, s_t + ) # transfer can't happen until overnight plate is unsealed ... + activity.add_flow(s_t, s_s) # ... and must complete before we re-seal it + activity.add_flow(s_m, s_s) # ... as must its measurement + + # run the step-by-step culture + growth_samples = s_t.output_pin("samples") + last_round = None + # sample_hours = [1, 3, 6, 9, 12, 15, 18, 21, 24] # Original: modified to be friendly to human execution + sample_hours = [1, 3, 6, 9, 18, 21, 24] + for i in range(0, len(sample_hours)): + incubation_hours = sample_hours[i] - (sample_hours[i - 1] if i > 0 else 0) + s_i = activity.execute_primitive( + "Incubate", + location=growth_samples, + temperature=sbol3.Measure(30, tyto.OM.get_uri_by_term("degree Celsius")), + duration=sbol3.Measure(incubation_hours, tyto.OM.hour), + shakingFrequency=sbol3.Measure(350, rpm.identity), + ) + s_m = activity.execute_subprotocol( + split_and_measure, + samples=growth_samples, + pbs=p_pbs.output_pin("samples"), + ) + if last_round: + activity.add_flow(last_round, s_i) # measurement after incubation + activity.add_flow(s_i, s_m) # measurement after incubation + last_round = s_m + + activity.add_flow(last_round, activity.final()) + + print("Protocol construction complete") + + ###################### + # Invocation of protocol on a plate:; + + # plate for invoking the protocol + # input_plate = labop.Container(name='497943_4_UWBF_to_stratoes', type=tyto.NCIT.Microplate, max_coordinate='H12') + + print("Validating document") + for e in doc.validate().errors: + print(e) + for w in doc.validate().warnings: + print(w) + + print("Writing document") + + doc.write("test/testfiles/growth_curve.json", "json-ld") + doc.write("test/testfiles/growth_curve.ttl", "turtle") + + print("Complete") + + +if __name__ == "__main__": + harness = ProtocolHarness( + entry_point=generate_protocol, + artifacts=[ + ProtocolSpecialization( + specialization=MarkdownSpecialization( + "test_golden_gate_markdown.md", + sample_format=Strings.XARRAY, + ) + ) + ], + namespace="https://labop.io/examples/protocols/golden-gate-assembly/", + protocol_name="GoldenGate_assembly", + protocol_long_name="Golden Gate Assembly", + protocol_version="1.0", + protocol_description=""" + This protocol is for Golden Gate Assembly of pairs of DNA fragments into plasmids using the New England Biolabs + Golden Gate Assembly Kit (BsaI-HFv2), product ID NEB #E1601. + Protocol implements the specific case of two part assembly for the NEB-provided protocol: + https://www.neb.com/protocols/2018/10/02/golden-gate-assembly-protocol-for-using-neb-golden-gate-assembly-mix-e1601 + """, + ) + harness.run() diff --git a/examples/protocols/iGEM/challenging-interlab-growth-curve.py b/examples/protocols/iGEM/challenging-interlab-growth-curve.py index a68db89b..2649e520 100644 --- a/examples/protocols/iGEM/challenging-interlab-growth-curve.py +++ b/examples/protocols/iGEM/challenging-interlab-growth-curve.py @@ -9,7 +9,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert.markdown.markdown_specialization import MarkdownSpecialization doc = sbol3.Document() @@ -118,6 +118,7 @@ "ContainerSet", quantity=2 * len(plasmids), specification=labop.ContainerSpec( + "culture_day_1", name=f"culture (day 1)", queryString="cont:CultureTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -141,6 +142,7 @@ "ContainerSet", quantity=2 * len(plasmids), specification=labop.ContainerSpec( + "culture_day_2", name=f"culture (day 2)", queryString="cont:CultureTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -169,6 +171,7 @@ "ContainerSet", quantity=2 * len(plasmids), specification=labop.ContainerSpec( + "back_diluted_culture", name=f"back-diluted culture", queryString="cont:50mlConicalTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -193,6 +196,7 @@ quantity=2 * len(plasmids), replicates=3, specification=labop.ContainerSpec( + "replicate_subcultures", name=f"replicate subcultures", queryString="cont:50mlConicalTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -221,6 +225,7 @@ "ContainerSet", quantity=2 * len(plasmids) * 3, specification=labop.ContainerSpec( + "cultures_0_hr_timepoint", name="cultures (0 hr timepoint)", queryString="cont:MicrofugeTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -245,6 +250,7 @@ plate1 = activity.primitive_step( "EmptyContainer", specification=labop.ContainerSpec( + "plate_1", name="plate 1", queryString="cont:Plate96Well", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -253,6 +259,7 @@ plate2 = activity.primitive_step( "EmptyContainer", specification=labop.ContainerSpec( + "plate_2", name="plate 2", queryString="cont:Plate96Well", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -261,6 +268,7 @@ plate3 = activity.primitive_step( "EmptyContainer", specification=labop.ContainerSpec( + "plate_3", name="plate 3", queryString="cont:Plate96Well", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -436,15 +444,9 @@ fluorescence_0hrs_plate3.name = "0 hr fluorescence timepoint" ## Cover plate -seal = activity.primitive_step( - "EvaporativeSeal", location=plate1.output_pin("samples"), type="foo" -) -seal = activity.primitive_step( - "EvaporativeSeal", location=plate2.output_pin("samples"), type="foo" -) -seal = activity.primitive_step( - "EvaporativeSeal", location=plate3.output_pin("samples"), type="foo" -) +seal = activity.primitive_step("EvaporativeSeal", location=plate1.output_pin("samples")) +seal = activity.primitive_step("EvaporativeSeal", location=plate2.output_pin("samples")) +seal = activity.primitive_step("EvaporativeSeal", location=plate3.output_pin("samples")) ## Begin outgrowth @@ -502,6 +504,7 @@ "ContainerSet", quantity=2 * len(plasmids) * 3, specification=labop.ContainerSpec( + "cultures_2_hr_timepoint", name="cultures (0 hr timepoint)", queryString="cont:MicrofugeTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -526,6 +529,7 @@ plate4 = activity.primitive_step( "EmptyContainer", specification=labop.ContainerSpec( + "plate_4", name="plate 4", queryString="cont:Plate96Well", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, diff --git a/examples/protocols/iGEM/interlab-endpoint.py b/examples/protocols/iGEM/interlab-endpoint.py index a423e1f8..7c5782c9 100644 --- a/examples/protocols/iGEM/interlab-endpoint.py +++ b/examples/protocols/iGEM/interlab-endpoint.py @@ -3,7 +3,6 @@ """ import json import os -import sys from urllib.parse import quote import sbol3 @@ -11,7 +10,6 @@ import labop import uml -from labop.execution_engine import ExecutionEngine from labop_convert import MarkdownSpecialization @@ -48,604 +46,630 @@ def render_kit_coordinates_table(ex: labop.ProtocolExecution): ex.markdown = ex.markdown[:insert_index] + table + ex.markdown[insert_index:] -if "unittest" in sys.modules: - REGENERATE_ARTIFACTS = False -else: - REGENERATE_ARTIFACTS = True - -filename = "".join(__file__.split(".py")[0].split("/")[-1:]) - -doc = sbol3.Document() -sbol3.set_namespace("http://igem.org/engineering/") - -############################################# -# Import the primitive libraries -print("Importing libraries") -labop.import_library("liquid_handling") -print("... Imported liquid handling") -labop.import_library("plate_handling") -# print('... Imported plate handling') -labop.import_library("spectrophotometry") -print("... Imported spectrophotometry") -labop.import_library("sample_arrays") -print("... Imported sample arrays") -labop.import_library("culturing") -############################################# - - -# Cells and test circuits -dh5alpha = sbol3.Component("dh5alpha", "https://identifiers.org/taxonomy:668369") -dh5alpha.name = "_E. coli_ DH5 alpha competent cells" -doc.add(dh5alpha) - -neg_control_plasmid = sbol3.Component( - "neg_control_plasmid", "http://parts.igem.org/Part:BBa_J428100" -) -neg_control_plasmid.name = "Negative control" -neg_control_plasmid.description = "BBa_J428100 Kit Plate 1 Well 12M" - -pos_control_plasmid = sbol3.Component( - "pos_control_plasmid", "http://parts.igem.org/Part:BBa_I20270" -) -pos_control_plasmid.name = "Positive control (I20270)" -pos_control_plasmid.description = "BBa_I20270 Kit Plate 1 Well 1A" - -test_device1 = sbol3.Component("test_device1", "http://parts.igem.org/Part:BBa_J364000") -test_device1.name = "Test Device 1 (J364000)" -test_device1.description = "BBa_J364000 Kit Plate 1 Well 1C" - -test_device2 = sbol3.Component("test_device2", "http://parts.igem.org/Part:BBa_J364001") -test_device2.name = "Test Device 2 (J364001)" -test_device2.description = "BBa_J364001 Kit Plate 1 Well 1E" - -test_device3 = sbol3.Component("test_device3", "http://parts.igem.org/Part:BBa_J364002") -test_device3.name = "Test Device 3 (J364002)" -test_device3.description = "BBa_J364002 Kit Plate 1 Well 1G" - -test_device4 = sbol3.Component("test_device4", "http://parts.igem.org/Part:BBa_J364007") -test_device4.name = "Test Device 4 (J364007)" -test_device4.description = "BBa_J364007 Kit Plate 1 Well 1I" - -test_device5 = sbol3.Component("test_device5", "http://parts.igem.org/Part:BBa_J364008") -test_device5.name = "Test Device 5 (J364008)" -test_device5.description = "BBa_J364008 Kit Plate 1 Well 1K" - -test_device6 = sbol3.Component("test_device6", "http://parts.igem.org/Part:BBa_J364009") -test_device6.name = "Test Device 6 (J364009)" -test_device6.description = "BBa_J364009 Kit Plate 1 Well 1M" - -doc.add(neg_control_plasmid) -doc.add(pos_control_plasmid) -doc.add(test_device1) -doc.add(test_device2) -doc.add(test_device3) -doc.add(test_device4) -doc.add(test_device5) -doc.add(test_device6) - -# Other reagents -lb_cam = sbol3.Component("lb_cam", "") -lb_cam.name = "LB Broth + Chloramphenicol (34 ug/mL)" - -lb_agar_cam = sbol3.Component("lb_agar_cam", "") -lb_agar_cam.name = "LB Agar + Chloramphenicol (34 ug/mL)" - -chloramphenicol = sbol3.Component( - "chloramphenicol", "https://pubchem.ncbi.nlm.nih.gov/compound/5959" -) -chloramphenicol.name = "Chloramphenicol stock solution (34 mg/mL)" - -ice = sbol3.Component("ice", "") -ice.name = "Ice" - -doc.add(lb_cam) -doc.add(lb_agar_cam) -doc.add(chloramphenicol) -doc.add(ice) - -# Instruments and laboratory equipment -# TODO: instruments should be represented by sbol3.Agent -plate_reader = sbol3.Component("plate_reader", "") -plate_reader.name = "Plate reader" - -shaking_incubator = sbol3.Component("shaking_incubator", "") -shaking_incubator.name = "Shaking incubator" - -doc.add(plate_reader) -doc.add(shaking_incubator) - - -activity = labop.Protocol("interlab") -activity.name = "Cell measurement protocol" -activity.version = sbol3.TextProperty( - activity, - "http://igem.org/interlab_working_group#Version", - 0, - 1, - [], - "1.2.2", -) -activity.description = """This year we plan to test protocols that will eventually be automated. For this reason, we will use 96-well plates instead of test tubes for culturing. Consequently, we want to evaluate how the performance of our plate culturing protocol compares to culturing in test tubes (e.g. 10 mL falcon tube) on a global scale. - -At the end of the experiment, you will have two plates to be measured. You will measure both fluorescence and absorbance in each plate. - -Before performing the cell measurements, you need to perform all the calibration measurements. Please do not proceed unless you have completed the calibration protocol. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Engineering Committee (engineering [at] igem [dot] org) to discuss your situation. - -For all below indicated cell measurements, you must use the same type of plates and the same volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same type of plates, volumes, and settings, the measurements will not be valid. - -Protocol summary: You will transform the eight devices listed in Table 1 into E. coli K-12 DH5-alpha cells. The next day you will pick two colonies from each transformation (16 total) and use them to inoculate 5 mL overnight cultures (this step is still in tubes). Each of these 16 overnight cultures will be used to inoculate four wells in a 96-well plate (200 microliter each, 4 replicates) and one test tube (12 mL). You will measure how fluorescence and optical density develops over 6 hours by taking measurements at time point 0 hour and at time point 6 hours. Follow the protocol below and the visual instructions in Figure 1 and Figure 2.""" - -doc.add(activity) -activity = doc.find(activity.identity) - -plasmids = [ - neg_control_plasmid, - pos_control_plasmid, - test_device1, - test_device2, - test_device3, - test_device4, - test_device5, - test_device6, -] - -# Day 1: Transformation -culture_plates = activity.primitive_step( - "CulturePlates", - quantity=len(plasmids), - specification=labop.ContainerSpec( - "transformant_strains", - name=f"transformant strains", - queryString="cont:PetriDish", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), - growth_medium=lb_agar_cam, -) - -transformation = activity.primitive_step( - f"Transform", - host=dh5alpha, - dna=plasmids, - selection_medium=lb_agar_cam, - destination=culture_plates.output_pin("samples"), -) -transformation.description = "Incubate overnight (for 16 hour) at 37.0 degree Celsius." - -# Day 2: Pick colonies and culture overnight -culture_container_day1 = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_day_1", - name=f"culture (day 1)", - queryString="cont:CultureTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -pick_colonies = activity.primitive_step( - "PickColonies", - colonies=transformation.output_pin("transformants"), - quantity=2 * len(plasmids), - replicates=2, -) - -overnight_culture = activity.primitive_step( - "Culture", - inoculum=pick_colonies.output_pin("samples"), - replicates=2, - growth_medium=lb_cam, - volume=sbol3.Measure(12, OM.millilitre), # Actually 5-10 ml in the written protocol - duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours - orbital_shake_speed=sbol3.Measure( - 220, "None" - ), # No unit for RPM or inverse minutes - temperature=sbol3.Measure(37, OM.degree_Celsius), - container=culture_container_day1.output_pin("samples"), -) - -# Day 3 culture -culture_container_day2 = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_day_2", - name=f"culture (day 2)", - queryString="cont:CultureTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - - -back_dilution = activity.primitive_step( - "Dilute", - source=culture_container_day1.output_pin("samples"), - destination=culture_container_day2.output_pin("samples"), - replicates=2, - diluent=lb_cam, - amount=sbol3.Measure(5.0, OM.millilitre), - dilution_factor=uml.LiteralInteger(value=10), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -back_dilution.description = "(This can be also performed on ice)." - - -# Transfer cultures to a microplate baseline measurement and outgrowth -timepoint_0hrs = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_0_hr_timepoint", - name="cultures (0 hr timepoint)", - queryString="cont:MicrofugeTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -hold = activity.primitive_step( - "HoldOnIce", location=timepoint_0hrs.output_pin("samples") -) -hold.description = "This will prevent cell growth while transferring samples." - -transfer = activity.primitive_step( - "Transfer", - source=culture_container_day2.output_pin("samples"), - destination=timepoint_0hrs.output_pin("samples"), - amount=sbol3.Measure(1, OM.milliliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -transfer.description = "(This can be also performed on Ice)." - -# Abs measurement -baseline_absorbance = activity.primitive_step( - "MeasureAbsorbance", - samples=timepoint_0hrs.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -baseline_absorbance.name = "baseline absorbance of culture (day 2)" - - -conical_tube = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "back_diluted_culture", - name=f"back-diluted culture", - queryString="cont:50mlConicalTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) -conical_tube.description = ( - "The conical tube should be opaque, amber-colored, or covered with foil." -) - -dilution = activity.primitive_step( - "DiluteToTargetOD", - source=culture_container_day2.output_pin("samples"), - destination=conical_tube.output_pin("samples"), - diluent=lb_cam, - amount=sbol3.Measure(12, OM.millilitre), - target_od=sbol3.Measure(0.02, "None"), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) # Dilute to a target OD of 0.2, opaque container -dilution.description = f"(This can be also performed on Ice)." - -embedded_image = activity.primitive_step( - "EmbeddedImage", - image=os.path.join( - os.path.dirname(os.path.realpath(__file__)), - "fig1_standard_protocol.png", - ), - caption="Fig 1: Visual representation of protocol", -) - - -temporary = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "back_diluted_culture_aliquots", - name="back-diluted culture aliquots", - queryString="cont:MicrofugeTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -hold = activity.primitive_step("HoldOnIce", location=temporary.output_pin("samples")) -hold.description = "This will prevent cell growth while transferring samples." - -transfer = activity.primitive_step( - "Transfer", - source=conical_tube.output_pin("samples"), - destination=temporary.output_pin("samples"), - amount=sbol3.Measure(1, OM.milliliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -transfer.description = "(This can be also performed on Ice)." - -plate1 = activity.primitive_step( - "EmptyContainer", - specification=labop.ContainerSpec( - "plate_1", - name="plate 1", - queryString="cont:Plate96Well", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - - -hold = activity.primitive_step("HoldOnIce", location=plate1.output_pin("samples")) - - -plan = labop.SampleData( - from_samples=temporary.output_pin("samples"), - values=quote( - json.dumps( - { - "1": "A2:D2", - "2": "E2:H2", - "3": "A3:D3", - "4": "E3:H3", - "5": "A4:D4", - "6": "E4:H4", - "7": "A5:D5", - "8": "E5:H5", - "9": "A7:D7", - "10": "E7:H7", - "11": "A8:D8", - "12": "E8:H8", - "13": "A9:D9", - "14": "E9:H9", - "15": "A10:D10", - "16": "E10:H10", - } - ) - ), -) - - -transfer = activity.primitive_step( - "TransferByMap", - source=temporary.output_pin("samples"), - destination=plate1.output_pin("samples"), - amount=sbol3.Measure(200, OM.microliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), - plan=plan, -) -transfer.description = "See also the plate layout below." - -plate_blanks = activity.primitive_step( - "Transfer", - source=[lb_cam], - destination=plate1.output_pin("samples"), - coordinates="A1:H1, A10:H10, A12:H12", - temperature=sbol3.Measure(4, OM.degree_Celsius), - amount=sbol3.Measure(200, OM.microliter), -) -plate_blanks.description = "These samples are blanks." - -embedded_image = activity.primitive_step( - "EmbeddedImage", - image=os.path.join( - os.path.dirname(os.path.realpath(__file__)), "fig2_cell_calibration.png" - ), - caption="Fig 2: Plate layout", -) - -# Possibly display map here -absorbance_plate1 = activity.primitive_step( - "MeasureAbsorbance", - samples=plate1.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -absorbance_plate1.name = "0 hr absorbance timepoint" -fluorescence_plate1 = activity.primitive_step( - "MeasureFluorescence", - samples=plate1.output_pin("samples"), - excitationWavelength=sbol3.Measure(488, OM.nanometer), - emissionWavelength=sbol3.Measure(530, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), -) -fluorescence_plate1.name = "0 hr fluorescence timepoint" - -# Cover plate -seal = activity.primitive_step( - "EvaporativeSeal", - location=plate1.output_pin("samples"), - specification=labop.ContainerSpec( - "seal", - queryString="cont:MicroplateAdhesiveSealingFilm", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -# Begin outgrowth -incubate = activity.primitive_step( - "Incubate", - location=conical_tube.output_pin("samples"), - duration=sbol3.Measure(6, OM.hour), - temperature=sbol3.Measure(37, OM.degree_Celsius), - shakingFrequency=sbol3.Measure(220, "None"), -) - -incubate = activity.primitive_step( - "Incubate", - location=plate1.output_pin("samples"), - duration=sbol3.Measure(6, OM.hour), - temperature=sbol3.Measure(37, OM.degree_Celsius), - shakingFrequency=sbol3.Measure(220, "None"), -) - -# Hold on ice to inhibit cell growth -hold = activity.primitive_step("HoldOnIce", location=conical_tube.output_pin("samples")) -hold.description = ( - "This will inhibit cell growth during the subsequent pipetting steps." -) - -hold = activity.primitive_step("HoldOnIce", location=plate1.output_pin("samples")) -hold.description = ( - "This will inhibit cell growth during the subsequent pipetting steps." -) - - -# Take a 6hr timepoint measurement - -plate2 = activity.primitive_step( - "EmptyContainer", - specification=labop.ContainerSpec( - "plate_2", - name="plate 2", - queryString="cont:Plate96Well", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -# Hold on ice - -hold = activity.primitive_step("HoldOnIce", location=plate2.output_pin("samples")) - - -plan = labop.SampleData( - from_samples=conical_tube.output_pin("samples"), - values=quote( - json.dumps( - { - "1": "A2:D2", - "2": "E2:H2", - "3": "A3:D3", - "4": "E3:H3", - "5": "A4:D4", - "6": "E4:H4", - "7": "A5:D5", - "8": "E5:H5", - "9": "A7:D7", - "10": "E7:H7", - "11": "A8:D8", - "12": "E8:H8", - "13": "A9:D9", - "14": "E9:H9", - "15": "A10:D10", - "16": "E10:H10", - } - ) - ), -) - -transfer = activity.primitive_step( - "TransferByMap", - source=conical_tube.output_pin("samples"), - destination=plate2.output_pin("samples"), - amount=sbol3.Measure(200, OM.microliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), - plan=plan, -) -transfer.description = "See the plate layout." - -# Plate the blanks -plate_blanks = activity.primitive_step( - "Transfer", - source=[lb_cam], - destination=plate2.output_pin("samples"), - coordinates="A1:H1, A10:H10, A12:H12", - temperature=sbol3.Measure(4, OM.degree_Celsius), - amount=sbol3.Measure(200, OM.microliter), -) -plate_blanks.description = "These are the blanks." - - -endpoint_absorbance_plate1 = activity.primitive_step( - "MeasureAbsorbance", - samples=plate1.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -endpoint_absorbance_plate1.name = "6 hr absorbance timepoint" - -endpoint_fluorescence_plate1 = activity.primitive_step( - "MeasureFluorescence", - samples=plate1.output_pin("samples"), - excitationWavelength=sbol3.Measure(485, OM.nanometer), - emissionWavelength=sbol3.Measure(530, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), -) -endpoint_fluorescence_plate1.name = "6 hr fluorescence timepoint" - -endpoint_absorbance_plate2 = activity.primitive_step( - "MeasureAbsorbance", - samples=plate2.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -endpoint_absorbance_plate2.name = "6 hr absorbance timepoint" - -endpoint_fluorescence_plate2 = activity.primitive_step( - "MeasureFluorescence", - samples=plate2.output_pin("samples"), - excitationWavelength=sbol3.Measure(485, OM.nanometer), - emissionWavelength=sbol3.Measure(530, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), -) -endpoint_fluorescence_plate2.name = "6 hr fluorescence timepoint" - -activity.designate_output( - "baseline_absorbance_measurements", - "http://bioprotocols.org/labop#SampleData", - source=baseline_absorbance.output_pin("measurements"), -) -activity.designate_output( - "absorbance_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=absorbance_plate1.output_pin("measurements"), -) -activity.designate_output( - "fluorescence_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=fluorescence_plate1.output_pin("measurements"), -) - -activity.designate_output( - "endpoint_absorbance_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_absorbance_plate1.output_pin("measurements"), -) -activity.designate_output( - "endpoint_fluorescence_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_fluorescence_plate1.output_pin("measurements"), -) - -activity.designate_output( - "endpoint_absorbance_plate2_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_absorbance_plate2.output_pin("measurements"), -) -activity.designate_output( - "endpoint_fluorescence_plate2_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_fluorescence_plate2.output_pin("measurements"), -) - - -agent = sbol3.Agent("test_agent") -ee = ExecutionEngine( - specializations=[MarkdownSpecialization("test_LUDOX_markdown.md")], - failsafe=False, - track_samples=False, - sample_format="json", -) -execution = ee.execute(activity, agent, id="test_execution", parameter_values=[]) -render_kit_coordinates_table(execution) -print(execution.markdown) - -# Dress up the markdown to make it pretty and more readable -execution.markdown = execution.markdown.replace("`_E. coli_", "_`E. coli`_ `") -execution.markdown = execution.markdown.replace(" milliliter", "mL") -execution.markdown = execution.markdown.replace( - " degree Celsius", "\u00B0C" -) # degree symbol -execution.markdown = execution.markdown.replace(" nanometer", "nm") -execution.markdown = execution.markdown.replace(" microliter", "uL") - -filename = "".join(__file__.split(".py")[0].split("/")[-1:]) - -if REGENERATE_ARTIFACTS: - with open(filename + ".md", "w", encoding="utf-8") as f: - f.write(execution.markdown) +def generate_protocol(doc: sbol3.Document, activity: labop.Protocol) -> labop.Protocol: + # Cells and test circuits + dh5alpha = sbol3.Component("dh5alpha", "https://identifiers.org/taxonomy:668369") + dh5alpha.name = "_E. coli_ DH5 alpha competent cells" + doc.add(dh5alpha) + + neg_control_plasmid = sbol3.Component( + "neg_control_plasmid", "http://parts.igem.org/Part:BBa_J428100" + ) + neg_control_plasmid.name = "Negative control" + neg_control_plasmid.description = "BBa_J428100 Kit Plate 1 Well 12M" + + pos_control_plasmid = sbol3.Component( + "pos_control_plasmid", "http://parts.igem.org/Part:BBa_I20270" + ) + pos_control_plasmid.name = "Positive control (I20270)" + pos_control_plasmid.description = "BBa_I20270 Kit Plate 1 Well 1A" + + test_device1 = sbol3.Component( + "test_device1", "http://parts.igem.org/Part:BBa_J364000" + ) + test_device1.name = "Test Device 1 (J364000)" + test_device1.description = "BBa_J364000 Kit Plate 1 Well 1C" + + test_device2 = sbol3.Component( + "test_device2", "http://parts.igem.org/Part:BBa_J364001" + ) + test_device2.name = "Test Device 2 (J364001)" + test_device2.description = "BBa_J364001 Kit Plate 1 Well 1E" + + test_device3 = sbol3.Component( + "test_device3", "http://parts.igem.org/Part:BBa_J364002" + ) + test_device3.name = "Test Device 3 (J364002)" + test_device3.description = "BBa_J364002 Kit Plate 1 Well 1G" + + test_device4 = sbol3.Component( + "test_device4", "http://parts.igem.org/Part:BBa_J364007" + ) + test_device4.name = "Test Device 4 (J364007)" + test_device4.description = "BBa_J364007 Kit Plate 1 Well 1I" + + test_device5 = sbol3.Component( + "test_device5", "http://parts.igem.org/Part:BBa_J364008" + ) + test_device5.name = "Test Device 5 (J364008)" + test_device5.description = "BBa_J364008 Kit Plate 1 Well 1K" + + test_device6 = sbol3.Component( + "test_device6", "http://parts.igem.org/Part:BBa_J364009" + ) + test_device6.name = "Test Device 6 (J364009)" + test_device6.description = "BBa_J364009 Kit Plate 1 Well 1M" + + doc.add(neg_control_plasmid) + doc.add(pos_control_plasmid) + doc.add(test_device1) + doc.add(test_device2) + doc.add(test_device3) + doc.add(test_device4) + doc.add(test_device5) + doc.add(test_device6) + + # Other reagents + lb_cam = sbol3.Component("lb_cam", "") + lb_cam.name = "LB Broth + Chloramphenicol (34 ug/mL)" + + lb_agar_cam = sbol3.Component("lb_agar_cam", "") + lb_agar_cam.name = "LB Agar + Chloramphenicol (34 ug/mL)" + + chloramphenicol = sbol3.Component( + "chloramphenicol", "https://pubchem.ncbi.nlm.nih.gov/compound/5959" + ) + chloramphenicol.name = "Chloramphenicol stock solution (34 mg/mL)" + + ice = sbol3.Component("ice", "") + ice.name = "Ice" + + doc.add(lb_cam) + doc.add(lb_agar_cam) + doc.add(chloramphenicol) + doc.add(ice) + + # Instruments and laboratory equipment + # TODO: instruments should be represented by sbol3.Agent + plate_reader = sbol3.Component("plate_reader", "") + plate_reader.name = "Plate reader" + + shaking_incubator = sbol3.Component("shaking_incubator", "") + shaking_incubator.name = "Shaking incubator" + + doc.add(plate_reader) + doc.add(shaking_incubator) + + activity.name = "Cell measurement protocol" + activity.version = sbol3.TextProperty( + activity, + "http://igem.org/interlab_working_group#Version", + 0, + 1, + [], + "1.2.2", + ) + activity.description = """This year we plan to test protocols that will eventually be automated. For this reason, we will use 96-well plates instead of test tubes for culturing. Consequently, we want to evaluate how the performance of our plate culturing protocol compares to culturing in test tubes (e.g. 10 mL falcon tube) on a global scale. + + At the end of the experiment, you will have two plates to be measured. You will measure both fluorescence and absorbance in each plate. + + Before performing the cell measurements, you need to perform all the calibration measurements. Please do not proceed unless you have completed the calibration protocol. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Engineering Committee (engineering [at] igem [dot] org) to discuss your situation. + + For all below indicated cell measurements, you must use the same type of plates and the same volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same type of plates, volumes, and settings, the measurements will not be valid. + + Protocol summary: You will transform the eight devices listed in Table 1 into E. coli K-12 DH5-alpha cells. The next day you will pick two colonies from each transformation (16 total) and use them to inoculate 5 mL overnight cultures (this step is still in tubes). Each of these 16 overnight cultures will be used to inoculate four wells in a 96-well plate (200 microliter each, 4 replicates) and one test tube (12 mL). You will measure how fluorescence and optical density develops over 6 hours by taking measurements at time point 0 hour and at time point 6 hours. Follow the protocol below and the visual instructions in Figure 1 and Figure 2.""" + + activity = doc.find(activity.identity) + + plasmids = [ + neg_control_plasmid, + pos_control_plasmid, + test_device1, + test_device2, + test_device3, + test_device4, + test_device5, + test_device6, + ] + + # Day 1: Transformation + culture_plates = activity.primitive_step( + "CulturePlates", + quantity=len(plasmids), + specification=labop.ContainerSpec( + "transformant_strains", + name=f"transformant strains", + queryString="cont:PetriDish", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + growth_medium=lb_agar_cam, + ) + + transformation = activity.primitive_step( + f"Transform", + host=dh5alpha, + dna=plasmids, + selection_medium=lb_agar_cam, + destination=culture_plates.output_pin("samples"), + ) + transformation.description = ( + "Incubate overnight (for 16 hour) at 37.0 degree Celsius." + ) + + # Day 2: Pick colonies and culture overnight + culture_container_day1 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_day_1", + name=f"culture (day 1)", + queryString="cont:CultureTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + pick_colonies = activity.primitive_step( + "PickColonies", + colonies=transformation.output_pin("transformants"), + quantity=2 * len(plasmids), + replicates=2, + ) + + overnight_culture = activity.primitive_step( + "Culture", + inoculum=pick_colonies.output_pin("samples"), + replicates=2, + growth_medium=lb_cam, + volume=sbol3.Measure( + 12, OM.millilitre + ), # Actually 5-10 ml in the written protocol + duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours + orbital_shake_speed=sbol3.Measure( + 220, "None" + ), # No unit for RPM or inverse minutes + temperature=sbol3.Measure(37, OM.degree_Celsius), + container=culture_container_day1.output_pin("samples"), + ) + + # Day 3 culture + culture_container_day2 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_day_2", + name=f"culture (day 2)", + queryString="cont:CultureTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + back_dilution = activity.primitive_step( + "Dilute", + source=culture_container_day1.output_pin("samples"), + destination=culture_container_day2.output_pin("samples"), + replicates=2, + diluent=lb_cam, + amount=sbol3.Measure(5.0, OM.millilitre), + dilution_factor=uml.LiteralInteger(value=10), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + back_dilution.description = "(This can be also performed on ice)." + + # Transfer cultures to a microplate baseline measurement and outgrowth + timepoint_0hrs = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_0_hr_timepoint", + name="cultures (0 hr timepoint)", + queryString="cont:MicrofugeTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + hold = activity.primitive_step( + "HoldOnIce", location=timepoint_0hrs.output_pin("samples") + ) + hold.description = "This will prevent cell growth while transferring samples." + + transfer = activity.primitive_step( + "Transfer", + source=culture_container_day2.output_pin("samples"), + destination=timepoint_0hrs.output_pin("samples"), + amount=sbol3.Measure(1, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + transfer.description = "(This can be also performed on Ice)." + + # Abs measurement + baseline_absorbance = activity.primitive_step( + "MeasureAbsorbance", + samples=timepoint_0hrs.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + baseline_absorbance.name = "baseline absorbance of culture (day 2)" + + conical_tube = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "back_diluted_culture", + name=f"back-diluted culture", + queryString="cont:50mlConicalTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + conical_tube.description = ( + "The conical tube should be opaque, amber-colored, or covered with foil." + ) + + dilution = activity.primitive_step( + "DiluteToTargetOD", + source=culture_container_day2.output_pin("samples"), + destination=conical_tube.output_pin("samples"), + diluent=lb_cam, + amount=sbol3.Measure(12, OM.millilitre), + target_od=sbol3.Measure(0.02, "None"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) # Dilute to a target OD of 0.2, opaque container + dilution.description = f"(This can be also performed on Ice)." + + embedded_image = activity.primitive_step( + "EmbeddedImage", + image=os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "fig1_standard_protocol.png", + ), + caption="Fig 1: Visual representation of protocol", + ) + + temporary = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "back_diluted_culture_aliquots", + name="back-diluted culture aliquots", + queryString="cont:MicrofugeTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + hold = activity.primitive_step( + "HoldOnIce", location=temporary.output_pin("samples") + ) + hold.description = "This will prevent cell growth while transferring samples." + + transfer = activity.primitive_step( + "Transfer", + source=conical_tube.output_pin("samples"), + destination=temporary.output_pin("samples"), + amount=sbol3.Measure(1, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + transfer.description = "(This can be also performed on Ice)." + + plate1 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + "plate_1", + name="plate 1", + queryString="cont:Plate96Well", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + hold = activity.primitive_step("HoldOnIce", location=plate1.output_pin("samples")) + + plan = labop.SampleData( + from_samples=temporary.output_pin("samples"), + values=quote( + json.dumps( + { + "1": "A2:D2", + "2": "E2:H2", + "3": "A3:D3", + "4": "E3:H3", + "5": "A4:D4", + "6": "E4:H4", + "7": "A5:D5", + "8": "E5:H5", + "9": "A7:D7", + "10": "E7:H7", + "11": "A8:D8", + "12": "E8:H8", + "13": "A9:D9", + "14": "E9:H9", + "15": "A10:D10", + "16": "E10:H10", + } + ) + ), + ) + + transfer = activity.primitive_step( + "TransferByMap", + source=temporary.output_pin("samples"), + destination=plate1.output_pin("samples"), + amount=sbol3.Measure(200, OM.microliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + plan=plan, + ) + transfer.description = "See also the plate layout below." + + plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate1.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(200, OM.microliter), + ) + plate_blanks.description = "These samples are blanks." + + embedded_image = activity.primitive_step( + "EmbeddedImage", + image=os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "fig2_cell_calibration.png", + ), + caption="Fig 2: Plate layout", + ) + + # Possibly display map here + absorbance_plate1 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate1.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + absorbance_plate1.name = "0 hr absorbance timepoint" + fluorescence_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(488, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), + ) + fluorescence_plate1.name = "0 hr fluorescence timepoint" + + # Cover plate + seal = activity.primitive_step( + "EvaporativeSeal", + location=plate1.output_pin("samples"), + specification=labop.ContainerSpec( + "seal", + queryString="cont:MicroplateAdhesiveSealingFilm", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + # Begin outgrowth + incubate = activity.primitive_step( + "Incubate", + location=conical_tube.output_pin("samples"), + duration=sbol3.Measure(6, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, "None"), + ) + + incubate = activity.primitive_step( + "Incubate", + location=plate1.output_pin("samples"), + duration=sbol3.Measure(6, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, "None"), + ) + + # Hold on ice to inhibit cell growth + hold = activity.primitive_step( + "HoldOnIce", location=conical_tube.output_pin("samples") + ) + hold.description = ( + "This will inhibit cell growth during the subsequent pipetting steps." + ) + + hold = activity.primitive_step("HoldOnIce", location=plate1.output_pin("samples")) + hold.description = ( + "This will inhibit cell growth during the subsequent pipetting steps." + ) + + # Take a 6hr timepoint measurement + + plate2 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + "plate_2", + name="plate 2", + queryString="cont:Plate96Well", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + # Hold on ice + + hold = activity.primitive_step("HoldOnIce", location=plate2.output_pin("samples")) + + plan = labop.SampleData( + from_samples=conical_tube.output_pin("samples"), + values=quote( + json.dumps( + { + "1": "A2:D2", + "2": "E2:H2", + "3": "A3:D3", + "4": "E3:H3", + "5": "A4:D4", + "6": "E4:H4", + "7": "A5:D5", + "8": "E5:H5", + "9": "A7:D7", + "10": "E7:H7", + "11": "A8:D8", + "12": "E8:H8", + "13": "A9:D9", + "14": "E9:H9", + "15": "A10:D10", + "16": "E10:H10", + } + ) + ), + ) + + transfer = activity.primitive_step( + "TransferByMap", + source=conical_tube.output_pin("samples"), + destination=plate2.output_pin("samples"), + amount=sbol3.Measure(200, OM.microliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + plan=plan, + ) + transfer.description = "See the plate layout." + + # Plate the blanks + plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate2.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(200, OM.microliter), + ) + plate_blanks.description = "These are the blanks." + + endpoint_absorbance_plate1 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate1.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + endpoint_absorbance_plate1.name = "6 hr absorbance timepoint" + + endpoint_fluorescence_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), + ) + endpoint_fluorescence_plate1.name = "6 hr fluorescence timepoint" + + endpoint_absorbance_plate2 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate2.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + endpoint_absorbance_plate2.name = "6 hr absorbance timepoint" + + endpoint_fluorescence_plate2 = activity.primitive_step( + "MeasureFluorescence", + samples=plate2.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), + ) + endpoint_fluorescence_plate2.name = "6 hr fluorescence timepoint" + + activity.designate_output( + "baseline_absorbance_measurements", + "http://bioprotocols.org/labop#SampleData", + source=baseline_absorbance.output_pin("measurements"), + ) + activity.designate_output( + "absorbance_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_plate1.output_pin("measurements"), + ) + activity.designate_output( + "fluorescence_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_plate1.output_pin("measurements"), + ) + + activity.designate_output( + "endpoint_absorbance_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_absorbance_plate1.output_pin("measurements"), + ) + activity.designate_output( + "endpoint_fluorescence_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_fluorescence_plate1.output_pin("measurements"), + ) + + activity.designate_output( + "endpoint_absorbance_plate2_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_absorbance_plate2.output_pin("measurements"), + ) + activity.designate_output( + "endpoint_fluorescence_plate2_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_fluorescence_plate2.output_pin("measurements"), + ) + return activity + + +class InterlabCustomSpecialization(labop.execution.harness.ProtocolSpecialization): + def generate_artifact(self, harness: "ProtocolHarness"): + execution = self.specialization.execution + + render_kit_coordinates_table(execution) + print(execution.markdown) + + # Dress up the markdown to make it pretty and more readable + execution.markdown = execution.markdown.replace("`_E. coli_", "_`E. coli`_ `") + execution.markdown = execution.markdown.replace(" milliliter", "mL") + execution.markdown = execution.markdown.replace( + " degree Celsius", "\u00B0C" + ) # degree symbol + execution.markdown = execution.markdown.replace(" nanometer", "nm") + execution.markdown = execution.markdown.replace(" microliter", "uL") + + super().generate_artifact(harness) + + +if __name__ == "__main__": + harness = labop.execution.harness.ProtocolHarness( + protocol_name="interlab", + clean_output=True, + base_dir=os.path.join( + os.path.dirname(__file__), "out", "out_igem_interlab_endpoint" + ), + entry_point=generate_protocol, + agent="test_agent", + libraries=[ + "liquid_handling", + "plate_handling", + "spectrophotometry", + "sample_arrays", + "culturing", + ], + artifacts=[ + InterlabCustomSpecialization( + specialization=MarkdownSpecialization("test_LUDOX_markdown.md") + ) + ], + execution_kwargs={ + "failsafe": False, + "sample_format": "json", + "track_samples": False, + }, + execution_id="test_execution", + ) + harness.run() diff --git a/examples/protocols/iGEM/interlab-exp1.py b/examples/protocols/iGEM/interlab-exp1.py index 910d9631..591537cb 100644 --- a/examples/protocols/iGEM/interlab-exp1.py +++ b/examples/protocols/iGEM/interlab-exp1.py @@ -2,16 +2,15 @@ http://2018.igem.org/wiki/images/0/09/2018_InterLab_Plate_Reader_Protocol.pdf """ import json -import sys +import os from urllib.parse import quote import sbol3 from tyto import OM import labop +import labop_convert import uml -from labop.execution_engine import ExecutionEngine -from labop_convert import MarkdownSpecialization def render_kit_coordinates_table(ex: labop.ProtocolExecution): @@ -47,597 +46,626 @@ def render_kit_coordinates_table(ex: labop.ProtocolExecution): ex.markdown = ex.markdown[:insert_index] + table + ex.markdown[insert_index:] -if "unittest" in sys.modules: - REGENERATE_ARTIFACTS = False -else: - REGENERATE_ARTIFACTS = True - -filename = "".join(__file__.split(".py")[0].split("/")[-1:]) - -doc = sbol3.Document() -sbol3.set_namespace("http://igem.org/engineering/") - -############################################# -# Import the primitive libraries -print("Importing libraries") -labop.import_library("liquid_handling") -print("... Imported liquid handling") -labop.import_library("plate_handling") -# print('... Imported plate handling') -labop.import_library("spectrophotometry") -print("... Imported spectrophotometry") -labop.import_library("sample_arrays") -print("... Imported sample arrays") -labop.import_library("culturing") -############################################# - +def generate_protocol(doc: sbol3.Document, activity: labop.Protocol) -> labop.Protocol: + # create the materials to be provisioned + dh5alpha = sbol3.Component("dh5alpha", "https://identifiers.org/taxonomy:668369") + dh5alpha.name = "_E. coli_ DH5 alpha competent cells" + doc.add(dh5alpha) -# create the materials to be provisioned -dh5alpha = sbol3.Component("dh5alpha", "https://identifiers.org/taxonomy:668369") -dh5alpha.name = "_E. coli_ DH5 alpha competent cells" -doc.add(dh5alpha) - -neg_control_plasmid = sbol3.Component( - "neg_control_plasmid", "http://parts.igem.org/Part:BBa_J428100" -) -neg_control_plasmid.name = "Negative control 2022" -neg_control_plasmid.description = "BBa_J428100 Kit Plate 1 Well 12M" - -pos_control_plasmid = sbol3.Component( - "pos_control_plasmid", "http://parts.igem.org/Part:BBa_I20270" -) -pos_control_plasmid.name = "Positive control 2018" -pos_control_plasmid.description = "BBa_I20270 Kit Plate 1 Well 1A" - -test_device1 = sbol3.Component("test_device1", "http://parts.igem.org/Part:BBa_J428112") -test_device1.name = "Test Device 1 Exp 1 (Green Device)" -test_device1.description = "BBa_J428112 Kit Plate 1 Well 14C" - -test_device2 = sbol3.Component("test_device2", "http://parts.igem.org/Part:BBa_J428110") -test_device2.name = "Test Device 2 Exp 1 (Red mRFP1 device)" -test_device2.description = "BBa_J428110 Kit Plate 1 Well 12O" - -test_device3 = sbol3.Component("test_device3", "http://parts.igem.org/Part:BBa_J428111") -test_device3.name = "Test Device 3 Exp 1 (Red mCherry device)" -test_device3.description = "BBa_J428111 Kit Plate 1 Well 14A" - -test_device4 = sbol3.Component("test_device4", "http://parts.igem.org/Part:BBa_J428101") -test_device4.name = "Test Device 4 Exp 1 (RiboJ Insulated mCherry device)" -test_device4.description = "BBa_J428101 Kit Plate 1 Well 12I" - -test_device5 = sbol3.Component("test_device5", "http://parts.igem.org/Part:BBa_J428108") -test_device5.name = "Test Device 5 Exp 1 (Dual construct Blue and Red)" -test_device5.description = "BBa_J428108 Kit Plate 1 Well 14E" - -test_device6 = sbol3.Component("test_device6", "http://parts.igem.org/Part:BBa_J428106") -test_device6.name = "Test Device 6 Exp 1 (Dual construct Green and Blue)" -test_device6.description = "BBa_J428106 Kit Plate 1 Well 12G" - -doc.add(neg_control_plasmid) -doc.add(pos_control_plasmid) -doc.add(test_device1) -doc.add(test_device2) -doc.add(test_device3) -doc.add(test_device4) -doc.add(test_device5) -doc.add(test_device6) - -# Other reagents -lb_cam = sbol3.Component("lb_cam", "") -lb_cam.name = "LB Broth + Chloramphenicol (34 ug/mL)" - -lb_agar_cam = sbol3.Component("lb_agar_cam", "") -lb_agar_cam.name = "LB Agar + Chloramphenicol (34 ug/mL)" - -chloramphenicol = sbol3.Component( - "chloramphenicol", "https://pubchem.ncbi.nlm.nih.gov/compound/5959" -) -chloramphenicol.name = "Chloramphenicol stock solution (34 mg/mL)" - -ice = sbol3.Component("ice", "") -ice.name = "Ice" - -doc.add(lb_cam) -doc.add(lb_agar_cam) -doc.add(chloramphenicol) -doc.add(ice) - -# Instruments and laboratory equipment -# TODO: instruments should be represented by sbol3.Agent -plate_reader = sbol3.Component("plate_reader", "") -plate_reader.name = "Plate reader" - -shaking_incubator = sbol3.Component("shaking_incubator", "") -shaking_incubator.name = "Shaking incubator" - -doc.add(plate_reader) -doc.add(shaking_incubator) - -################################################################ -activity = labop.Protocol("interlab") -activity.name = "Testing the three color calibration protocol" -activity.version = sbol3.TextProperty( - activity, "http://igem.org/interlab_working_group#Version", 0, 1, [], "1.1b" -) -activity.description = """In this experiment, your team will measure the fluorescence of six devices that encode either a single fluorescence protein (blue, green, or red) or two fluorescence proteins encoded in two transcriptional units. You will calibrate the fluorescence of these devices to the three calibrant dyes and you will calibrate the optical density of the culture to the cell density calibrant. - -This experiment aims to assess the lab-to-lab reproducibility of the new three color calibration protocol. We will test if it works well for calibrating the fluorescence in cells that express one single fluorescent protein and for cells expressing two different fluorescent proteins at the same time. - -Before performing the cell measurements, you need to perform all the calibration measurements. Please do not proceed unless you have completed the calibration protocol. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Engineering Committee (engineering [at] igem [dot] org) to discuss your situation. - -For all below indicated cell measurements, you must use the same type of plates and the same volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same type of plates, volumes, and settings, the measurements will not be valid. - -Protocol summary: You will transform the eight devices listed in Table 1 into E. coli K-12 DH5-alpha cells. The next day you will pick two colonies from each transformation (16 total) and use them to inoculate 5 mL overnight cultures (this step is still in tubes). Each of these 16 overnight cultures will be used to inoculate four wells in a 96-well plate (200 microliter each, 4 replicates) and one test tube (12 mL). You will measure how fluorescence and optical density develops over 6 hours by taking measurements at time point 0 hour and at time point 6 hours. Follow the protocol below and the visual instructions in Figure 1 and Figure 2.""" - -doc.add(activity) -activity = doc.find(activity.identity) - -plasmids = [ - neg_control_plasmid, - pos_control_plasmid, - test_device1, - test_device2, - test_device3, - test_device4, - test_device5, - test_device6, -] - -# Day 1: Transformation -culture_plates = activity.primitive_step( - "CulturePlates", - quantity=len(plasmids), - specification=labop.ContainerSpec( - "transformant_strains", - name=f"transformant strains", - queryString="cont:PetriDish", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), - growth_medium=lb_agar_cam, -) - -transformation = activity.primitive_step( - f"Transform", - host=dh5alpha, - dna=plasmids, - selection_medium=lb_agar_cam, - destination=culture_plates.output_pin("samples"), -) -transformation.description = "Incubate overnight (for 16 hour) at 37.0 degree Celsius." - -# Day 2: Pick colonies and culture overnight -culture_container_day1 = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_day_1", - name=f"culture (day 1)", - queryString="cont:CultureTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -pick_colonies = activity.primitive_step( - "PickColonies", - colonies=transformation.output_pin("transformants"), - quantity=2 * len(plasmids), - replicates=2, -) - -overnight_culture = activity.primitive_step( - "Culture", - inoculum=pick_colonies.output_pin("samples"), - replicates=2, - growth_medium=lb_cam, - volume=sbol3.Measure(5, OM.millilitre), # Actually 5-10 ml in the written protocol - duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours - orbital_shake_speed=sbol3.Measure( - 220, "None" - ), # No unit for RPM or inverse minutes - temperature=sbol3.Measure(37, OM.degree_Celsius), - container=culture_container_day1.output_pin("samples"), -) - -# Day 3 culture -culture_container_day2 = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_day_2", - name=f"culture (day 2)", - queryString="cont:CultureTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - - -back_dilution = activity.primitive_step( - "Dilute", - source=culture_container_day1.output_pin("samples"), - destination=culture_container_day2.output_pin("samples"), - replicates=2, - diluent=lb_cam, - amount=sbol3.Measure(5.0, OM.millilitre), - dilution_factor=uml.LiteralInteger(value=10), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -back_dilution.description = "(This can be also performed on ice)." - -# Transfer cultures to a microplate baseline measurement and outgrowth -timepoint_0hrs = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_0hr_timepoint", - name="cultures (0 hr timepoint)", - queryString="cont:MicrofugeTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -hold = activity.primitive_step( - "HoldOnIce", location=timepoint_0hrs.output_pin("samples") -) -hold.description = "This will prevent cell growth while transferring samples." - -transfer = activity.primitive_step( - "Transfer", - source=culture_container_day2.output_pin("samples"), - destination=timepoint_0hrs.output_pin("samples"), - amount=sbol3.Measure(1, OM.milliliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -transfer.description = "(This can be also performed on Ice)." - -# Abs measurement -baseline_absorbance = activity.primitive_step( - "MeasureAbsorbance", - samples=timepoint_0hrs.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -baseline_absorbance.name = "baseline absorbance of culture (day 2)" - - -conical_tube = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "back_diluted_culture", - name=f"back-diluted culture", - queryString="cont:50mlConicalTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) -conical_tube.description = ( - "The conical tube should be opaque, amber-colored, or covered with foil." -) - -dilution = activity.primitive_step( - "DiluteToTargetOD", - source=culture_container_day2.output_pin("samples"), - destination=conical_tube.output_pin("samples"), - diluent=lb_cam, - amount=sbol3.Measure(12, OM.millilitre), - target_od=sbol3.Measure(0.02, "None"), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) # Dilute to a target OD of 0.2, opaque container -dilution.description = f"(This can be also performed on Ice)." - -embedded_image = activity.primitive_step( - "EmbeddedImage", - image="Exp1_2_protocol_published.png", - caption="Fig 1: Visual representation of protocol", -) - - -temporary = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "back_diluted_culture_aliquots", - name="back-diluted culture aliquots", - queryString="cont:MicrofugeTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -hold = activity.primitive_step("HoldOnIce", location=temporary.output_pin("samples")) -hold.description = "This will prevent cell growth while transferring samples." - -transfer = activity.primitive_step( - "Transfer", - source=conical_tube.output_pin("samples"), - destination=temporary.output_pin("samples"), - amount=sbol3.Measure(1, OM.milliliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -transfer.description = "(This can be also performed on Ice)." - -plate1 = activity.primitive_step( - "EmptyContainer", - specification=labop.ContainerSpec( - "plate_1", - name="plate 1", - queryString="cont:Plate96Well", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - - -hold = activity.primitive_step("HoldOnIce", location=plate1.output_pin("samples")) - - -plan = labop.SampleData( - from_samples=temporary.output_pin("samples"), - values=quote( - json.dumps( - { - "1": "A2:D2", - "2": "E2:H2", - "3": "A3:D3", - "4": "E3:H3", - "5": "A4:D4", - "6": "E4:H4", - "7": "A5:D5", - "8": "E5:H5", - "9": "A7:D7", - "10": "E7:H7", - "11": "A8:D8", - "12": "E8:H8", - "13": "A9:D9", - "14": "E9:H9", - "15": "A10:D10", - "16": "E10:H10", - } - ) - ), -) - - -transfer = activity.primitive_step( - "TransferByMap", - source=temporary.output_pin("samples"), - destination=plate1.output_pin("samples"), - amount=sbol3.Measure(200, OM.microliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), - plan=plan, -) -transfer.description = "See also the plate layout below." - -plate_blanks = activity.primitive_step( - "Transfer", - source=[lb_cam], - destination=plate1.output_pin("samples"), - coordinates="A1:H1, A10:H10, A12:H12", - temperature=sbol3.Measure(4, OM.degree_Celsius), - amount=sbol3.Measure(200, OM.microliter), -) -plate_blanks.description = "These samples are blanks." - -embedded_image = activity.primitive_step( - "EmbeddedImage", - image="fig2_cell_calibration.png", - caption="Fig 2: Plate layout", -) - - -# Possibly display map here -absorbance_plate1 = activity.primitive_step( - "MeasureAbsorbance", - samples=plate1.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -absorbance_plate1.name = "0 hr absorbance timepoint" -fluorescence_plate1 = activity.primitive_step( - "MeasureFluorescence", - samples=plate1.output_pin("samples"), - excitationWavelength=sbol3.Measure(488, OM.nanometer), - emissionWavelength=sbol3.Measure(530, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), -) -fluorescence_plate1.name = "0 hr green fluorescence timepoint" - -fluorescence_blue_plate1 = activity.primitive_step( - "MeasureFluorescence", - samples=plate1.output_pin("samples"), - excitationWavelength=sbol3.Measure(405, OM.nanometer), - emissionWavelength=sbol3.Measure(450, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(50, OM.nanometer), -) -fluorescence_blue_plate1.name = "0 hr blue fluorescence timepoint" - -fluorescence_red_plate1 = activity.primitive_step( - "MeasureFluorescence", - samples=plate1.output_pin("samples"), - excitationWavelength=sbol3.Measure(561, OM.nanometer), - emissionWavelength=sbol3.Measure(610, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(20, OM.nanometer), -) -fluorescence_red_plate1.name = "0 hr red fluorescence timepoint" - - -# Begin outgrowth -incubate = activity.primitive_step( - "Incubate", - location=conical_tube.output_pin("samples"), - duration=sbol3.Measure(6, OM.hour), - temperature=sbol3.Measure(37, OM.degree_Celsius), - shakingFrequency=sbol3.Measure(220, "None"), -) - - -# Hold on ice to inhibit cell growth -hold = activity.primitive_step("HoldOnIce", location=conical_tube.output_pin("samples")) -hold.description = ( - "This will inhibit cell growth during the subsequent pipetting steps." -) - -# Take a 6hr timepoint measurement -plate2 = activity.primitive_step( - "EmptyContainer", - specification=labop.ContainerSpec( - "plate_2", - name="plate 2", - queryString="cont:Plate96Well", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -# Hold on ice -hold = activity.primitive_step("HoldOnIce", location=plate2.output_pin("samples")) - - -plan = labop.SampleData( - from_samples=conical_tube.output_pin("samples"), - values=quote( - json.dumps( - { - "1": "A2:D2", - "2": "E2:H2", - "3": "A3:D3", - "4": "E3:H3", - "5": "A4:D4", - "6": "E4:H4", - "7": "A5:D5", - "8": "E5:H5", - "9": "A7:D7", - "10": "E7:H7", - "11": "A8:D8", - "12": "E8:H8", - "13": "A9:D9", - "14": "E9:H9", - "15": "A10:D10", - "16": "E10:H10", - } - ) - ), -) - -transfer = activity.primitive_step( - "TransferByMap", - source=conical_tube.output_pin("samples"), - destination=plate2.output_pin("samples"), - amount=sbol3.Measure(200, OM.microliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), - plan=plan, -) -transfer.description = "See the plate layout." - -# Plate the blanks -plate_blanks = activity.primitive_step( - "Transfer", - source=[lb_cam], - destination=plate2.output_pin("samples"), - coordinates="A1:H1, A10:H10, A12:H12", - temperature=sbol3.Measure(4, OM.degree_Celsius), - amount=sbol3.Measure(200, OM.microliter), -) -plate_blanks.description = "These are the blanks." - - -endpoint_absorbance_plate2 = activity.primitive_step( - "MeasureAbsorbance", - samples=plate2.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -endpoint_absorbance_plate2.name = "6 hr absorbance timepoint" - -endpoint_fluorescence_plate2 = activity.primitive_step( - "MeasureFluorescence", - samples=plate2.output_pin("samples"), - excitationWavelength=sbol3.Measure(485, OM.nanometer), - emissionWavelength=sbol3.Measure(530, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), -) -endpoint_fluorescence_plate2.name = "6 hr green fluorescence timepoint" - -endpoint_fluorescence_blue_plate2 = activity.primitive_step( - "MeasureFluorescence", - samples=plate2.output_pin("samples"), - excitationWavelength=sbol3.Measure(405, OM.nanometer), - emissionWavelength=sbol3.Measure(450, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(50, OM.nanometer), -) -endpoint_fluorescence_blue_plate2.name = "6 hr blue fluorescence timepoint" - -endpoint_fluorescence_red_plate2 = activity.primitive_step( - "MeasureFluorescence", - samples=plate2.output_pin("samples"), - excitationWavelength=sbol3.Measure(561, OM.nanometer), - emissionWavelength=sbol3.Measure(610, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(20, OM.nanometer), -) -endpoint_fluorescence_red_plate2.name = "6 hr red fluorescence timepoint" - - -activity.designate_output( - "baseline_absorbance_measurements", - "http://bioprotocols.org/labop#SampleData", - source=baseline_absorbance.output_pin("measurements"), -) -activity.designate_output( - "absorbance_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=absorbance_plate1.output_pin("measurements"), -) -activity.designate_output( - "fluorescence_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=fluorescence_plate1.output_pin("measurements"), -) -activity.designate_output( - "fluorescence_blue_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=fluorescence_blue_plate1.output_pin("measurements"), -) -activity.designate_output( - "fluorescence_red_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=fluorescence_red_plate1.output_pin("measurements"), -) - - -activity.designate_output( - "endpoint_absorbance_plate2_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_absorbance_plate2.output_pin("measurements"), -) -activity.designate_output( - "endpoint_fluorescence_plate2_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_fluorescence_plate2.output_pin("measurements"), -) -activity.designate_output( - "endpoint_fluorescence_blue_plate2_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_fluorescence_blue_plate2.output_pin("measurements"), -) -activity.designate_output( - "endpoint_fluorescence_red_plate2_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_fluorescence_red_plate2.output_pin("measurements"), -) - -agent = sbol3.Agent("test_agent") -ee = ExecutionEngine( - specializations=[MarkdownSpecialization("test_LUDOX_markdown.md")], - failsafe=False, - sample_format="json", - track_samples=False, -) -execution = ee.execute(activity, agent, id="test_execution", parameter_values=[]) -render_kit_coordinates_table(execution) -print(execution.markdown) - -# Dress up the markdown to make it pretty and more readable -execution.markdown = execution.markdown.replace("`_E. coli_", "_`E. coli`_ `") -execution.markdown = execution.markdown.replace(" milliliter", "mL") -execution.markdown = execution.markdown.replace( - " degree Celsius", "\u00B0C" -) # degree symbol -execution.markdown = execution.markdown.replace(" nanometer", "nm") -execution.markdown = execution.markdown.replace(" microliter", "uL") - -if REGENERATE_ARTIFACTS: - with open(filename + ".md", "w", encoding="utf-8") as f: - f.write(execution.markdown) + neg_control_plasmid = sbol3.Component( + "neg_control_plasmid", "http://parts.igem.org/Part:BBa_J428100" + ) + neg_control_plasmid.name = "Negative control 2022" + neg_control_plasmid.description = "BBa_J428100 Kit Plate 1 Well 12M" + + pos_control_plasmid = sbol3.Component( + "pos_control_plasmid", "http://parts.igem.org/Part:BBa_I20270" + ) + pos_control_plasmid.name = "Positive control 2018" + pos_control_plasmid.description = "BBa_I20270 Kit Plate 1 Well 1A" + + test_device1 = sbol3.Component( + "test_device1", "http://parts.igem.org/Part:BBa_J428112" + ) + test_device1.name = "Test Device 1 Exp 1 (Green Device)" + test_device1.description = "BBa_J428112 Kit Plate 1 Well 14C" + + test_device2 = sbol3.Component( + "test_device2", "http://parts.igem.org/Part:BBa_J428110" + ) + test_device2.name = "Test Device 2 Exp 1 (Red mRFP1 device)" + test_device2.description = "BBa_J428110 Kit Plate 1 Well 12O" + + test_device3 = sbol3.Component( + "test_device3", "http://parts.igem.org/Part:BBa_J428111" + ) + test_device3.name = "Test Device 3 Exp 1 (Red mCherry device)" + test_device3.description = "BBa_J428111 Kit Plate 1 Well 14A" + + test_device4 = sbol3.Component( + "test_device4", "http://parts.igem.org/Part:BBa_J428101" + ) + test_device4.name = "Test Device 4 Exp 1 (RiboJ Insulated mCherry device)" + test_device4.description = "BBa_J428101 Kit Plate 1 Well 12I" + + test_device5 = sbol3.Component( + "test_device5", "http://parts.igem.org/Part:BBa_J428108" + ) + test_device5.name = "Test Device 5 Exp 1 (Dual construct Blue and Red)" + test_device5.description = "BBa_J428108 Kit Plate 1 Well 14E" + + test_device6 = sbol3.Component( + "test_device6", "http://parts.igem.org/Part:BBa_J428106" + ) + test_device6.name = "Test Device 6 Exp 1 (Dual construct Green and Blue)" + test_device6.description = "BBa_J428106 Kit Plate 1 Well 12G" + + doc.add(neg_control_plasmid) + doc.add(pos_control_plasmid) + doc.add(test_device1) + doc.add(test_device2) + doc.add(test_device3) + doc.add(test_device4) + doc.add(test_device5) + doc.add(test_device6) + + # Other reagents + lb_cam = sbol3.Component("lb_cam", "") + lb_cam.name = "LB Broth + Chloramphenicol (34 ug/mL)" + + lb_agar_cam = sbol3.Component("lb_agar_cam", "") + lb_agar_cam.name = "LB Agar + Chloramphenicol (34 ug/mL)" + + chloramphenicol = sbol3.Component( + "chloramphenicol", "https://pubchem.ncbi.nlm.nih.gov/compound/5959" + ) + chloramphenicol.name = "Chloramphenicol stock solution (34 mg/mL)" + + ice = sbol3.Component("ice", "") + ice.name = "Ice" + + doc.add(lb_cam) + doc.add(lb_agar_cam) + doc.add(chloramphenicol) + doc.add(ice) + + # Instruments and laboratory equipment + # TODO: instruments should be represented by sbol3.Agent + plate_reader = sbol3.Component("plate_reader", "") + plate_reader.name = "Plate reader" + + shaking_incubator = sbol3.Component("shaking_incubator", "") + shaking_incubator.name = "Shaking incubator" + + doc.add(plate_reader) + doc.add(shaking_incubator) + + ################################################################ + activity.name = "Testing the three color calibration protocol" + activity.version = sbol3.TextProperty( + activity, + "http://igem.org/interlab_working_group#Version", + 0, + 1, + [], + "1.1b", + ) + activity.description = """In this experiment, your team will measure the fluorescence of six devices that encode either a single fluorescence protein (blue, green, or red) or two fluorescence proteins encoded in two transcriptional units. You will calibrate the fluorescence of these devices to the three calibrant dyes and you will calibrate the optical density of the culture to the cell density calibrant. + + This experiment aims to assess the lab-to-lab reproducibility of the new three color calibration protocol. We will test if it works well for calibrating the fluorescence in cells that express one single fluorescent protein and for cells expressing two different fluorescent proteins at the same time. + + Before performing the cell measurements, you need to perform all the calibration measurements. Please do not proceed unless you have completed the calibration protocol. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Engineering Committee (engineering [at] igem [dot] org) to discuss your situation. + + For all below indicated cell measurements, you must use the same type of plates and the same volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same type of plates, volumes, and settings, the measurements will not be valid. + + Protocol summary: You will transform the eight devices listed in Table 1 into E. coli K-12 DH5-alpha cells. The next day you will pick two colonies from each transformation (16 total) and use them to inoculate 5 mL overnight cultures (this step is still in tubes). Each of these 16 overnight cultures will be used to inoculate four wells in a 96-well plate (200 microliter each, 4 replicates) and one test tube (12 mL). You will measure how fluorescence and optical density develops over 6 hours by taking measurements at time point 0 hour and at time point 6 hours. Follow the protocol below and the visual instructions in Figure 1 and Figure 2.""" + + activity = doc.find(activity.identity) + + plasmids = [ + neg_control_plasmid, + pos_control_plasmid, + test_device1, + test_device2, + test_device3, + test_device4, + test_device5, + test_device6, + ] + + # Day 1: Transformation + culture_plates = activity.primitive_step( + "CulturePlates", + quantity=len(plasmids), + specification=labop.ContainerSpec( + "transformant_strains", + name=f"transformant strains", + queryString="cont:PetriDish", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + growth_medium=lb_agar_cam, + ) + + transformation = activity.primitive_step( + f"Transform", + host=dh5alpha, + dna=plasmids, + selection_medium=lb_agar_cam, + destination=culture_plates.output_pin("samples"), + ) + transformation.description = ( + "Incubate overnight (for 16 hour) at 37.0 degree Celsius." + ) + + # Day 2: Pick colonies and culture overnight + culture_container_day1 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_day_1", + name=f"culture (day 1)", + queryString="cont:CultureTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + pick_colonies = activity.primitive_step( + "PickColonies", + colonies=transformation.output_pin("transformants"), + quantity=2 * len(plasmids), + replicates=2, + ) + + overnight_culture = activity.primitive_step( + "Culture", + inoculum=pick_colonies.output_pin("samples"), + replicates=2, + growth_medium=lb_cam, + volume=sbol3.Measure( + 5, OM.millilitre + ), # Actually 5-10 ml in the written protocol + duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours + orbital_shake_speed=sbol3.Measure( + 220, "None" + ), # No unit for RPM or inverse minutes + temperature=sbol3.Measure(37, OM.degree_Celsius), + container=culture_container_day1.output_pin("samples"), + ) + + # Day 3 culture + culture_container_day2 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_day_2", + name=f"culture (day 2)", + queryString="cont:CultureTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + back_dilution = activity.primitive_step( + "Dilute", + source=culture_container_day1.output_pin("samples"), + destination=culture_container_day2.output_pin("samples"), + replicates=2, + diluent=lb_cam, + amount=sbol3.Measure(5.0, OM.millilitre), + dilution_factor=uml.LiteralInteger(value=10), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + back_dilution.description = "(This can be also performed on ice)." + + # Transfer cultures to a microplate baseline measurement and outgrowth + timepoint_0hrs = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_0hr_timepoint", + name="cultures (0 hr timepoint)", + queryString="cont:MicrofugeTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + hold = activity.primitive_step( + "HoldOnIce", location=timepoint_0hrs.output_pin("samples") + ) + hold.description = "This will prevent cell growth while transferring samples." + + transfer = activity.primitive_step( + "Transfer", + source=culture_container_day2.output_pin("samples"), + destination=timepoint_0hrs.output_pin("samples"), + amount=sbol3.Measure(1, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + transfer.description = "(This can be also performed on Ice)." + + # Abs measurement + baseline_absorbance = activity.primitive_step( + "MeasureAbsorbance", + samples=timepoint_0hrs.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + baseline_absorbance.name = "baseline absorbance of culture (day 2)" + + conical_tube = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "back_diluted_culture", + name=f"back-diluted culture", + queryString="cont:50mlConicalTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + conical_tube.description = ( + "The conical tube should be opaque, amber-colored, or covered with foil." + ) + + dilution = activity.primitive_step( + "DiluteToTargetOD", + source=culture_container_day2.output_pin("samples"), + destination=conical_tube.output_pin("samples"), + diluent=lb_cam, + amount=sbol3.Measure(12, OM.millilitre), + target_od=sbol3.Measure(0.02, "None"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) # Dilute to a target OD of 0.2, opaque container + dilution.description = f"(This can be also performed on Ice)." + + embedded_image = activity.primitive_step( + "EmbeddedImage", + image="Exp1_2_protocol_published.png", + caption="Fig 1: Visual representation of protocol", + ) + + temporary = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "back_diluted_culture_aliquots", + name="back-diluted culture aliquots", + queryString="cont:MicrofugeTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + hold = activity.primitive_step( + "HoldOnIce", location=temporary.output_pin("samples") + ) + hold.description = "This will prevent cell growth while transferring samples." + + transfer = activity.primitive_step( + "Transfer", + source=conical_tube.output_pin("samples"), + destination=temporary.output_pin("samples"), + amount=sbol3.Measure(1, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + transfer.description = "(This can be also performed on Ice)." + + plate1 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + "plate_1", + name="plate 1", + queryString="cont:Plate96Well", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + hold = activity.primitive_step("HoldOnIce", location=plate1.output_pin("samples")) + + plan = labop.SampleData( + from_samples=temporary.output_pin("samples"), + values=quote( + json.dumps( + { + "1": "A2:D2", + "2": "E2:H2", + "3": "A3:D3", + "4": "E3:H3", + "5": "A4:D4", + "6": "E4:H4", + "7": "A5:D5", + "8": "E5:H5", + "9": "A7:D7", + "10": "E7:H7", + "11": "A8:D8", + "12": "E8:H8", + "13": "A9:D9", + "14": "E9:H9", + "15": "A10:D10", + "16": "E10:H10", + } + ) + ), + ) + + transfer = activity.primitive_step( + "TransferByMap", + source=temporary.output_pin("samples"), + destination=plate1.output_pin("samples"), + amount=sbol3.Measure(200, OM.microliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + plan=plan, + ) + transfer.description = "See also the plate layout below." + + plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate1.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(200, OM.microliter), + ) + plate_blanks.description = "These samples are blanks." + + embedded_image = activity.primitive_step( + "EmbeddedImage", + image="fig2_cell_calibration.png", + caption="Fig 2: Plate layout", + ) + + # Possibly display map here + absorbance_plate1 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate1.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + absorbance_plate1.name = "0 hr absorbance timepoint" + fluorescence_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(488, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), + ) + fluorescence_plate1.name = "0 hr green fluorescence timepoint" + + fluorescence_blue_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(405, OM.nanometer), + emissionWavelength=sbol3.Measure(450, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(50, OM.nanometer), + ) + fluorescence_blue_plate1.name = "0 hr blue fluorescence timepoint" + + fluorescence_red_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(561, OM.nanometer), + emissionWavelength=sbol3.Measure(610, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(20, OM.nanometer), + ) + fluorescence_red_plate1.name = "0 hr red fluorescence timepoint" + + # Begin outgrowth + incubate = activity.primitive_step( + "Incubate", + location=conical_tube.output_pin("samples"), + duration=sbol3.Measure(6, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, "None"), + ) + + # Hold on ice to inhibit cell growth + hold = activity.primitive_step( + "HoldOnIce", location=conical_tube.output_pin("samples") + ) + hold.description = ( + "This will inhibit cell growth during the subsequent pipetting steps." + ) + + # Take a 6hr timepoint measurement + plate2 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + "plate_2", + name="plate 2", + queryString="cont:Plate96Well", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + # Hold on ice + hold = activity.primitive_step("HoldOnIce", location=plate2.output_pin("samples")) + + plan = labop.SampleData( + from_samples=conical_tube.output_pin("samples"), + values=quote( + json.dumps( + { + "1": "A2:D2", + "2": "E2:H2", + "3": "A3:D3", + "4": "E3:H3", + "5": "A4:D4", + "6": "E4:H4", + "7": "A5:D5", + "8": "E5:H5", + "9": "A7:D7", + "10": "E7:H7", + "11": "A8:D8", + "12": "E8:H8", + "13": "A9:D9", + "14": "E9:H9", + "15": "A10:D10", + "16": "E10:H10", + } + ) + ), + ) + + transfer = activity.primitive_step( + "TransferByMap", + source=conical_tube.output_pin("samples"), + destination=plate2.output_pin("samples"), + amount=sbol3.Measure(200, OM.microliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + plan=plan, + ) + transfer.description = "See the plate layout." + + # Plate the blanks + plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate2.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(200, OM.microliter), + ) + plate_blanks.description = "These are the blanks." + + endpoint_absorbance_plate2 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate2.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + endpoint_absorbance_plate2.name = "6 hr absorbance timepoint" + + endpoint_fluorescence_plate2 = activity.primitive_step( + "MeasureFluorescence", + samples=plate2.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), + ) + endpoint_fluorescence_plate2.name = "6 hr green fluorescence timepoint" + + endpoint_fluorescence_blue_plate2 = activity.primitive_step( + "MeasureFluorescence", + samples=plate2.output_pin("samples"), + excitationWavelength=sbol3.Measure(405, OM.nanometer), + emissionWavelength=sbol3.Measure(450, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(50, OM.nanometer), + ) + endpoint_fluorescence_blue_plate2.name = "6 hr blue fluorescence timepoint" + + endpoint_fluorescence_red_plate2 = activity.primitive_step( + "MeasureFluorescence", + samples=plate2.output_pin("samples"), + excitationWavelength=sbol3.Measure(561, OM.nanometer), + emissionWavelength=sbol3.Measure(610, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(20, OM.nanometer), + ) + endpoint_fluorescence_red_plate2.name = "6 hr red fluorescence timepoint" + + activity.designate_output( + "baseline_absorbance_measurements", + "http://bioprotocols.org/labop#SampleData", + source=baseline_absorbance.output_pin("measurements"), + ) + activity.designate_output( + "absorbance_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_plate1.output_pin("measurements"), + ) + activity.designate_output( + "fluorescence_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_plate1.output_pin("measurements"), + ) + activity.designate_output( + "fluorescence_blue_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_blue_plate1.output_pin("measurements"), + ) + activity.designate_output( + "fluorescence_red_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_red_plate1.output_pin("measurements"), + ) + + activity.designate_output( + "endpoint_absorbance_plate2_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_absorbance_plate2.output_pin("measurements"), + ) + activity.designate_output( + "endpoint_fluorescence_plate2_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_fluorescence_plate2.output_pin("measurements"), + ) + activity.designate_output( + "endpoint_fluorescence_blue_plate2_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_fluorescence_blue_plate2.output_pin("measurements"), + ) + activity.designate_output( + "endpoint_fluorescence_red_plate2_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_fluorescence_red_plate2.output_pin("measurements"), + ) + return activity + + +class InterlabCustomSpecialization(labop.execution.harness.ProtocolSpecialization): + def generate_artifact(self, harness: "ProtocolHarness"): + execution = self.specialization.execution + + render_kit_coordinates_table(execution) + print(execution.markdown) + + # Dress up the markdown to make it pretty and more readable + execution.markdown = execution.markdown.replace("`_E. coli_", "_`E. coli`_ `") + execution.markdown = execution.markdown.replace(" milliliter", "mL") + execution.markdown = execution.markdown.replace( + " degree Celsius", "\u00B0C" + ) # degree symbol + execution.markdown = execution.markdown.replace(" nanometer", "nm") + execution.markdown = execution.markdown.replace(" microliter", "uL") + + super().generate_artifact(harness) + + +if __name__ == "__main__": + harness = labop.execution.harness.ProtocolHarness( + protocol_name="interlab", + clean_output=True, + base_dir=os.path.join(os.path.dirname(__file__), "out", "out_igem_example1"), + entry_point=generate_protocol, + agent="test_agent", + libraries=[ + "liquid_handling", + "plate_handling", + "spectrophotometry", + "sample_arrays", + "culturing", + ], + artifacts=[ + InterlabCustomSpecialization( + specialization=labop_convert.MarkdownSpecialization( + "test_LUDOX_markdown.md" + ) + ) + ], + execution_kwargs={ + "failsafe": False, + "sample_format": "json", + "track_samples": False, + }, + execution_id="test_execution", + ) + harness.run() diff --git a/examples/protocols/iGEM/interlab-exp1_MI.py b/examples/protocols/iGEM/interlab-exp1_MI.py index 32006875..5b16f325 100644 --- a/examples/protocols/iGEM/interlab-exp1_MI.py +++ b/examples/protocols/iGEM/interlab-exp1_MI.py @@ -10,7 +10,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert.markdown.markdown_specialization import MarkdownSpecialization filename = "".join(__file__.split(".py")[0].split("/")[-1:]) diff --git a/examples/protocols/iGEM/interlab-exp2.py b/examples/protocols/iGEM/interlab-exp2.py index 5495c8a6..9fe46c0a 100644 --- a/examples/protocols/iGEM/interlab-exp2.py +++ b/examples/protocols/iGEM/interlab-exp2.py @@ -2,16 +2,15 @@ http://2018.igem.org/wiki/images/0/09/2018_InterLab_Plate_Reader_Protocol.pdf """ import json -import sys +import os from urllib.parse import quote import sbol3 from tyto import OM import labop +import labop_convert import uml -from labop.execution_engine import ExecutionEngine -from labop_convert import MarkdownSpecialization def render_kit_coordinates_table(ex: labop.ProtocolExecution): @@ -47,604 +46,623 @@ def render_kit_coordinates_table(ex: labop.ProtocolExecution): ex.markdown = ex.markdown[:insert_index] + table + ex.markdown[insert_index:] -if "unittest" in sys.modules: - REGENERATE_ARTIFACTS = False -else: - REGENERATE_ARTIFACTS = True - -filename = "".join(__file__.split(".py")[0].split("/")[-1:]) - -doc = sbol3.Document() -sbol3.set_namespace("http://igem.org/engineering/") - -############################################# -# Import the primitive libraries -print("Importing libraries") -labop.import_library("liquid_handling") -print("... Imported liquid handling") -labop.import_library("plate_handling") -# print('... Imported plate handling') -labop.import_library("spectrophotometry") -print("... Imported spectrophotometry") -labop.import_library("sample_arrays") -print("... Imported sample arrays") -labop.import_library("culturing") -############################################# - - -# create the materials to be provisioned -dh5alpha = sbol3.Component("dh5alpha", "https://identifiers.org/taxonomy:668369") -dh5alpha.name = "_E. coli_ DH5 alpha" -doc.add(dh5alpha) - -lb_cam = sbol3.Component("lb_cam", "") -lb_cam.name = "LB Broth+chloramphenicol" -doc.add(lb_cam) - -chloramphenicol = sbol3.Component( - "chloramphenicol", "https://pubchem.ncbi.nlm.nih.gov/compound/5959" -) -chloramphenicol.name = "chloramphenicol" -doc.add(chloramphenicol) - - -neg_control_plasmid = sbol3.Component( - "neg_control_plasmid", "http://parts.igem.org/Part:BBa_J428100" -) -neg_control_plasmid.name = "Negative control 2022" -neg_control_plasmid.description = "BBa_J428100 Kit Plate 1 Well 12M" - -pos_control_green_plasmid = sbol3.Component( - "pos_control_green_plasmid", "http://parts.igem.org/Part:BBa_J428112" -) -pos_control_green_plasmid.name = "Positive control 2022 Green" -pos_control_green_plasmid.description = ( - "3_Colors_ins_K2656022 BBa_J428112 Kit Plate 1 Well 14C" -) - -pos_control_red_plasmid = sbol3.Component( - "pos_control_red_plasmid", "http://parts.igem.org/Part:BBa_J428101" -) -pos_control_red_plasmid.name = "Positive control red (mCherry) Exp 2" -pos_control_red_plasmid.description = "BBa_J428101 Kit Plate 1 Well 12I" - -test_device1 = sbol3.Component("test_device1", "http://parts.igem.org/Part:BBa_J428106") -test_device1.name = "Test Device 1 Exp 2 (Dual construct Green and Blue)" -test_device1.description = "BBa_J428106 Kit Plate 1 Well 12G" - -test_device2 = sbol3.Component("test_device2", "http://parts.igem.org/Part:BBa_J428107") -test_device2.name = "Test Device 2 Exp 2 (Dual construct Green and Red)" -test_device2.description = "BBa_J428107 Kit Plate 1 Well 3L" - -test_device3 = sbol3.Component("test_device3", "http://parts.igem.org/Part:BBa_J428105") -test_device3.name = "Test Device 3 Exp 2 (Dual construct Red and Blue)" -test_device3.description = "BBa_J428105 Kit Plate 1 Well 5J" - -test_device4 = sbol3.Component("test_device4", "http://parts.igem.org/Part:BBa_J428108") -test_device4.name = "Test Device 4 Exp 2 (Dual construct Blue and Red)" -test_device4.description = "BBa_J428108 Kit Plate 1 Well 14E" - -test_device5 = sbol3.Component("test_device5", "http://parts.igem.org/Part:BBa_J428104") -test_device5.name = "Test Device 5 Exp 2 (Dual construct Red and Green)" -test_device5.description = "DC_R_ins_K2656022 BBa_J428104 Kit Plate 1 Well 5L" - -doc.add(neg_control_plasmid) -doc.add(pos_control_green_plasmid) -doc.add(pos_control_red_plasmid) -doc.add(test_device1) -doc.add(test_device2) -doc.add(test_device3) -doc.add(test_device4) -doc.add(test_device5) - - -activity = labop.Protocol("interlab") -activity.name = "Using the three color calibration protocol: Does the order of transcritional units influence their expression strength?" -activity.version = sbol3.TextProperty( - activity, "http://igem.org/interlab_working_group#Version", 0, 1, [], "1.0b" -) -activity.description = """In this experiment, your team will measure the fluorescence of six devices that encode two fluorescence proteins in two transcriptional units. The devices differ in the order of the transcriptional units. You will calibrate the fluorescence of these devices to the calibrant dyes and the optical density of the culture to the cell density calibrant. - -This experiment aims to assess the lab-to-lab reproducibility of the three color calibration protocol when two fluorescent proteins are expressed in the same cell. Besides this technical question, it also adresses a fundamental synthetic biology question: does the order of the transcritional units (that encode for the two different fluorescent proteins) on the devices influence their expression levels?""" - -doc.add(activity) -activity = doc.find(activity.identity) - -plasmids = [ - neg_control_plasmid, - pos_control_green_plasmid, - pos_control_red_plasmid, - test_device1, - test_device2, - test_device3, - test_device4, - test_device5, -] - -# Day 1: Transformation -culture_plates = activity.primitive_step( - "CulturePlates", - quantity=len(plasmids), - specification=labop.ContainerSpec( - "transformant_strains", - name=f"transformant strains", - queryString="cont:PetriDish", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), - growth_medium=lb_cam, -) - -transformation = activity.primitive_step( - f"Transform", - host=dh5alpha, - dna=plasmids, - selection_medium=lb_cam, - destination=culture_plates.output_pin("samples"), -) - -# Day 2: Pick colonies and culture overnight -culture_container_day1 = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_day_1", - name=f"culture (day 1)", - queryString="cont:CultureTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -overnight_culture = activity.primitive_step( - "Culture", - inoculum=transformation.output_pin("transformants"), - replicates=2, - growth_medium=lb_cam, - volume=sbol3.Measure(5, OM.millilitre), # Actually 5-10 ml in the written protocol - duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours - orbital_shake_speed=sbol3.Measure( - 220, "None" - ), # No unit for RPM or inverse minutes - temperature=sbol3.Measure(37, OM.degree_Celsius), - container=culture_container_day1.output_pin("samples"), -) - -# Day 3 culture -culture_container_day2 = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_day_2", - name=f"culture (day 2)", - queryString="cont:CultureTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - - -back_dilution = activity.primitive_step( - "Dilute", - source=culture_container_day1.output_pin("samples"), - destination=culture_container_day2.output_pin("samples"), - replicates=2, - diluent=lb_cam, - amount=sbol3.Measure(5.0, OM.millilitre), - dilution_factor=uml.LiteralInteger(value=10), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) - -# Transfer cultures to a microplate baseline measurement and outgrowth -timepoint_0hrs = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_0hr_timepoint", - name="cultures (0 hr timepoint)", - queryString="cont:MicrofugeTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -hold = activity.primitive_step( - "Hold", - location=timepoint_0hrs.output_pin("samples"), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -hold.description = "This will prevent cell growth while transferring samples." - -transfer = activity.primitive_step( - "Transfer", - source=culture_container_day2.output_pin("samples"), - destination=timepoint_0hrs.output_pin("samples"), - amount=sbol3.Measure(1, OM.milliliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) - -baseline_absorbance = activity.primitive_step( - "MeasureAbsorbance", - samples=timepoint_0hrs.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -baseline_absorbance.name = "baseline absorbance of culture (day 2)" - - -conical_tube = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "back_diluted_culture", - name=f"back-diluted culture", - queryString="cont:50mlConicalTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) -conical_tube.description = ( - "The conical tube should be opaque, amber-colored, or covered with foil." -) - -dilution = activity.primitive_step( - "DiluteToTargetOD", - source=culture_container_day2.output_pin("samples"), - destination=conical_tube.output_pin("samples"), - diluent=lb_cam, - amount=sbol3.Measure(12, OM.millilitre), - target_od=sbol3.Measure(0.02, "None"), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) # Dilute to a target OD of 0.2, opaque container -dilution.description = " Use the provided Excel sheet to calculate this dilution. Reliability of the dilution upon Abs600 measurement: should stay between 0.1-0.9" - -embedded_image = activity.primitive_step( - "EmbeddedImage", - image="/Users/bbartley/Dev/git/sd2/labop/fig1_cell_calibration.png", - caption="Figure 1: Cell Calibration", -) - - -temporary = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "back_diluted_culture_aliquots", - name="back-diluted culture aliquots", - queryString="cont:MicrofugeTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -hold = activity.primitive_step( - "Hold", - location=temporary.output_pin("samples"), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -hold.description = "This will prevent cell growth while transferring samples." - -transfer = activity.primitive_step( - "Transfer", - source=conical_tube.output_pin("samples"), - destination=temporary.output_pin("samples"), - amount=sbol3.Measure(1, OM.milliliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) - -plate1 = activity.primitive_step( - "EmptyContainer", - specification=labop.ContainerSpec( - "plate_1", - name="plate 1", - queryString="cont:Plate96Well", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - - -hold = activity.primitive_step( - "Hold", - location=plate1.output_pin("samples"), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) - - -plan = labop.SampleData( - from_samples=timepoint_0hrs.output_pin("samples"), - values=quote( - json.dumps( - { - "1": "A2:D2", - "2": "E2:H2", - "3": "A3:D3", - "4": "E3:H3", - "5": "A4:D4", - "6": "E4:H4", - "7": "A5:D5", - "8": "E5:H5", - "9": "A7:D7", - "10": "E7:H7", - "11": "A8:D8", - "12": "E8:H8", - "13": "A9:D9", - "14": "E9:H9", - "15": "A10:D10", - "16": "E10:H10", - } - ) - ), -) - - -transfer = activity.primitive_step( - "TransferByMap", - source=timepoint_0hrs.output_pin("samples"), - destination=plate1.output_pin("samples"), - amount=sbol3.Measure(100, OM.microliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), - plan=plan, -) -transfer.description = "See also the plate layout below." - -plate_blanks = activity.primitive_step( - "Transfer", - source=[lb_cam], - destination=plate1.output_pin("samples"), - coordinates="A1:H1, A10:H10, A12:H12", - temperature=sbol3.Measure(4, OM.degree_Celsius), - amount=sbol3.Measure(100, OM.microliter), -) -plate_blanks.description = "These samples are blanks." - -embedded_image = activity.primitive_step( - "EmbeddedImage", - image="/Users/bbartley/Dev/git/sd2/labop/fig2_cell_calibration.png", - caption="Figure 2: Cell Calibration", -) - - -# Possibly display map here -absorbance_plate1 = activity.primitive_step( - "MeasureAbsorbance", - samples=plate1.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -absorbance_plate1.name = "0 hr absorbance timepoint" -fluorescence_plate1 = activity.primitive_step( - "MeasureFluorescence", - samples=plate1.output_pin("samples"), - excitationWavelength=sbol3.Measure(488, OM.nanometer), - emissionWavelength=sbol3.Measure(530, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), -) -fluorescence_plate1.name = "0 hr green fluorescence timepoint" - -fluorescence_blue_plate1 = activity.primitive_step( - "MeasureFluorescence", - samples=plate1.output_pin("samples"), - excitationWavelength=sbol3.Measure(405, OM.nanometer), - emissionWavelength=sbol3.Measure(450, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(50, OM.nanometer), -) -fluorescence_blue_plate1.name = "0 hr blue fluorescence timepoint" - -fluorescence_red_plate1 = activity.primitive_step( - "MeasureFluorescence", - samples=plate1.output_pin("samples"), - excitationWavelength=sbol3.Measure(561, OM.nanometer), - emissionWavelength=sbol3.Measure(610, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(20, OM.nanometer), -) -fluorescence_red_plate1.name = "0 hr red fluorescence timepoint" - - -# Begin outgrowth -incubate = activity.primitive_step( - "Incubate", - location=conical_tube.output_pin("samples"), - duration=sbol3.Measure(6, OM.hour), - temperature=sbol3.Measure(37, OM.degree_Celsius), - shakingFrequency=sbol3.Measure(220, "None"), -) - - -# Hold on ice to inhibit cell growth -hold = activity.primitive_step( - "Hold", - location=timepoint_0hrs.output_pin("samples"), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -hold.description = ( - "This will inhibit cell growth during the subsequent pipetting steps." -) - - -# Take a 6hr timepoint measurement -timepoint_6hrs = activity.primitive_step( - "ContainerSet", - quantity=len(plasmids) * 2, - specification=labop.ContainerSpec( - "timepoint_6hr", - name=f"6hr timepoint", - queryString="cont:MicrofugeTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -plate2 = activity.primitive_step( - "EmptyContainer", - specification=labop.ContainerSpec( - "plate_2", - name="plate 2", - queryString="cont:Plate96Well", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -# Hold on ice -hold = activity.primitive_step( - "Hold", - location=timepoint_6hrs.output_pin("samples"), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -hold.description = "This will prevent cell growth while transferring samples." - -hold = activity.primitive_step( - "Hold", - location=plate2.output_pin("samples"), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) - - -transfer = activity.primitive_step( - "Transfer", - source=conical_tube.output_pin("samples"), - destination=timepoint_6hrs.output_pin("samples"), - temperature=sbol3.Measure(4, OM.degree_Celsius), - amount=sbol3.Measure(1, OM.milliliter), -) - - -plan = labop.SampleData( - from_samples=timepoint_6hrs.output_pin("samples"), - values=quote( - json.dumps( - { - "1": "A2:D2", - "2": "E2:H2", - "3": "A3:D3", - "4": "E3:H3", - "5": "A4:D4", - "6": "E4:H4", - "7": "A5:D5", - "8": "E5:H5", - "9": "A7:D7", - "10": "E7:H7", - "11": "A8:D8", - "12": "E8:H8", - "13": "A9:D9", - "14": "E9:H9", - "15": "A10:D10", - "16": "E10:H10", - } - ) - ), -) - -transfer = activity.primitive_step( - "TransferByMap", - source=timepoint_6hrs.output_pin("samples"), - destination=plate2.output_pin("samples"), - amount=sbol3.Measure(100, OM.microliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), - plan=plan, -) -transfer.description = "See the plate layout." - -# Plate the blanks -plate_blanks = activity.primitive_step( - "Transfer", - source=[lb_cam], - destination=plate2.output_pin("samples"), - coordinates="A1:H1, A10:H10, A12:H12", - temperature=sbol3.Measure(4, OM.degree_Celsius), - amount=sbol3.Measure(100, OM.microliter), -) -plate_blanks.description = "These are the blanks." - - -endpoint_absorbance_plate2 = activity.primitive_step( - "MeasureAbsorbance", - samples=plate2.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -endpoint_absorbance_plate2.name = "6 hr absorbance timepoint" - -endpoint_fluorescence_plate2 = activity.primitive_step( - "MeasureFluorescence", - samples=plate2.output_pin("samples"), - excitationWavelength=sbol3.Measure(485, OM.nanometer), - emissionWavelength=sbol3.Measure(530, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), -) -endpoint_fluorescence_plate2.name = "6 hr green fluorescence timepoint" - -endpoint_fluorescence_blue_plate2 = activity.primitive_step( - "MeasureFluorescence", - samples=plate2.output_pin("samples"), - excitationWavelength=sbol3.Measure(405, OM.nanometer), - emissionWavelength=sbol3.Measure(450, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(50, OM.nanometer), -) -endpoint_fluorescence_blue_plate2.name = "6 hr blue fluorescence timepoint" - -endpoint_fluorescence_red_plate2 = activity.primitive_step( - "MeasureFluorescence", - samples=plate2.output_pin("samples"), - excitationWavelength=sbol3.Measure(561, OM.nanometer), - emissionWavelength=sbol3.Measure(610, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(20, OM.nanometer), -) -endpoint_fluorescence_red_plate2.name = "6 hr red fluorescence timepoint" - - -activity.designate_output( - "baseline_absorbance_measurements", - "http://bioprotocols.org/labop#SampleData", - source=baseline_absorbance.output_pin("measurements"), -) -activity.designate_output( - "absorbance_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=absorbance_plate1.output_pin("measurements"), -) -activity.designate_output( - "fluorescence_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=fluorescence_plate1.output_pin("measurements"), -) -activity.designate_output( - "fluorescence_blue_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=fluorescence_blue_plate1.output_pin("measurements"), -) -activity.designate_output( - "fluorescence_red_plate1_measurements", - "http://bioprotocols.org/labop#SampleData", - source=fluorescence_red_plate1.output_pin("measurements"), -) - - -activity.designate_output( - "endpoint_absorbance_plate2_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_absorbance_plate2.output_pin("measurements"), -) -activity.designate_output( - "endpoint_fluorescence_plate2_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_fluorescence_plate2.output_pin("measurements"), -) -activity.designate_output( - "endpoint_fluorescence_blue_plate2_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_fluorescence_blue_plate2.output_pin("measurements"), -) -activity.designate_output( - "endpoint_fluorescence_red_plate2_measurements", - "http://bioprotocols.org/labop#SampleData", - source=endpoint_fluorescence_red_plate2.output_pin("measurements"), -) - -agent = sbol3.Agent("test_agent") -ee = ExecutionEngine( - specializations=[MarkdownSpecialization("test_LUDOX_markdown.md")], - failsafe=False, - sample_format="json", -) -execution = ee.execute(activity, agent, id="test_execution", parameter_values=[]) - -# Post-process the markdown to add a table that shows where each -# iGEM part is contained in the parts distribution kit -render_kit_coordinates_table(execution) - -print(execution.markdown) -execution.markdown = execution.markdown.replace("`_E. coli_", "_`E. coli`_ `") - -if REGENERATE_ARTIFACTS: - with open(filename + ".md", "w", encoding="utf-8") as f: - f.write(execution.markdown) +def generate_protocol(doc: sbol3.Document, activity: labop.Protocol) -> labop.Protocol: + # create the materials to be provisioned + dh5alpha = sbol3.Component("dh5alpha", "https://identifiers.org/taxonomy:668369") + dh5alpha.name = "_E. coli_ DH5 alpha" + doc.add(dh5alpha) + + lb_cam = sbol3.Component("lb_cam", "") + lb_cam.name = "LB Broth+chloramphenicol" + doc.add(lb_cam) + + chloramphenicol = sbol3.Component( + "chloramphenicol", "https://pubchem.ncbi.nlm.nih.gov/compound/5959" + ) + chloramphenicol.name = "chloramphenicol" + doc.add(chloramphenicol) + + neg_control_plasmid = sbol3.Component( + "neg_control_plasmid", "http://parts.igem.org/Part:BBa_J428100" + ) + neg_control_plasmid.name = "Negative control 2022" + neg_control_plasmid.description = "BBa_J428100 Kit Plate 1 Well 12M" + + pos_control_green_plasmid = sbol3.Component( + "pos_control_green_plasmid", "http://parts.igem.org/Part:BBa_J428112" + ) + pos_control_green_plasmid.name = "Positive control 2022 Green" + pos_control_green_plasmid.description = ( + "3_Colors_ins_K2656022 BBa_J428112 Kit Plate 1 Well 14C" + ) + + pos_control_red_plasmid = sbol3.Component( + "pos_control_red_plasmid", "http://parts.igem.org/Part:BBa_J428101" + ) + pos_control_red_plasmid.name = "Positive control red (mCherry) Exp 2" + pos_control_red_plasmid.description = "BBa_J428101 Kit Plate 1 Well 12I" + + test_device1 = sbol3.Component( + "test_device1", "http://parts.igem.org/Part:BBa_J428106" + ) + test_device1.name = "Test Device 1 Exp 2 (Dual construct Green and Blue)" + test_device1.description = "BBa_J428106 Kit Plate 1 Well 12G" + + test_device2 = sbol3.Component( + "test_device2", "http://parts.igem.org/Part:BBa_J428107" + ) + test_device2.name = "Test Device 2 Exp 2 (Dual construct Green and Red)" + test_device2.description = "BBa_J428107 Kit Plate 1 Well 3L" + + test_device3 = sbol3.Component( + "test_device3", "http://parts.igem.org/Part:BBa_J428105" + ) + test_device3.name = "Test Device 3 Exp 2 (Dual construct Red and Blue)" + test_device3.description = "BBa_J428105 Kit Plate 1 Well 5J" + + test_device4 = sbol3.Component( + "test_device4", "http://parts.igem.org/Part:BBa_J428108" + ) + test_device4.name = "Test Device 4 Exp 2 (Dual construct Blue and Red)" + test_device4.description = "BBa_J428108 Kit Plate 1 Well 14E" + + test_device5 = sbol3.Component( + "test_device5", "http://parts.igem.org/Part:BBa_J428104" + ) + test_device5.name = "Test Device 5 Exp 2 (Dual construct Red and Green)" + test_device5.description = "DC_R_ins_K2656022 BBa_J428104 Kit Plate 1 Well 5L" + + doc.add(neg_control_plasmid) + doc.add(pos_control_green_plasmid) + doc.add(pos_control_red_plasmid) + doc.add(test_device1) + doc.add(test_device2) + doc.add(test_device3) + doc.add(test_device4) + doc.add(test_device5) + + activity.name = "Using the three color calibration protocol: Does the order of transcritional units influence their expression strength?" + activity.version = sbol3.TextProperty( + activity, + "http://igem.org/interlab_working_group#Version", + 0, + 1, + [], + "1.0b", + ) + activity.description = """In this experiment, your team will measure the fluorescence of six devices that encode two fluorescence proteins in two transcriptional units. The devices differ in the order of the transcriptional units. You will calibrate the fluorescence of these devices to the calibrant dyes and the optical density of the culture to the cell density calibrant. + + This experiment aims to assess the lab-to-lab reproducibility of the three color calibration protocol when two fluorescent proteins are expressed in the same cell. Besides this technical question, it also adresses a fundamental synthetic biology question: does the order of the transcritional units (that encode for the two different fluorescent proteins) on the devices influence their expression levels?""" + + activity = doc.find(activity.identity) + + plasmids = [ + neg_control_plasmid, + pos_control_green_plasmid, + pos_control_red_plasmid, + test_device1, + test_device2, + test_device3, + test_device4, + test_device5, + ] + + # Day 1: Transformation + culture_plates = activity.primitive_step( + "CulturePlates", + quantity=len(plasmids), + specification=labop.ContainerSpec( + "transformant_strains", + name=f"transformant strains", + queryString="cont:PetriDish", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + growth_medium=lb_cam, + ) + + transformation = activity.primitive_step( + f"Transform", + host=dh5alpha, + dna=plasmids, + selection_medium=lb_cam, + destination=culture_plates.output_pin("samples"), + ) + + # Day 2: Pick colonies and culture overnight + culture_container_day1 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_day_1", + name=f"culture (day 1)", + queryString="cont:CultureTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + overnight_culture = activity.primitive_step( + "Culture", + inoculum=transformation.output_pin("transformants"), + replicates=2, + growth_medium=lb_cam, + volume=sbol3.Measure( + 5, OM.millilitre + ), # Actually 5-10 ml in the written protocol + duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours + orbital_shake_speed=sbol3.Measure( + 220, "None" + ), # No unit for RPM or inverse minutes + temperature=sbol3.Measure(37, OM.degree_Celsius), + container=culture_container_day1.output_pin("samples"), + ) + + # Day 3 culture + culture_container_day2 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_day_2", + name=f"culture (day 2)", + queryString="cont:CultureTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + back_dilution = activity.primitive_step( + "Dilute", + source=culture_container_day1.output_pin("samples"), + destination=culture_container_day2.output_pin("samples"), + replicates=2, + diluent=lb_cam, + amount=sbol3.Measure(5.0, OM.millilitre), + dilution_factor=uml.LiteralInteger(value=10), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + + # Transfer cultures to a microplate baseline measurement and outgrowth + timepoint_0hrs = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_0hr_timepoint", + name="cultures (0 hr timepoint)", + queryString="cont:MicrofugeTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + hold = activity.primitive_step( + "Hold", + location=timepoint_0hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + hold.description = "This will prevent cell growth while transferring samples." + + transfer = activity.primitive_step( + "Transfer", + source=culture_container_day2.output_pin("samples"), + destination=timepoint_0hrs.output_pin("samples"), + amount=sbol3.Measure(1, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + + baseline_absorbance = activity.primitive_step( + "MeasureAbsorbance", + samples=timepoint_0hrs.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + baseline_absorbance.name = "baseline absorbance of culture (day 2)" + + conical_tube = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "back_diluted_culture", + name=f"back-diluted culture", + queryString="cont:50mlConicalTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + conical_tube.description = ( + "The conical tube should be opaque, amber-colored, or covered with foil." + ) + + dilution = activity.primitive_step( + "DiluteToTargetOD", + source=culture_container_day2.output_pin("samples"), + destination=conical_tube.output_pin("samples"), + diluent=lb_cam, + amount=sbol3.Measure(12, OM.millilitre), + target_od=sbol3.Measure(0.02, "None"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) # Dilute to a target OD of 0.2, opaque container + dilution.description = " Use the provided Excel sheet to calculate this dilution. Reliability of the dilution upon Abs600 measurement: should stay between 0.1-0.9" + + embedded_image = activity.primitive_step( + "EmbeddedImage", + image="/Users/bbartley/Dev/git/sd2/labop/fig1_cell_calibration.png", + caption="Figure 1: Cell Calibration", + ) + + temporary = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "back_diluted_culture_aliquots", + name="back-diluted culture aliquots", + queryString="cont:MicrofugeTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + hold = activity.primitive_step( + "Hold", + location=temporary.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + hold.description = "This will prevent cell growth while transferring samples." + + transfer = activity.primitive_step( + "Transfer", + source=conical_tube.output_pin("samples"), + destination=temporary.output_pin("samples"), + amount=sbol3.Measure(1, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + + plate1 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + "plate_1", + name="plate 1", + queryString="cont:Plate96Well", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + hold = activity.primitive_step( + "Hold", + location=plate1.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + + plan = labop.SampleData( + from_samples=timepoint_0hrs.output_pin("samples"), + values=quote( + json.dumps( + { + "1": "A2:D2", + "2": "E2:H2", + "3": "A3:D3", + "4": "E3:H3", + "5": "A4:D4", + "6": "E4:H4", + "7": "A5:D5", + "8": "E5:H5", + "9": "A7:D7", + "10": "E7:H7", + "11": "A8:D8", + "12": "E8:H8", + "13": "A9:D9", + "14": "E9:H9", + "15": "A10:D10", + "16": "E10:H10", + } + ) + ), + ) + + transfer = activity.primitive_step( + "TransferByMap", + source=timepoint_0hrs.output_pin("samples"), + destination=plate1.output_pin("samples"), + amount=sbol3.Measure(100, OM.microliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + plan=plan, + ) + transfer.description = "See also the plate layout below." + + plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate1.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(100, OM.microliter), + ) + plate_blanks.description = "These samples are blanks." + + embedded_image = activity.primitive_step( + "EmbeddedImage", + image="/Users/bbartley/Dev/git/sd2/labop/fig2_cell_calibration.png", + caption="Figure 2: Cell Calibration", + ) + + # Possibly display map here + absorbance_plate1 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate1.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + absorbance_plate1.name = "0 hr absorbance timepoint" + fluorescence_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(488, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), + ) + fluorescence_plate1.name = "0 hr green fluorescence timepoint" + + fluorescence_blue_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(405, OM.nanometer), + emissionWavelength=sbol3.Measure(450, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(50, OM.nanometer), + ) + fluorescence_blue_plate1.name = "0 hr blue fluorescence timepoint" + + fluorescence_red_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(561, OM.nanometer), + emissionWavelength=sbol3.Measure(610, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(20, OM.nanometer), + ) + fluorescence_red_plate1.name = "0 hr red fluorescence timepoint" + + # Begin outgrowth + incubate = activity.primitive_step( + "Incubate", + location=conical_tube.output_pin("samples"), + duration=sbol3.Measure(6, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, "None"), + ) + + # Hold on ice to inhibit cell growth + hold = activity.primitive_step( + "Hold", + location=timepoint_0hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + hold.description = ( + "This will inhibit cell growth during the subsequent pipetting steps." + ) + + # Take a 6hr timepoint measurement + timepoint_6hrs = activity.primitive_step( + "ContainerSet", + quantity=len(plasmids) * 2, + specification=labop.ContainerSpec( + "timepoint_6hr", + name=f"6hr timepoint", + queryString="cont:MicrofugeTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + plate2 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + "plate_2", + name="plate 2", + queryString="cont:Plate96Well", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + # Hold on ice + hold = activity.primitive_step( + "Hold", + location=timepoint_6hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + hold.description = "This will prevent cell growth while transferring samples." + + hold = activity.primitive_step( + "Hold", + location=plate2.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + + transfer = activity.primitive_step( + "Transfer", + source=conical_tube.output_pin("samples"), + destination=timepoint_6hrs.output_pin("samples"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(1, OM.milliliter), + ) + + plan = labop.SampleData( + from_samples=timepoint_6hrs.output_pin("samples"), + values=quote( + json.dumps( + { + "1": "A2:D2", + "2": "E2:H2", + "3": "A3:D3", + "4": "E3:H3", + "5": "A4:D4", + "6": "E4:H4", + "7": "A5:D5", + "8": "E5:H5", + "9": "A7:D7", + "10": "E7:H7", + "11": "A8:D8", + "12": "E8:H8", + "13": "A9:D9", + "14": "E9:H9", + "15": "A10:D10", + "16": "E10:H10", + } + ) + ), + ) + + transfer = activity.primitive_step( + "TransferByMap", + source=timepoint_6hrs.output_pin("samples"), + destination=plate2.output_pin("samples"), + amount=sbol3.Measure(100, OM.microliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + plan=plan, + ) + transfer.description = "See the plate layout." + + # Plate the blanks + plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate2.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(100, OM.microliter), + ) + plate_blanks.description = "These are the blanks." + + endpoint_absorbance_plate2 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate2.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + endpoint_absorbance_plate2.name = "6 hr absorbance timepoint" + + endpoint_fluorescence_plate2 = activity.primitive_step( + "MeasureFluorescence", + samples=plate2.output_pin("samples"), + excitationWavelength=sbol3.Measure(485, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), + ) + endpoint_fluorescence_plate2.name = "6 hr green fluorescence timepoint" + + endpoint_fluorescence_blue_plate2 = activity.primitive_step( + "MeasureFluorescence", + samples=plate2.output_pin("samples"), + excitationWavelength=sbol3.Measure(405, OM.nanometer), + emissionWavelength=sbol3.Measure(450, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(50, OM.nanometer), + ) + endpoint_fluorescence_blue_plate2.name = "6 hr blue fluorescence timepoint" + + endpoint_fluorescence_red_plate2 = activity.primitive_step( + "MeasureFluorescence", + samples=plate2.output_pin("samples"), + excitationWavelength=sbol3.Measure(561, OM.nanometer), + emissionWavelength=sbol3.Measure(610, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(20, OM.nanometer), + ) + endpoint_fluorescence_red_plate2.name = "6 hr red fluorescence timepoint" + + activity.designate_output( + "baseline_absorbance_measurements", + "http://bioprotocols.org/labop#SampleData", + source=baseline_absorbance.output_pin("measurements"), + ) + activity.designate_output( + "absorbance_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_plate1.output_pin("measurements"), + ) + activity.designate_output( + "fluorescence_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_plate1.output_pin("measurements"), + ) + activity.designate_output( + "fluorescence_blue_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_blue_plate1.output_pin("measurements"), + ) + activity.designate_output( + "fluorescence_red_plate1_measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_red_plate1.output_pin("measurements"), + ) + + activity.designate_output( + "endpoint_absorbance_plate2_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_absorbance_plate2.output_pin("measurements"), + ) + activity.designate_output( + "endpoint_fluorescence_plate2_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_fluorescence_plate2.output_pin("measurements"), + ) + activity.designate_output( + "endpoint_fluorescence_blue_plate2_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_fluorescence_blue_plate2.output_pin("measurements"), + ) + activity.designate_output( + "endpoint_fluorescence_red_plate2_measurements", + "http://bioprotocols.org/labop#SampleData", + source=endpoint_fluorescence_red_plate2.output_pin("measurements"), + ) + + return activity + + +class InterlabCustomSpecialization(labop.execution.harness.ProtocolSpecialization): + def generate_artifact(self, harness: "ProtocolHarness"): + execution = self.specialization.execution + + # Post-process the markdown to add a table that shows where each + # iGEM part is contained in the parts distribution kit + render_kit_coordinates_table(execution) + + print(execution.markdown) + execution.markdown = execution.markdown.replace("`_E. coli_", "_`E. coli`_ `") + super().generate_artifact(harness) + + +if __name__ == "__main__": + harness = labop.execution.harness.ProtocolHarness( + protocol_name="interlab", + clean_output=True, + base_dir=os.path.join(os.path.dirname(__file__), "out", "out_igem_example2"), + entry_point=generate_protocol, + agent="test_agent", + libraries=[ + "liquid_handling", + "plate_handling", + "spectrophotometry", + "sample_arrays", + "culturing", + ], + artifacts=[ + InterlabCustomSpecialization( + specialization=labop_convert.MarkdownSpecialization( + "test_LUDOX_markdown.md" + ) + ) + ], + execution_kwargs={ + "failsafe": False, + "sample_format": "json", + "track_samples": False, + }, + execution_id="test_execution", + ) + harness.run() diff --git a/examples/protocols/iGEM/interlab-exp2_MI.py b/examples/protocols/iGEM/interlab-exp2_MI.py index cb9f1d94..3888de8e 100644 --- a/examples/protocols/iGEM/interlab-exp2_MI.py +++ b/examples/protocols/iGEM/interlab-exp2_MI.py @@ -10,7 +10,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert.markdown.markdown_specialization import MarkdownSpecialization filename = "".join(__file__.split(".py")[0].split("/")[-1:]) diff --git a/examples/protocols/iGEM/interlab-exp2_from1.py b/examples/protocols/iGEM/interlab-exp2_from1.py index 91118127..f72982c8 100644 --- a/examples/protocols/iGEM/interlab-exp2_from1.py +++ b/examples/protocols/iGEM/interlab-exp2_from1.py @@ -10,7 +10,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert.markdown.markdown_specialization import MarkdownSpecialization filename = "".join(__file__.split(".py")[0].split("/")[-1:]) diff --git a/examples/protocols/iGEM/interlab-exp3_challenge.py b/examples/protocols/iGEM/interlab-exp3_challenge.py index 8306b504..c0f8401f 100644 --- a/examples/protocols/iGEM/interlab-exp3_challenge.py +++ b/examples/protocols/iGEM/interlab-exp3_challenge.py @@ -2,16 +2,15 @@ http://2018.igem.org/wiki/images/0/09/2018_InterLab_Plate_Reader_Protocol.pdf """ import json -import sys +import os from urllib.parse import quote import sbol3 from tyto import OM import labop +import labop_convert import uml -from labop.execution_engine import ExecutionEngine -from labop_convert import MarkdownSpecialization def render_kit_coordinates_table(ex: labop.ProtocolExecution): @@ -47,660 +46,691 @@ def render_kit_coordinates_table(ex: labop.ProtocolExecution): ex.markdown = ex.markdown[:insert_index] + table + ex.markdown[insert_index:] -if "unittest" in sys.modules: - REGENERATE_ARTIFACTS = False -else: - REGENERATE_ARTIFACTS = True - -filename = "".join(__file__.split(".py")[0].split("/")[-1:]) - -doc = sbol3.Document() -sbol3.set_namespace("http://igem.org/engineering/") - -############################################# -# Import the primitive libraries -print("Importing libraries") -labop.import_library("liquid_handling") -print("... Imported liquid handling") -labop.import_library("plate_handling") -# print('... Imported plate handling') -labop.import_library("spectrophotometry") -print("... Imported spectrophotometry") -labop.import_library("sample_arrays") -print("... Imported sample arrays") -labop.import_library("culturing") -############################################# +def generate_protocol(doc: sbol3.Document, activity: labop.Protocol) -> labop.Protocol: + # Cells and test circuits + dh5alpha = sbol3.Component("dh5alpha", "https://identifiers.org/taxonomy:668369") + dh5alpha.name = "_E. coli_ DH5 alpha competent cells" + doc.add(dh5alpha) + neg_control_plasmid = sbol3.Component( + "neg_control_plasmid", "http://parts.igem.org/Part:BBa_J428100" + ) + neg_control_plasmid.name = "Negative control" + neg_control_plasmid.description = "BBa_J428100 Kit Plate 1 Well 12M" -# Cells and test circuits -dh5alpha = sbol3.Component("dh5alpha", "https://identifiers.org/taxonomy:668369") -dh5alpha.name = "_E. coli_ DH5 alpha competent cells" -doc.add(dh5alpha) - -neg_control_plasmid = sbol3.Component( - "neg_control_plasmid", "http://parts.igem.org/Part:BBa_J428100" -) -neg_control_plasmid.name = "Negative control" -neg_control_plasmid.description = "BBa_J428100 Kit Plate 1 Well 12M" - -pos_control_plasmid = sbol3.Component( - "pos_control_plasmid", "http://parts.igem.org/Part:BBa_I20270" -) -pos_control_plasmid.name = "Positive control (I20270)" -pos_control_plasmid.description = "BBa_I20270 Kit Plate 1 Well 1A" - -test_device1 = sbol3.Component("test_device1", "http://parts.igem.org/Part:BBa_J364000") -test_device1.name = "Test Device 1 (J364000)" -test_device1.description = "BBa_J364000 Kit Plate 1 Well 1C" - -test_device2 = sbol3.Component("test_device2", "http://parts.igem.org/Part:BBa_J364001") -test_device2.name = "Test Device 2 (J364001)" -test_device2.description = "BBa_J364001 Kit Plate 1 Well 1E" - -test_device3 = sbol3.Component("test_device3", "http://parts.igem.org/Part:BBa_J364002") -test_device3.name = "Test Device 3 (J364002)" -test_device3.description = "BBa_J364002 Kit Plate 1 Well 1G" - -test_device4 = sbol3.Component("test_device4", "http://parts.igem.org/Part:BBa_J364007") -test_device4.name = "Test Device 4 (J364007)" -test_device4.description = "BBa_J364007 Kit Plate 1 Well 1I" - -test_device5 = sbol3.Component("test_device5", "http://parts.igem.org/Part:BBa_J364008") -test_device5.name = "Test Device 5 (J364008)" -test_device5.description = "BBa_J364008 Kit Plate 1 Well 1K" - -test_device6 = sbol3.Component("test_device6", "http://parts.igem.org/Part:BBa_J364009") -test_device6.name = "Test Device 6 (J364009)" -test_device6.description = "BBa_J364009 Kit Plate 1 Well 1M" - -doc.add(neg_control_plasmid) -doc.add(pos_control_plasmid) -doc.add(test_device1) -doc.add(test_device2) -doc.add(test_device3) -doc.add(test_device4) -doc.add(test_device5) -doc.add(test_device6) - -# Other reagents -lb_cam = sbol3.Component("lb_cam", "") -lb_cam.name = "LB Broth + Chloramphenicol (34 ug/mL)" - -lb_agar_cam = sbol3.Component("lb_agar_cam", "") -lb_agar_cam.name = "LB Agar + Chloramphenicol (34 ug/mL)" - -chloramphenicol = sbol3.Component( - "chloramphenicol", "https://pubchem.ncbi.nlm.nih.gov/compound/5959" -) -chloramphenicol.name = "Chloramphenicol stock solution (34 mg/mL)" - -ice = sbol3.Component("ice", "") -ice.name = "Ice" - -doc.add(lb_cam) -doc.add(lb_agar_cam) -doc.add(chloramphenicol) -doc.add(ice) - -# Instruments and laboratory equipment -# TODO: instruments should be represented by sbol3.Agent -plate_reader = sbol3.Component("plate_reader", "") -plate_reader.name = "Plate reader" - -shaking_incubator = sbol3.Component("shaking_incubator", "") -shaking_incubator.name = "Shaking incubator" - -doc.add(plate_reader) -doc.add(shaking_incubator) - - -activity = labop.Protocol("interlab") -activity.name = "Experiment 3 - Cell measurement protocol Challenge" -activity.version = sbol3.TextProperty( - activity, "http://igem.org/interlab_working_group#Version", 0, 1, [], "1.2b" -) -activity.description = """This year we plan to test protocols that will eventually be automated. For this reason, we will use 96-well plates instead of test tubes for culturing. Consequently, we want to evaluate how the performance of our plate culturing protocol compares to culturing in test tubes (e.g. 10 mL falcon tube) on a global scale. This version of the interlab protocol involves 2 hr. time interval measurements and incubation inside a microplate reader/incubator. - -At the end of the experiment, you will have four plates to be measured. You will measure both fluorescence and absorbance in each plate. - -Before performing the cell measurements, you need to perform all the calibration measurements. Please do not proceed unless you have completed the calibration protocol. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Engineering Committee (engineering [at] igem [dot] org) to discuss your situation. - -For all below indicated cell measurements, you must use the same type of plates and the same volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same type of plates, volumes, and settings, the measurements will not be valid. - -Protocol summary: UPDATE You will transform the eight devices listed in Table 1 into E. coli K-12 DH5-alpha cells. The next day you will pick two colonies from each transformation (16 total) and use them to inoculate 5 mL overnight cultures (this step is still in tubes). Each of these 16 overnight cultures will be used to inoculate four wells in a 96-well plate (200 microliter each, 4 replicates) and one test tube (12 mL). You will measure how fluorescence and optical density develops over 6 hours by taking measurements at time point 0 hour and at time point 6 hours. Follow the protocol below and the visual instructions in Figure 1 and Figure 2.""" - -doc.add(activity) -activity = doc.find(activity.identity) - -plasmids = [ - neg_control_plasmid, - pos_control_plasmid, - test_device1, - test_device2, - test_device3, - test_device4, - test_device5, - test_device6, -] - -# Day 1: Transformation -culture_plates = activity.primitive_step( - "CulturePlates", - quantity=len(plasmids), - specification=labop.ContainerSpec( - "transformant_strains", - name=f"transformant strains", - queryString="cont:PetriDish", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), - growth_medium=lb_agar_cam, -) - -transformation = activity.primitive_step( - f"Transform", - host=dh5alpha, - dna=plasmids, - selection_medium=lb_agar_cam, - destination=culture_plates.output_pin("samples"), -) -transformation.description = "Incubate overnight (for 16 hour) at 37.0 degree Celsius." - -# Day 2: Pick colonies and culture overnight -culture_container_day1 = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_day_1", - name=f"culture (day 1)", - queryString="cont:CultureTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -pick_colonies = activity.primitive_step( - "PickColonies", - colonies=transformation.output_pin("transformants"), - quantity=2 * len(plasmids), - replicates=2, -) - -overnight_culture = activity.primitive_step( - "Culture", - inoculum=pick_colonies.output_pin("samples"), - replicates=2, - growth_medium=lb_cam, - volume=sbol3.Measure(5, OM.millilitre), # Actually 5-10 ml in the written protocol - duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours - orbital_shake_speed=sbol3.Measure( - 220, "None" - ), # No unit for RPM or inverse minutes - temperature=sbol3.Measure(37, OM.degree_Celsius), - container=culture_container_day1.output_pin("samples"), -) - -# Day 3 culture -culture_container_day2 = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_day_2", - name=f"culture (day 2)", - queryString="cont:CultureTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - - -back_dilution = activity.primitive_step( - "Dilute", - source=culture_container_day1.output_pin("samples"), - destination=culture_container_day2.output_pin("samples"), - replicates=2, - diluent=lb_cam, - amount=sbol3.Measure(5.0, OM.millilitre), - dilution_factor=uml.LiteralInteger(value=10), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -back_dilution.description = "(This can be also performed on ice)." - - -# Transfer cultures to a microplate baseline measurement and outgrowth -timepoint_0hrs = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "culture_0hr_timepoint", - name="cultures (0 hr timepoint)", - queryString="cont:MicrofugeTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -hold = activity.primitive_step( - "HoldOnIce", location=timepoint_0hrs.output_pin("samples") -) -hold.description = "This will prevent cell growth while transferring samples." - -transfer = activity.primitive_step( - "Transfer", - source=culture_container_day2.output_pin("samples"), - destination=timepoint_0hrs.output_pin("samples"), - amount=sbol3.Measure(1, OM.milliliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) -transfer.description = "(This can be also performed on Ice)." - -# Abs measurement step 11 -baseline_absorbance = activity.primitive_step( - "MeasureAbsorbance", - samples=timepoint_0hrs.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -baseline_absorbance.name = "baseline absorbance of culture (day 2)" - -# Every measurement primitive produces an output pin called `measurements` that must be designated as a protocol output -activity.designate_output( - "baseline_absorbance_measurements", - "http://bioprotocols.org/labop#SampleData", - source=baseline_absorbance.output_pin("measurements"), -) - - -conical_tube = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "back_diluted_culture", - name=f"back-diluted culture", - queryString="cont:50mlConicalTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) -conical_tube.description = ( - "The conical tube should be opaque, amber-colored, or covered with foil." -) - -dilution = activity.primitive_step( - "DiluteToTargetOD", - source=culture_container_day2.output_pin("samples"), - destination=conical_tube.output_pin("samples"), - diluent=lb_cam, - amount=sbol3.Measure(40, OM.millilitre), - target_od=sbol3.Measure(0.02, "None"), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) # Dilute to a target OD of 0.2, opaque container -dilution.description = f"(This can be also performed on Ice)." - -embedded_image = activity.primitive_step( - "EmbeddedImage", - image="fig1_challenge_protocol.png", - caption="Fig 1: Visual representation of protocol", -) - - -### Aliquot subcultures for timepoint samples -spec = labop.ContainerSpec( - "tube1", - name=f"Tube 1", - queryString="cont:50mlConicalTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, -) -timepoint_subculture1 = activity.primitive_step( - "ContainerSet", quantity=2 * len(plasmids), specification=spec -) -timepoint_subculture1.description = ( - "The conical tubes should be opaque, amber-colored, or covered with foil." -) - -timepoint_subculture2 = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "tube2", - name=f"Tube 2", - queryString="cont:50mlConicalTube", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) -timepoint_subculture2.description = ( - "The conical tubes should be opaque, amber-colored, or covered with foil." -) - -timepoint_subculture3 = activity.primitive_step( - "ContainerSet", - quantity=2 * len(plasmids), - specification=labop.ContainerSpec( - "tube3", - name=f"Tube 3", + pos_control_plasmid = sbol3.Component( + "pos_control_plasmid", "http://parts.igem.org/Part:BBa_I20270" + ) + pos_control_plasmid.name = "Positive control (I20270)" + pos_control_plasmid.description = "BBa_I20270 Kit Plate 1 Well 1A" + + test_device1 = sbol3.Component( + "test_device1", "http://parts.igem.org/Part:BBa_J364000" + ) + test_device1.name = "Test Device 1 (J364000)" + test_device1.description = "BBa_J364000 Kit Plate 1 Well 1C" + + test_device2 = sbol3.Component( + "test_device2", "http://parts.igem.org/Part:BBa_J364001" + ) + test_device2.name = "Test Device 2 (J364001)" + test_device2.description = "BBa_J364001 Kit Plate 1 Well 1E" + + test_device3 = sbol3.Component( + "test_device3", "http://parts.igem.org/Part:BBa_J364002" + ) + test_device3.name = "Test Device 3 (J364002)" + test_device3.description = "BBa_J364002 Kit Plate 1 Well 1G" + + test_device4 = sbol3.Component( + "test_device4", "http://parts.igem.org/Part:BBa_J364007" + ) + test_device4.name = "Test Device 4 (J364007)" + test_device4.description = "BBa_J364007 Kit Plate 1 Well 1I" + + test_device5 = sbol3.Component( + "test_device5", "http://parts.igem.org/Part:BBa_J364008" + ) + test_device5.name = "Test Device 5 (J364008)" + test_device5.description = "BBa_J364008 Kit Plate 1 Well 1K" + + test_device6 = sbol3.Component( + "test_device6", "http://parts.igem.org/Part:BBa_J364009" + ) + test_device6.name = "Test Device 6 (J364009)" + test_device6.description = "BBa_J364009 Kit Plate 1 Well 1M" + + doc.add(neg_control_plasmid) + doc.add(pos_control_plasmid) + doc.add(test_device1) + doc.add(test_device2) + doc.add(test_device3) + doc.add(test_device4) + doc.add(test_device5) + doc.add(test_device6) + + # Other reagents + lb_cam = sbol3.Component("lb_cam", "") + lb_cam.name = "LB Broth + Chloramphenicol (34 ug/mL)" + + lb_agar_cam = sbol3.Component("lb_agar_cam", "") + lb_agar_cam.name = "LB Agar + Chloramphenicol (34 ug/mL)" + + chloramphenicol = sbol3.Component( + "chloramphenicol", "https://pubchem.ncbi.nlm.nih.gov/compound/5959" + ) + chloramphenicol.name = "Chloramphenicol stock solution (34 mg/mL)" + + ice = sbol3.Component("ice", "") + ice.name = "Ice" + + doc.add(lb_cam) + doc.add(lb_agar_cam) + doc.add(chloramphenicol) + doc.add(ice) + + # Instruments and laboratory equipment + # TODO: instruments should be represented by sbol3.Agent + plate_reader = sbol3.Component("plate_reader", "") + plate_reader.name = "Plate reader" + + shaking_incubator = sbol3.Component("shaking_incubator", "") + shaking_incubator.name = "Shaking incubator" + + doc.add(plate_reader) + doc.add(shaking_incubator) + + activity.name = "Experiment 3 - Cell measurement protocol Challenge" + activity.version = sbol3.TextProperty( + activity, + "http://igem.org/interlab_working_group#Version", + 0, + 1, + [], + "1.2b", + ) + activity.description = """This year we plan to test protocols that will eventually be automated. For this reason, we will use 96-well plates instead of test tubes for culturing. Consequently, we want to evaluate how the performance of our plate culturing protocol compares to culturing in test tubes (e.g. 10 mL falcon tube) on a global scale. This version of the interlab protocol involves 2 hr. time interval measurements and incubation inside a microplate reader/incubator. + + At the end of the experiment, you will have four plates to be measured. You will measure both fluorescence and absorbance in each plate. + + Before performing the cell measurements, you need to perform all the calibration measurements. Please do not proceed unless you have completed the calibration protocol. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Engineering Committee (engineering [at] igem [dot] org) to discuss your situation. + + For all below indicated cell measurements, you must use the same type of plates and the same volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same type of plates, volumes, and settings, the measurements will not be valid. + + Protocol summary: UPDATE You will transform the eight devices listed in Table 1 into E. coli K-12 DH5-alpha cells. The next day you will pick two colonies from each transformation (16 total) and use them to inoculate 5 mL overnight cultures (this step is still in tubes). Each of these 16 overnight cultures will be used to inoculate four wells in a 96-well plate (200 microliter each, 4 replicates) and one test tube (12 mL). You will measure how fluorescence and optical density develops over 6 hours by taking measurements at time point 0 hour and at time point 6 hours. Follow the protocol below and the visual instructions in Figure 1 and Figure 2.""" + + activity = doc.find(activity.identity) + + plasmids = [ + neg_control_plasmid, + pos_control_plasmid, + test_device1, + test_device2, + test_device3, + test_device4, + test_device5, + test_device6, + ] + + # Day 1: Transformation + culture_plates = activity.primitive_step( + "CulturePlates", + quantity=len(plasmids), + specification=labop.ContainerSpec( + "transformant_strains", + name=f"transformant strains", + queryString="cont:PetriDish", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + growth_medium=lb_agar_cam, + ) + + transformation = activity.primitive_step( + f"Transform", + host=dh5alpha, + dna=plasmids, + selection_medium=lb_agar_cam, + destination=culture_plates.output_pin("samples"), + ) + transformation.description = ( + "Incubate overnight (for 16 hour) at 37.0 degree Celsius." + ) + + # Day 2: Pick colonies and culture overnight + culture_container_day1 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_day_1", + name=f"culture (day 1)", + queryString="cont:CultureTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + pick_colonies = activity.primitive_step( + "PickColonies", + colonies=transformation.output_pin("transformants"), + quantity=2 * len(plasmids), + replicates=2, + ) + + overnight_culture = activity.primitive_step( + "Culture", + inoculum=pick_colonies.output_pin("samples"), + replicates=2, + growth_medium=lb_cam, + volume=sbol3.Measure( + 5, OM.millilitre + ), # Actually 5-10 ml in the written protocol + duration=sbol3.Measure(16, OM.hour), # Actually 16-18 hours + orbital_shake_speed=sbol3.Measure( + 220, "None" + ), # No unit for RPM or inverse minutes + temperature=sbol3.Measure(37, OM.degree_Celsius), + container=culture_container_day1.output_pin("samples"), + ) + + # Day 3 culture + culture_container_day2 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_day_2", + name=f"culture (day 2)", + queryString="cont:CultureTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + back_dilution = activity.primitive_step( + "Dilute", + source=culture_container_day1.output_pin("samples"), + destination=culture_container_day2.output_pin("samples"), + replicates=2, + diluent=lb_cam, + amount=sbol3.Measure(5.0, OM.millilitre), + dilution_factor=uml.LiteralInteger(value=10), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + back_dilution.description = "(This can be also performed on ice)." + + # Transfer cultures to a microplate baseline measurement and outgrowth + timepoint_0hrs = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "culture_0hr_timepoint", + name="cultures (0 hr timepoint)", + queryString="cont:MicrofugeTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + hold = activity.primitive_step( + "HoldOnIce", location=timepoint_0hrs.output_pin("samples") + ) + hold.description = "This will prevent cell growth while transferring samples." + + transfer = activity.primitive_step( + "Transfer", + source=culture_container_day2.output_pin("samples"), + destination=timepoint_0hrs.output_pin("samples"), + amount=sbol3.Measure(1, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + transfer.description = "(This can be also performed on Ice)." + + # Abs measurement step 11 + baseline_absorbance = activity.primitive_step( + "MeasureAbsorbance", + samples=timepoint_0hrs.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + baseline_absorbance.name = "baseline absorbance of culture (day 2)" + + # Every measurement primitive produces an output pin called `measurements` that must be designated as a protocol output + activity.designate_output( + "baseline_absorbance_measurements", + "http://bioprotocols.org/labop#SampleData", + source=baseline_absorbance.output_pin("measurements"), + ) + + conical_tube = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "back_diluted_culture", + name=f"back-diluted culture", + queryString="cont:50mlConicalTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + conical_tube.description = ( + "The conical tube should be opaque, amber-colored, or covered with foil." + ) + + dilution = activity.primitive_step( + "DiluteToTargetOD", + source=culture_container_day2.output_pin("samples"), + destination=conical_tube.output_pin("samples"), + diluent=lb_cam, + amount=sbol3.Measure(40, OM.millilitre), + target_od=sbol3.Measure(0.02, "None"), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) # Dilute to a target OD of 0.2, opaque container + dilution.description = f"(This can be also performed on Ice)." + + embedded_image = activity.primitive_step( + "EmbeddedImage", + image="fig1_challenge_protocol.png", + caption="Fig 1: Visual representation of protocol", + ) + + ### Aliquot subcultures for timepoint samples + spec = labop.ContainerSpec( + "tube1", + name=f"Tube 1", queryString="cont:50mlConicalTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) -timepoint_subculture3.description = ( - "The conical tubes should be opaque, amber-colored, or covered with foil." -) - -transfer = activity.primitive_step( - "Transfer", - source=conical_tube.output_pin("samples"), - destination=timepoint_subculture1.output_pin("samples"), - amount=sbol3.Measure(12, OM.milliliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) - -transfer = activity.primitive_step( - "Transfer", - source=conical_tube.output_pin("samples"), - destination=timepoint_subculture2.output_pin("samples"), - amount=sbol3.Measure(12, OM.milliliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) - -transfer = activity.primitive_step( - "Transfer", - source=conical_tube.output_pin("samples"), - destination=timepoint_subculture3.output_pin("samples"), - amount=sbol3.Measure(12, OM.milliliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), -) - -plate1 = activity.primitive_step( - "EmptyContainer", - specification=labop.ContainerSpec( - "plate1", - name="plate 1", - queryString="cont:Plate96Well", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -hold = activity.primitive_step("HoldOnIce", location=plate1.output_pin("samples")) - -plan = labop.SampleData( - from_samples=conical_tube.output_pin("samples"), - values=quote( - json.dumps( - { - "1": "A2:D2", - "2": "E2:H2", - "3": "A3:D3", - "4": "E3:H3", - "5": "A4:D4", - "6": "E4:H4", - "7": "A5:D5", - "8": "E5:H5", - "9": "A7:D7", - "10": "E7:H7", - "11": "A8:D8", - "12": "E8:H8", - "13": "A9:D9", - "14": "E9:H9", - "15": "A10:D10", - "16": "E10:H10", - } - ) - ), -) - - -transfer = activity.primitive_step( - "TransferByMap", - source=conical_tube.output_pin("samples"), - destination=plate1.output_pin("samples"), - amount=sbol3.Measure(200, OM.microliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), - plan=plan, -) -transfer.description = "See the plate layout below." -plate_blanks = activity.primitive_step( - "Transfer", - source=[lb_cam], - destination=plate1.output_pin("samples"), - coordinates="A1:H1, A10:H10, A12:H12", - temperature=sbol3.Measure(4, OM.degree_Celsius), - amount=sbol3.Measure(200, OM.microliter), -) -plate_blanks.description = "These samples are blanks." - -# Display ma here -embedded_image = activity.primitive_step( - "EmbeddedImage", - image="fig2_cell_calibration.png", - caption="Fig 2: Plate layout", -) - -absorbance_plate1 = activity.primitive_step( - "MeasureAbsorbance", - samples=plate1.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -absorbance_plate1.name = "0 hr absorbance timepoint" -fluorescence_plate1 = activity.primitive_step( - "MeasureFluorescence", - samples=plate1.output_pin("samples"), - excitationWavelength=sbol3.Measure(488, OM.nanometer), - emissionWavelength=sbol3.Measure(530, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), -) -fluorescence_plate1.name = "0 hr fluorescence timepoint" - -activity.designate_output( - "0_absorbance_measurements", - "http://bioprotocols.org/labop#SampleData", - source=absorbance_plate1.output_pin("measurements"), -) -activity.designate_output( - "0_fluorescence_measurements", - "http://bioprotocols.org/labop#SampleData", - source=fluorescence_plate1.output_pin("measurements"), -) - - -# Cover plate -seal = activity.primitive_step( - "EvaporativeSeal", - location=plate1.output_pin("samples"), - specification=labop.ContainerSpec( - "seal", - queryString="cont:MicroplateAdhesiveSealingFilm", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -############### Hasta aca bien -# Begin outgrowth - -incubate = activity.primitive_step( - "Incubate", - location=plate1.output_pin("samples"), - duration=sbol3.Measure(6, OM.hour), - temperature=sbol3.Measure(37, OM.degree_Celsius), - shakingFrequency=sbol3.Measure(220, "None"), -) - -absorbance_plate1 = activity.primitive_step( - "MeasureAbsorbance", - samples=plate1.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), - timepoints=[ - sbol3.Measure(2, OM.hour), - sbol3.Measure(4, OM.hour), - sbol3.Measure(6, OM.hour), - ], -) - -absorbance_plate1.name = "absorbance timepoint" - -fluorescence_plate1 = activity.primitive_step( - "MeasureFluorescence", - samples=plate1.output_pin("samples"), - excitationWavelength=sbol3.Measure(488, OM.nanometer), - emissionWavelength=sbol3.Measure(530, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), - timepoints=[ - sbol3.Measure(2, OM.hour), - sbol3.Measure(4, OM.hour), - sbol3.Measure(6, OM.hour), - ], -) -fluorescence_plate1.name = "fluorescence timepoint" -activity.designate_output( - "246_absorbance_measurements", - "http://bioprotocols.org/labop#SampleData", - source=absorbance_plate1.output_pin("measurements"), -) -activity.designate_output( - "246_fluorescence_measurements", - "http://bioprotocols.org/labop#SampleData", - source=fluorescence_plate1.output_pin("measurements"), -) -# Added to si if it changes the next stap -spec.name = "Tube 1" -incubate = activity.primitive_step( - "Incubate", - location=timepoint_subculture1.output_pin("samples"), - duration=sbol3.Measure(2, OM.hour), - temperature=sbol3.Measure(37, OM.degree_Celsius), - shakingFrequency=sbol3.Measure(220, "None"), -) - -# Hold on ice to inhibit cell growth -hold = activity.primitive_step( - "HoldOnIce", location=timepoint_subculture1.output_pin("samples") -) -hold.description = "Reserve until the end of the experiment for absorbance and fluorescence measurements." - - -incubate = activity.primitive_step( - "Incubate", - location=timepoint_subculture2.output_pin("samples"), - duration=sbol3.Measure(4, OM.hour), - temperature=sbol3.Measure(37, OM.degree_Celsius), - shakingFrequency=sbol3.Measure(220, "None"), -) -hold = activity.primitive_step( - "HoldOnIce", location=timepoint_subculture2.output_pin("samples") -) -hold.description = "Reserve until the end of the experiment for absorbance and fluorescence measurements." - - -incubate = activity.primitive_step( - "Incubate", - location=timepoint_subculture3.output_pin("samples"), - duration=sbol3.Measure(6, OM.hour), - temperature=sbol3.Measure(37, OM.degree_Celsius), - shakingFrequency=sbol3.Measure(220, "None"), -) -hold = activity.primitive_step( - "HoldOnIce", location=timepoint_subculture3.output_pin("samples") -) -hold.description = "Reserve until the end of the experiment for absorbance and fluorescence measurements." - - -plates234 = activity.primitive_step( - "EmptyContainer", - specification=labop.ContainerSpec( - "plates234", - name="Plates 2, 3, and 4", - queryString="cont:Plate96Well", - prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, - ), -) - -plan = labop.SampleData( - from_samples=timepoint_subculture1.output_pin("samples"), - values=quote( - json.dumps( - { - "1": "A2:D2", - "2": "E2:H2", - "3": "A3:D3", - "4": "E3:H3", - "5": "A4:D4", - "6": "E4:H4", - "7": "A5:D5", - "8": "E5:H5", - "9": "A7:D7", - "10": "E7:H7", - "11": "A8:D8", - "12": "E8:H8", - "13": "A9:D9", - "14": "E9:H9", - "15": "A10:D10", - "16": "E10:H10", - } - ) - ), -) - -spec.name = "Tubes 1, 2 and 3" -transfer = activity.primitive_step( - "TransferByMap", - source=timepoint_subculture1.output_pin("samples"), - destination=plates234.output_pin("samples"), - amount=sbol3.Measure(200, OM.microliter), - temperature=sbol3.Measure(4, OM.degree_Celsius), - plan=plan, -) - - -plate_blanks = activity.primitive_step( - "Transfer", - source=[lb_cam], - destination=plates234.output_pin("samples"), - coordinates="A1:H1, A10:H10, A12:H12", - temperature=sbol3.Measure(4, OM.degree_Celsius), - amount=sbol3.Measure(200, OM.microliter), -) -plate_blanks.description = "These samples are blanks." - -absorbance_plate = activity.primitive_step( - "MeasureAbsorbance", - samples=plates234.output_pin("samples"), - wavelength=sbol3.Measure(600, OM.nanometer), -) -absorbance_plate.name = f"absorbance timepoint" -fluorescence_plate = activity.primitive_step( - "MeasureFluorescence", - samples=plates234.output_pin("samples"), - excitationWavelength=sbol3.Measure(488, OM.nanometer), - emissionWavelength=sbol3.Measure(530, OM.nanometer), - emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), -) -fluorescence_plate.name = f"fluorescence timepoint" - -activity.designate_output( - "plates234_absorbance_measurements", - "http://bioprotocols.org/labop#SampleData", - source=absorbance_plate.output_pin("measurements"), -) -activity.designate_output( - "plates234_fluorescence_measurements", - "http://bioprotocols.org/labop#SampleData", - source=fluorescence_plate.output_pin("measurements"), -) - - -agent = sbol3.Agent("test_agent") -ee = ExecutionEngine( - specializations=[MarkdownSpecialization("test_LUDOX_markdown.md")], - failsafe=False, - sample_format="json", - track_samples=False, -) -execution = ee.execute(activity, agent, id="test_execution", parameter_values=[]) -render_kit_coordinates_table(execution) -print(execution.markdown) - -# Dress up the markdown to make it pretty and more readable -execution.markdown = execution.markdown.replace("`_E. coli_", "_`E. coli`_ `") -execution.markdown = execution.markdown.replace(" milliliter", "mL") -execution.markdown = execution.markdown.replace( - " degree Celsius", "\u00B0C" -) # degree symbol -execution.markdown = execution.markdown.replace(" nanometer", "nm") -execution.markdown = execution.markdown.replace(" microliter", "uL") - -if REGENERATE_ARTIFACTS: - with open(filename + ".md", "w", encoding="utf-8") as f: - f.write(execution.markdown) + ) + timepoint_subculture1 = activity.primitive_step( + "ContainerSet", quantity=2 * len(plasmids), specification=spec + ) + timepoint_subculture1.description = ( + "The conical tubes should be opaque, amber-colored, or covered with foil." + ) + + timepoint_subculture2 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "tube2", + name=f"Tube 2", + queryString="cont:50mlConicalTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + timepoint_subculture2.description = ( + "The conical tubes should be opaque, amber-colored, or covered with foil." + ) + + timepoint_subculture3 = activity.primitive_step( + "ContainerSet", + quantity=2 * len(plasmids), + specification=labop.ContainerSpec( + "tube3", + name=f"Tube 3", + queryString="cont:50mlConicalTube", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + timepoint_subculture3.description = ( + "The conical tubes should be opaque, amber-colored, or covered with foil." + ) + + transfer = activity.primitive_step( + "Transfer", + source=conical_tube.output_pin("samples"), + destination=timepoint_subculture1.output_pin("samples"), + amount=sbol3.Measure(12, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + + transfer = activity.primitive_step( + "Transfer", + source=conical_tube.output_pin("samples"), + destination=timepoint_subculture2.output_pin("samples"), + amount=sbol3.Measure(12, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + + transfer = activity.primitive_step( + "Transfer", + source=conical_tube.output_pin("samples"), + destination=timepoint_subculture3.output_pin("samples"), + amount=sbol3.Measure(12, OM.milliliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + ) + + plate1 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + "plate1", + name="plate 1", + queryString="cont:Plate96Well", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + hold = activity.primitive_step("HoldOnIce", location=plate1.output_pin("samples")) + + plan = labop.SampleData( + from_samples=conical_tube.output_pin("samples"), + values=quote( + json.dumps( + { + "1": "A2:D2", + "2": "E2:H2", + "3": "A3:D3", + "4": "E3:H3", + "5": "A4:D4", + "6": "E4:H4", + "7": "A5:D5", + "8": "E5:H5", + "9": "A7:D7", + "10": "E7:H7", + "11": "A8:D8", + "12": "E8:H8", + "13": "A9:D9", + "14": "E9:H9", + "15": "A10:D10", + "16": "E10:H10", + } + ) + ), + ) + + transfer = activity.primitive_step( + "TransferByMap", + source=conical_tube.output_pin("samples"), + destination=plate1.output_pin("samples"), + amount=sbol3.Measure(200, OM.microliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + plan=plan, + ) + transfer.description = "See the plate layout below." + plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plate1.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(200, OM.microliter), + ) + plate_blanks.description = "These samples are blanks." + + # Display ma here + embedded_image = activity.primitive_step( + "EmbeddedImage", + image="fig2_cell_calibration.png", + caption="Fig 2: Plate layout", + ) + + absorbance_plate1 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate1.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + absorbance_plate1.name = "0 hr absorbance timepoint" + fluorescence_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(488, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), + ) + fluorescence_plate1.name = "0 hr fluorescence timepoint" + + activity.designate_output( + "0_absorbance_measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_plate1.output_pin("measurements"), + ) + activity.designate_output( + "0_fluorescence_measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_plate1.output_pin("measurements"), + ) + + # Cover plate + seal = activity.primitive_step( + "EvaporativeSeal", + location=plate1.output_pin("samples"), + specification=labop.ContainerSpec( + "seal", + queryString="cont:MicroplateAdhesiveSealingFilm", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + ############### Hasta aca bien + # Begin outgrowth + + incubate = activity.primitive_step( + "Incubate", + location=plate1.output_pin("samples"), + duration=sbol3.Measure(6, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, "None"), + ) + + absorbance_plate1 = activity.primitive_step( + "MeasureAbsorbance", + samples=plate1.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + timepoints=[ + sbol3.Measure(2, OM.hour), + sbol3.Measure(4, OM.hour), + sbol3.Measure(6, OM.hour), + ], + ) + + absorbance_plate1.name = "absorbance timepoint" + + fluorescence_plate1 = activity.primitive_step( + "MeasureFluorescence", + samples=plate1.output_pin("samples"), + excitationWavelength=sbol3.Measure(488, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), + timepoints=[ + sbol3.Measure(2, OM.hour), + sbol3.Measure(4, OM.hour), + sbol3.Measure(6, OM.hour), + ], + ) + fluorescence_plate1.name = "fluorescence timepoint" + activity.designate_output( + "246_absorbance_measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_plate1.output_pin("measurements"), + ) + activity.designate_output( + "246_fluorescence_measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_plate1.output_pin("measurements"), + ) + # Added to si if it changes the next stap + spec.name = "Tube 1" + incubate = activity.primitive_step( + "Incubate", + location=timepoint_subculture1.output_pin("samples"), + duration=sbol3.Measure(2, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, "None"), + ) + + # Hold on ice to inhibit cell growth + hold = activity.primitive_step( + "HoldOnIce", location=timepoint_subculture1.output_pin("samples") + ) + hold.description = "Reserve until the end of the experiment for absorbance and fluorescence measurements." + + incubate = activity.primitive_step( + "Incubate", + location=timepoint_subculture2.output_pin("samples"), + duration=sbol3.Measure(4, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, "None"), + ) + hold = activity.primitive_step( + "HoldOnIce", location=timepoint_subculture2.output_pin("samples") + ) + hold.description = "Reserve until the end of the experiment for absorbance and fluorescence measurements." + + incubate = activity.primitive_step( + "Incubate", + location=timepoint_subculture3.output_pin("samples"), + duration=sbol3.Measure(6, OM.hour), + temperature=sbol3.Measure(37, OM.degree_Celsius), + shakingFrequency=sbol3.Measure(220, "None"), + ) + hold = activity.primitive_step( + "HoldOnIce", location=timepoint_subculture3.output_pin("samples") + ) + hold.description = "Reserve until the end of the experiment for absorbance and fluorescence measurements." + + plates234 = activity.primitive_step( + "EmptyContainer", + specification=labop.ContainerSpec( + "plates234", + name="Plates 2, 3, and 4", + queryString="cont:Plate96Well", + prefixMap={ + "cont": "https://sift.net/container-ontology/container-ontology#" + }, + ), + ) + + plan = labop.SampleData( + from_samples=timepoint_subculture1.output_pin("samples"), + values=quote( + json.dumps( + { + "1": "A2:D2", + "2": "E2:H2", + "3": "A3:D3", + "4": "E3:H3", + "5": "A4:D4", + "6": "E4:H4", + "7": "A5:D5", + "8": "E5:H5", + "9": "A7:D7", + "10": "E7:H7", + "11": "A8:D8", + "12": "E8:H8", + "13": "A9:D9", + "14": "E9:H9", + "15": "A10:D10", + "16": "E10:H10", + } + ) + ), + ) + + spec.name = "Tubes 1, 2 and 3" + transfer = activity.primitive_step( + "TransferByMap", + source=timepoint_subculture1.output_pin("samples"), + destination=plates234.output_pin("samples"), + amount=sbol3.Measure(200, OM.microliter), + temperature=sbol3.Measure(4, OM.degree_Celsius), + plan=plan, + ) + + plate_blanks = activity.primitive_step( + "Transfer", + source=[lb_cam], + destination=plates234.output_pin("samples"), + coordinates="A1:H1, A10:H10, A12:H12", + temperature=sbol3.Measure(4, OM.degree_Celsius), + amount=sbol3.Measure(200, OM.microliter), + ) + plate_blanks.description = "These samples are blanks." + + absorbance_plate = activity.primitive_step( + "MeasureAbsorbance", + samples=plates234.output_pin("samples"), + wavelength=sbol3.Measure(600, OM.nanometer), + ) + absorbance_plate.name = f"absorbance timepoint" + fluorescence_plate = activity.primitive_step( + "MeasureFluorescence", + samples=plates234.output_pin("samples"), + excitationWavelength=sbol3.Measure(488, OM.nanometer), + emissionWavelength=sbol3.Measure(530, OM.nanometer), + emissionBandpassWidth=sbol3.Measure(30, OM.nanometer), + ) + fluorescence_plate.name = f"fluorescence timepoint" + + activity.designate_output( + "plates234_absorbance_measurements", + "http://bioprotocols.org/labop#SampleData", + source=absorbance_plate.output_pin("measurements"), + ) + activity.designate_output( + "plates234_fluorescence_measurements", + "http://bioprotocols.org/labop#SampleData", + source=fluorescence_plate.output_pin("measurements"), + ) + + return activity + + +class InterlabCustomSpecialization(labop.execution.harness.ProtocolSpecialization): + def generate_artifact(self, harness: "ProtocolHarness"): + execution = self.specialization.execution + + render_kit_coordinates_table(execution) + print(execution.markdown) + + # Dress up the markdown to make it pretty and more readable + execution.markdown = execution.markdown.replace("`_E. coli_", "_`E. coli`_ `") + execution.markdown = execution.markdown.replace(" milliliter", "mL") + execution.markdown = execution.markdown.replace( + " degree Celsius", "\u00B0C" + ) # degree symbol + execution.markdown = execution.markdown.replace(" nanometer", "nm") + execution.markdown = execution.markdown.replace(" microliter", "uL") + + super().generate_artifact(harness) + + +if __name__ == "__main__": + harness = labop.execution.harness.ProtocolHarness( + protocol_name="interlab", + clean_output=True, + base_dir=os.path.join(os.path.dirname(__file__), "out", "out_igem_example3"), + entry_point=generate_protocol, + agent="test_agent", + libraries=[ + "liquid_handling", + "plate_handling", + "spectrophotometry", + "sample_arrays", + "culturing", + ], + artifacts=[ + InterlabCustomSpecialization( + specialization=labop_convert.MarkdownSpecialization( + "test_LUDOX_markdown.md" + ) + ) + ], + execution_kwargs={ + "failsafe": False, + "sample_format": "json", + "track_samples": False, + }, + execution_id="test_execution", + ) + harness.run() diff --git a/examples/protocols/iGEM/interlab-growth-curve.ipynb b/examples/protocols/iGEM/interlab-growth-curve.ipynb index e1e1a334..4076e08c 100644 --- a/examples/protocols/iGEM/interlab-growth-curve.ipynb +++ b/examples/protocols/iGEM/interlab-growth-curve.ipynb @@ -14,7 +14,7 @@ "import uml\n", "import sbol3\n", "from tyto import OM\n", - "from labop.execution_engine import ExecutionEngine\n", + "from labop.execution.execution_engine import ExecutionEngine\n", "from labop_convert.markdown.markdown_specialization import MarkdownSpecialization\n", "\n", "\n", diff --git a/examples/protocols/iGEM/interlab-growth-curve.py b/examples/protocols/iGEM/interlab-growth-curve.py index b2785794..50f5f6e5 100644 --- a/examples/protocols/iGEM/interlab-growth-curve.py +++ b/examples/protocols/iGEM/interlab-growth-curve.py @@ -9,7 +9,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert.markdown.markdown_specialization import MarkdownSpecialization doc = sbol3.Document() diff --git a/examples/protocols/iGEM/interlab-timepoint-B.py b/examples/protocols/iGEM/interlab-timepoint-B.py index 767b54cf..e7561f2b 100644 --- a/examples/protocols/iGEM/interlab-timepoint-B.py +++ b/examples/protocols/iGEM/interlab-timepoint-B.py @@ -11,7 +11,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert.markdown.markdown_specialization import MarkdownSpecialization filename = "".join(__file__.split(".py")[0].split("/")[-1:]) diff --git a/examples/protocols/iGEM/interlab-timepoint-B_AV.py b/examples/protocols/iGEM/interlab-timepoint-B_AV.py index f891369a..9725d1b8 100644 --- a/examples/protocols/iGEM/interlab-timepoint-B_AV.py +++ b/examples/protocols/iGEM/interlab-timepoint-B_AV.py @@ -11,7 +11,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert.markdown.markdown_specialization import MarkdownSpecialization filename = "".join(__file__.split(".py")[0].split("/")[-1:]) diff --git a/examples/protocols/iGEM/revised-interlab-growth-curve.py b/examples/protocols/iGEM/revised-interlab-growth-curve.py index bcf4dbb3..b7f07d5e 100644 --- a/examples/protocols/iGEM/revised-interlab-growth-curve.py +++ b/examples/protocols/iGEM/revised-interlab-growth-curve.py @@ -2,6 +2,7 @@ http://2018.igem.org/wiki/images/0/09/2018_InterLab_Plate_Reader_Protocol.pdf """ import json +import sys from urllib.parse import quote import sbol3 @@ -9,7 +10,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert import MarkdownSpecialization if "unittest" in sys.modules: @@ -134,6 +135,7 @@ "ContainerSet", quantity=2 * len(plasmids), specification=labop.ContainerSpec( + "culture_day_1", name=f"culture (day 1)", queryString="cont:CultureTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -157,6 +159,7 @@ "ContainerSet", quantity=2 * len(plasmids), specification=labop.ContainerSpec( + "culture_day_2", name=f"culture (day 2)", queryString="cont:CultureTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -180,6 +183,7 @@ "ContainerSet", quantity=2 * len(plasmids), specification=labop.ContainerSpec( + "cultures_0_hr_timepoint", name="cultures (0 hr timepoint)", queryString="cont:MicrofugeTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -213,6 +217,7 @@ "ContainerSet", quantity=2 * len(plasmids), specification=labop.ContainerSpec( + "back_diluted_culture", name=f"back-diluted culture", queryString="cont:50mlConicalTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -243,6 +248,7 @@ "ContainerSet", quantity=2 * len(plasmids), specification=labop.ContainerSpec( + "back_diluted_culture_aliquots", name="back-diluted culture aliquots", queryString="cont:MicrofugeTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -267,6 +273,7 @@ plate1 = activity.primitive_step( "EmptyContainer", specification=labop.ContainerSpec( + "plate_1", name="plate 1", queryString="cont:Plate96Well", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -333,9 +340,7 @@ ) # Cover plate -seal = activity.primitive_step( - "EvaporativeSeal", location=plate1.output_pin("samples"), type="foo" -) +seal = activity.primitive_step("EvaporativeSeal", location=plate1.output_pin("samples")) # Possibly display map here @@ -397,6 +402,7 @@ "ContainerSet", quantity=len(plasmids) * 2, specification=labop.ContainerSpec( + "six_hr_timepoint", name=f"6hr timepoint", queryString="cont:MicrofugeTube", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -406,6 +412,7 @@ plate2 = activity.primitive_step( "EmptyContainer", specification=labop.ContainerSpec( + "plate_2", name="plate 2", queryString="cont:Plate96Well", prefixMap={"cont": "https://sift.net/container-ontology/container-ontology#"}, @@ -483,9 +490,7 @@ plate_blanks.description = "These are the blanks." # Cover plate -seal = activity.primitive_step( - "EvaporativeSeal", location=plate1.output_pin("samples"), type="foo" -) +seal = activity.primitive_step("EvaporativeSeal", location=plate1.output_pin("samples")) # quick_spin = protocol.primitive_step('QuickSpin', diff --git a/examples/protocols/ludox/LUDOX_protocol.py b/examples/protocols/ludox/LUDOX_protocol.py index 7f4d6422..20ea351e 100644 --- a/examples/protocols/ludox/LUDOX_protocol.py +++ b/examples/protocols/ludox/LUDOX_protocol.py @@ -1,14 +1,12 @@ import logging +import os import sbol3 import tyto from sbol3 import Document import labop -from labop.constants import ddh2o, ludox -from labop.strings import Strings -from labop.utils.harness import ProtocolHarness, ProtocolSpecialization -from labop_convert.markdown.markdown_specialization import MarkdownSpecialization +import labop_convert logger: logging.Logger = logging.Logger(__name__) @@ -21,11 +19,13 @@ def create_plate(protocol: labop.Protocol): + from labop.constants import PREFIX_MAP + spec = labop.ContainerSpec( "plateRequirement", name="calibration plate", queryString=PLATE_SPECIFICATION, - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) plate = protocol.primitive_step("EmptyContainer", specification=spec) plate.name = "calibration plate" @@ -33,6 +33,8 @@ def create_plate(protocol: labop.Protocol): def provision_h2o(protocol: labop.Protocol, plate) -> None: + from labop.constants import ddh2o + c_ddh2o = protocol.primitive_step( "PlateCoordinates", source=plate.output_pin("samples"), @@ -47,6 +49,8 @@ def provision_h2o(protocol: labop.Protocol, plate) -> None: def provision_ludox(protocol: labop.Protocol, plate) -> None: + from labop.constants import ludox + c_ludox = protocol.primitive_step( "PlateCoordinates", source=plate.output_pin("samples"), @@ -92,6 +96,9 @@ def measure_fluorescence( def ludox_protocol(doc: Document, protocol: labop.Protocol) -> labop.Protocol: + # importing the constants after the doc namespace has been set, so the constants have the same namespace. + from labop.constants import ddh2o, ludox + # create the materials to be provisioned doc.add(ddh2o) doc.add(ludox) @@ -126,32 +133,32 @@ def ludox_protocol(doc: Document, protocol: labop.Protocol) -> labop.Protocol: return protocol -harness = ProtocolHarness( - entry_point=ludox_protocol, - artifacts=[ - ProtocolSpecialization( - specialization=MarkdownSpecialization( - "test_LUDOX_markdown.md", - sample_format=Strings.XARRAY, - ) - ) - ], - namespace="https://labop.io/examples/protocols/ludox/", - protocol_name="iGEM_LUDOX_OD_calibration_2018", - protocol_long_name="iGEM 2018 LUDOX OD calibration protocol", - protocol_version="1.0", - protocol_description=""" -With this protocol you will use LUDOX CL-X (a 45% colloidal silica suspension) as a single point reference to -obtain a conversion factor to transform absorbance (OD600) data from your plate reader into a comparable -OD600 measurement as would be obtained in a spectrophotometer. This conversion is necessary because plate -reader measurements of absorbance are volume dependent; the depth of the fluid in the well defines the path -length of the light passing through the sample, which can vary slightly from well to well. In a standard -spectrophotometer, the path length is fixed and is defined by the width of the cuvette, which is constant. -Therefore this conversion calculation can transform OD600 measurements from a plate reader (i.e. absorbance -at 600 nm, the basic output of most instruments) into comparable OD600 measurements. The LUDOX solution -is only weakly scattering and so will give a low absorbance value. - """, -) - if __name__ == "__main__": + harness = labop.execution.harness.ProtocolHarness( + base_dir=os.path.dirname(__file__), + entry_point=ludox_protocol, + artifacts=[ + labop.execution.harness.ProtocolSpecialization( + specialization=labop_convert.MarkdownSpecialization( + "test_LUDOX_markdown.md", + sample_format=labop.Strings.XARRAY, + ) + ) + ], + namespace="https://labop.io/examples/protocols/ludox/", + protocol_name="iGEM_LUDOX_OD_calibration_2018", + protocol_long_name="iGEM 2018 LUDOX OD calibration protocol", + protocol_version="1.0", + protocol_description=""" + With this protocol you will use LUDOX CL-X (a 45% colloidal silica suspension) as a single point reference to + obtain a conversion factor to transform absorbance (OD600) data from your plate reader into a comparable + OD600 measurement as would be obtained in a spectrophotometer. This conversion is necessary because plate + reader measurements of absorbance are volume dependent; the depth of the fluid in the well defines the path + length of the light passing through the sample, which can vary slightly from well to well. In a standard + spectrophotometer, the path length is fixed and is defined by the width of the cuvette, which is constant. + Therefore this conversion calculation can transform OD600 measurements from a plate reader (i.e. absorbance + at 600 nm, the basic output of most instruments) into comparable OD600 measurements. The LUDOX solution + is only weakly scattering and so will give a low absorbance value. + """, + ) harness.run() diff --git a/examples/protocols/ludox/artifacts/test_LUDOX_markdown.md b/examples/protocols/ludox/artifacts/test_LUDOX_markdown.md index 84f6ea23..bc9e51a8 100644 --- a/examples/protocols/ludox/artifacts/test_LUDOX_markdown.md +++ b/examples/protocols/ludox/artifacts/test_LUDOX_markdown.md @@ -1,102 +1,33 @@ -# Experiment 3 - Cell measurement protocol Challenge +# iGEM 2018 LUDOX OD calibration protocol -This year we plan to test protocols that will eventually be automated. For this reason, we will use 96-well plates instead of test tubes for culturing. Consequently, we want to evaluate how the performance of our plate culturing protocol compares to culturing in test tubes (e.g. 10 mL falcon tube) on a global scale. This version of the interlab protocol involves 2 hr. time interval measurements and incubation inside a microplate reader/incubator. -At the end of the experiment, you will have four plates to be measured. You will measure both fluorescence and absorbance in each plate. - -Before performing the cell measurements, you need to perform all the calibration measurements. Please do not proceed unless you have completed the calibration protocol. Completion of the calibrations will ensure that you understand the measurement process and that you can take the cell measurements under the same conditions. For consistency and reproducibility, we are requiring all teams to use E. coli K-12 DH5-alpha. If you do not have access to this strain, you can request streaks of the transformed devices from another team near you. If you are absolutely unable to obtain the DH5-alpha strain, you may still participate in the InterLab study by contacting the Engineering Committee (engineering [at] igem [dot] org) to discuss your situation. - -For all below indicated cell measurements, you must use the same type of plates and the same volumes that you used in your calibration protocol. You must also use the same settings (e.g., filters or excitation and emission wavelengths) that you used in your calibration measurements. If you do not use the same type of plates, volumes, and settings, the measurements will not be valid. - -Protocol summary: UPDATE You will transform the eight devices listed in Table 1 into E. coli K-12 DH5-alpha cells. The next day you will pick two colonies from each transformation (16 total) and use them to inoculate 5 mL overnight cultures (this step is still in tubes). Each of these 16 overnight cultures will be used to inoculate four wells in a 96-well plate (200 microliter each, 4 replicates) and one test tube (12 mL). You will measure how fluorescence and optical density develops over 6 hours by taking measurements at time point 0 hour and at time point 6 hours. Follow the protocol below and the visual instructions in Figure 1 and Figure 2. - - -## Protocol Outputs: -* `baseline absorbance of culture (day 2) measurements of cultures (0 hr timepoint)` -* `0 hr absorbance timepoint measurements of plate 1` -* `0 hr fluorescence timepoint measurements of plate 1` -* `absorbance timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour` -* `fluorescence timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour` -* `absorbance timepoint measurements of Plates 2, 3, and 4` -* `fluorescence timepoint measurements of Plates 2, 3, and 4` +With this protocol you will use LUDOX CL-X (a 45% colloidal silica suspension) as a single point reference to +obtain a conversion factor to transform absorbance (OD600) data from your plate reader into a comparable +OD600 measurement as would be obtained in a spectrophotometer. This conversion is necessary because plate +reader measurements of absorbance are volume dependent; the depth of the fluid in the well defines the path +length of the light passing through the sample, which can vary slightly from well to well. In a standard +spectrophotometer, the path length is fixed and is defined by the width of the cuvette, which is constant. +Therefore this conversion calculation can transform OD600 measurements from a plate reader (i.e. absorbance +at 600 nm, the basic output of most instruments) into comparable OD600 measurements. The LUDOX solution +is only weakly scattering and so will give a low absorbance value. + ## Protocol Materials: -* [_E. coli_ DH5 alpha competent cells](https://identifiers.org/taxonomy:668369) -* [Negative control](http://parts.igem.org/Part:BBa_J428100) -* [Positive control (I20270)](http://parts.igem.org/Part:BBa_I20270) -* [Test Device 1 (J364000)](http://parts.igem.org/Part:BBa_J364000) -* [Test Device 2 (J364001)](http://parts.igem.org/Part:BBa_J364001) -* [Test Device 3 (J364002)](http://parts.igem.org/Part:BBa_J364002) -* [Test Device 4 (J364007)](http://parts.igem.org/Part:BBa_J364007) -* [Test Device 5 (J364008)](http://parts.igem.org/Part:BBa_J364008) -* [Test Device 6 (J364009)](http://parts.igem.org/Part:BBa_J364009) -* [LB Broth + Chloramphenicol (34 ug/mL)]() -* [LB Agar + Chloramphenicol (34 ug/mL)]() -* [Chloramphenicol stock solution (34 mg/mL)](https://pubchem.ncbi.nlm.nih.gov/compound/5959) -* [Ice]() -* [Plate reader]() -* [Shaking incubator]() -* Petri dish (x 8) -* culture tube (x 32) -* 1.5 mL microfuge tube (x 16) -* 50 ml conical tube (x 64) -* 96 well microplate (x 2) -* microplate adhesive sealing film +* [Water, sterile-filtered, BioReagent, suitable for cell culture](https://identifiers.org/pubchem.substance:24901740) +* [LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O](https://identifiers.org/pubchem.substance:24866361) ## Protocol Steps: -1. Obtain 8 x Petri dish containing LB Agar + Chloramphenicol (34 ug/mL) growth medium for culturing `transformant strains` -2. Transform `Negative control` DNA into `_E. coli_ DH5 alpha competent cells`. Repeat for the remaining transformant DNA: `Positive control (I20270)`, `Test Device 1 (J364000)`, `Test Device 2 (J364001)`, `Test Device 3 (J364002)`, `Test Device 4 (J364007)`, `Test Device 5 (J364008)`, and `Test Device 6 (J364009)`. Plate transformants on LB Agar + Chloramphenicol (34 ug/mL) `transformant strains` plates. Incubate overnight (for 16 hour) at 37.0 degree Celsius. -3. Obtain 16 x culture tubes to contain `culture (day 1)` -4. Pick 2 colonies from each `transformant strains` plate. -5. Inoculate 2 colonies of each transformant strains, for a total of 16 cultures. Inoculate each into 5.0 milliliter of LB Broth + Chloramphenicol (34 ug/mL) in culture (day 1) and grow overnight (for 16.0 hour) at 37.0 degree Celsius and 220 rpm. -6. Obtain 16 x culture tubes to contain `culture (day 2)` -7. Dilute each of 16 `culture (day 1)` samples with LB Broth + Chloramphenicol (34 ug/mL) into the culture tube at a 1:10 ratio and final volume of 5.0 milliliter. Maintain at 4.0 degree Celsius while performing dilutions. (This can be also performed on ice). -8. Obtain 16 x 1.5 mL microfuge tubes to contain `cultures (0 hr timepoint)` -9. Hold `cultures (0 hr timepoint)` on ice. This will prevent cell growth while transferring samples. -10. Transfer 1.0 milliliter of each of 16 `culture (day 2)` samples to 1.5 mL microfuge tube containers to contain a total of 16 `cultures (0 hr timepoint)` samples. Maintain at 4.0 degree Celsius during transfer. (This can be also performed on Ice). -11. Measure baseline absorbance of culture (day 2) of `cultures (0 hr timepoint)` at 600.0 nanometer. -12. Obtain 16 x 50 ml conical tubes to contain `back-diluted culture` The conical tube should be opaque, amber-colored, or covered with foil. -13. Back-dilute each of 16 `culture (day 2)` samples to a target OD of 0.02 using LB Broth + Chloramphenicol (34 ug/mL) as diluent to a final volume of 40.0 milliliter. Maintain at 4.0 degree Celsius while performing dilutions. - -![](fig1_challenge_protocol.png) -

Fig 1: Visual representation of protocol

- -14. Obtain 16 x 50 ml conical tubes to contain `Tubes 1, 2 and 3` The conical tubes should be opaque, amber-colored, or covered with foil. -15. Obtain 16 x 50 ml conical tubes to contain `Tube 2` The conical tubes should be opaque, amber-colored, or covered with foil. -16. Obtain 16 x 50 ml conical tubes to contain `Tube 3` The conical tubes should be opaque, amber-colored, or covered with foil. -17. Transfer 12.0 milliliter of each of 16 `back-diluted culture` samples to 50 ml conical tube containers to contain a total of 16 `Tubes 1, 2 and 3` samples. Maintain at 4.0 degree Celsius during transfer. -18. Transfer 12.0 milliliter of each of 16 `back-diluted culture` samples to 50 ml conical tube containers to contain a total of 16 `Tube 2` samples. Maintain at 4.0 degree Celsius during transfer. -19. Transfer 12.0 milliliter of each of 16 `back-diluted culture` samples to 50 ml conical tube containers to contain a total of 16 `Tube 3` samples. Maintain at 4.0 degree Celsius during transfer. -20. Obtain a 96 well microplate to contain `plate 1` -21. Hold `plate 1` on ice. -22. Transfer 200.0 microliter of each `back-diluted culture` sample to 96 well microplate `plate 1` in the wells indicated in the plate layout. - Maintain at 4.0 degree Celsius during transfer. -23. Transfer 200.0 microliter of `LB Broth + Chloramphenicol (34 ug/mL)` sample to wells A1:H1, A10:H10, A12:H12 of 96 well microplate `plate 1`. Maintain at 4.0 degree Celsius during transfer. These samples are blanks. - -![](fig2_cell_calibration.png) -

Fig 2: Plate layout

+1. Provision a container named `calibration plate` meeting specification: cont:ClearPlate and + cont:SLAS-4-2004 and + (cont:wellVolume some + ((om:hasUnit value om:microlitre) and + (om:hasNumericalValue only xsd:decimal[>= "200"^^xsd:decimal]))). +2. Pipette 100.0 microliter of [Water, sterile-filtered, BioReagent, suitable for cell culture](https://identifiers.org/pubchem.substance:24901740) into `calibration plate A1:D1`. +3. Pipette 100.0 microliter of [LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O](https://identifiers.org/pubchem.substance:24866361) into `calibration plate A2:D2`. +4. Import data into the provided Excel file: . -24. Measure 0 hr absorbance timepoint of `plate 1` at 600.0 nanometer. -25. Measure 0 hr fluorescence timepoint of `plate 1` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass. -26. Cover `plate 1` samples in 96 well microplate with your choice of material to prevent evaporation. -27. Incubate all `plate 1` samples for 6.0 hour at 37.0 degree Celsius at 220 rpm. -28. Measure absorbance timepoint of `plate 1` at 600.0 nanometer at timepoints 2.0 hour, 4.0 hour, 6.0 hour. -29. Measure fluorescence timepoint of `plate 1` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass at timepoints 2.0 hour, 4.0 hour, 6.0 hour. -30. Incubate all `Tubes 1, 2 and 3` samples for 2.0 hour at 37.0 degree Celsius at 220 rpm. -31. Hold all `Tubes 1, 2 and 3` samples on ice. Reserve until the end of the experiment for absorbance and fluorescence measurements. -32. Incubate all `Tube 2` samples for 4.0 hour at 37.0 degree Celsius at 220 rpm. -33. Hold all `Tube 2` samples on ice. Reserve until the end of the experiment for absorbance and fluorescence measurements. -34. Incubate all `Tube 3` samples for 6.0 hour at 37.0 degree Celsius at 220 rpm. -35. Hold all `Tube 3` samples on ice. Reserve until the end of the experiment for absorbance and fluorescence measurements. -36. Obtain a 96 well microplate to contain `Plates 2, 3, and 4` -37. Transfer 200.0 microliter of each `Tubes 1, 2 and 3` sample to 96 well microplate `Plates 2, 3, and 4` in the wells indicated in the plate layout. - Maintain at 4.0 degree Celsius during transfer. -38. Transfer 200.0 microliter of `LB Broth + Chloramphenicol (34 ug/mL)` sample to wells A1:H1, A10:H10, A12:H12 of 96 well microplate `Plates 2, 3, and 4`. Maintain at 4.0 degree Celsius during transfer. These samples are blanks. -39. Measure absorbance timepoint of `Plates 2, 3, and 4` at 600.0 nanometer. -40. Measure fluorescence timepoint of `Plates 2, 3, and 4` with excitation wavelength of 488.0 nanometer and emission filter of 530.0 nanometer and 30.0 nanometer bandpass. -41. Import data for `baseline absorbance of culture (day 2) measurements of cultures (0 hr timepoint)`, `0 hr absorbance timepoint measurements of plate 1`, `0 hr fluorescence timepoint measurements of plate 1`, `absorbance timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour`, `fluorescence timepoint measurements of plate 1 at timepoints 2.0 hour, 4.0 hour, 6.0 hour`, `absorbance timepoint measurements of Plates 2, 3, and 4`, `fluorescence timepoint measurements of Plates 2, 3, and 4` into provided Excel file. --- -Timestamp: 2022-07-08 19:34:25.986146--- -Protocol version: 1.2b \ No newline at end of file +Timestamp: 2023-10-14 18:13:35.378047 +Protocol version: 1.0 diff --git a/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py b/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py index 5b1ae849..e27ce02f 100644 --- a/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py +++ b/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py @@ -2,10 +2,10 @@ import tyto import labop -from labop.constants import ddh2o, ludox +from labop.constants import PREFIX_MAP, ddh2o, ludox +from labop.execution.harness import ProtocolHarness, ProtocolSpecialization from labop.protocol import Protocol from labop.strings import Strings -from labop.utils.harness import ProtocolHarness, ProtocolSpecialization from labop_convert.markdown.markdown_specialization import MarkdownSpecialization from labop_convert.opentrons.opentrons_specialization import OT2Specialization @@ -27,30 +27,30 @@ def generate_protocol(doc: sbol3.Document, activity: Protocol) -> Protocol: "working_reagents_rack", name="rack for reagent aliquots", queryString="cont:Opentrons24TubeRackwithEppendorf1.5mLSafe-LockSnapcap", - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) spec_ludox_container = labop.ContainerSpec( "ludox_working_solution", name="tube for ludox working solution", queryString="cont:MicrofugeTube", - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) spec_water_container = labop.ContainerSpec( "water_stock", name="tube for water aliquot", queryString="cont:MicrofugeTube", - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) spec_plate = labop.ContainerSpec( "calibration_plate", name="calibration plate", queryString="cont:Corning96WellPlate360uLFlat", - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) spec_tiprack = labop.ContainerSpec( "tiprack", queryString="cont:Opentrons96TipRack300uL", - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) doc.add(spec_rack) doc.add(spec_ludox_container) @@ -125,26 +125,25 @@ def generate_protocol(doc: sbol3.Document, activity: Protocol) -> Protocol: return activity -harness = ProtocolHarness( - entry_point=generate_protocol, - artifacts=[ - ProtocolSpecialization( - specialization=MarkdownSpecialization( - "opentrons_ludox_example_protocol.md", - sample_format=Strings.XARRAY, - ) - ), - ProtocolSpecialization( - specialization=OT2Specialization("opentrons_ludox_example_labop.py") - ), - ], - namespace="https://labop.io/examples/protocols/opentrons/", - protocol_name="iGEM_LUDOX_OD_calibration_2018", - protocol_long_name="iGEM 2018 LUDOX OD calibration protocol for OT2", - protocol_version="1.0", - protocol_description="Test Execution", - agent=sbol3.Agent("ot2_machine", name="OT2 machine"), -) - if __name__ == "__main__": + harness = ProtocolHarness( + entry_point=generate_protocol, + artifacts=[ + ProtocolSpecialization( + specialization=MarkdownSpecialization( + "opentrons_ludox_example_protocol.md", + sample_format=Strings.XARRAY, + ) + ), + ProtocolSpecialization( + specialization=OT2Specialization("opentrons_ludox_example_labop.py") + ), + ], + namespace="https://labop.io/examples/protocols/opentrons/", + protocol_name="iGEM_LUDOX_OD_calibration_2018", + protocol_long_name="iGEM 2018 LUDOX OD calibration protocol for OT2", + protocol_version="1.0", + protocol_description="Test Execution", + agent=sbol3.Agent("ot2_machine", name="OT2 machine"), + ) harness.run() diff --git a/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py b/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py index e3a00179..cc91f22d 100644 --- a/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py +++ b/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py @@ -6,9 +6,8 @@ import labop import uml -from labop.constants import ddh2o, ludox -from labop.execution_engine import ExecutionEngine -from labop_convert.markdown.markdown_specialization import MarkdownSpecialization +from labop.constants import PREFIX_MAP, ddh2o, ludox +from labop.execution.execution_engine import ExecutionEngine from labop_convert.opentrons.opentrons_specialization import OT2Specialization # Dev Note: This is a test of the initial version of the OT2 specialization. Any specs shown here can be changed in the future. Use at your own risk. Here be dragons. @@ -155,7 +154,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): "reagent_rack", name="Tube rack for reagents", queryString="cont:Opentrons24TubeRackwithEppendorf1.5mLSafe-LockSnapcap", - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) rack = activity.primitive_step("EmptyRack", specification=reagent_rack) load_rack = activity.primitive_step( @@ -167,7 +166,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): "primer_plate", name="primers in 96-well plate", queryString="cont:Corning96WellPlate360uLFlat", - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) load = activity.primitive_step( "LoadRackOnInstrument", rack=primer_plate, coordinates="3" @@ -179,7 +178,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): "polymerase", name="DNA Polymerase", queryString="cont:StockReagent", - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) load_reagents = activity.primitive_step( "LoadContainerInRack", @@ -196,7 +195,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): "water", name="tube for water", queryString="cont:MicrofugeTube", - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ), coordinates="B1", ) @@ -217,7 +216,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): template.display_id + "_container", name="container of " + template.name, queryString="cont:MicrofugeTube", - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) load_template = activity.primitive_step( "LoadContainerInRack", @@ -232,7 +231,7 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): "pcr_plate", name="PCR plate", queryString="cont:Biorad96WellPCRPlate", - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) load_pcr_plate_on_thermocycler = activity.primitive_step( "LoadContainerOnInstrument", diff --git a/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py b/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py index 1e586ca1..34baed8d 100644 --- a/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py +++ b/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py @@ -1,24 +1,14 @@ import logging -import rdflib as rdfl import sbol3 import tyto from sbol3 import Document import labop -import uml -from labop.execution_engine import ExecutionEngine +from labop.constants import PREFIX_MAP +from labop.execution import ProtocolHarness, ProtocolSpecialization from labop.protocol import Protocol from labop.strings import Strings -from labop.utils.harness import ( - ProtocolDiagram, - ProtocolExecutionDiagram, - ProtocolExecutionNTuples, - ProtocolHarness, - ProtocolNTuples, - ProtocolSampleTrace, - ProtocolSpecialization, -) from labop_convert.markdown.markdown_specialization import MarkdownSpecialization from labop_convert.opentrons.opentrons_specialization import ( REVERSE_LABWARE_MAP, @@ -61,7 +51,7 @@ def get_container(protocol: labop.Protocol, container_name: str, container_type: container_name.replace(" ", "_"), name=container_name, queryString=query_string, - prefixMap=labop.constants.PREFIX_MAP, + prefixMap=PREFIX_MAP, ) plate = protocol.primitive_step("EmptyContainer", specification=plate_spec) return plate @@ -126,24 +116,23 @@ def opentrons_toy_protocol(doc: sbol3.Document, protocol: Protocol) -> Protocol: return protocol -harness = ProtocolHarness( - entry_point=opentrons_toy_protocol, - artifacts=[ - ProtocolSpecialization( - specialization=MarkdownSpecialization( - "opentrons_toy_protocol.md", sample_format=Strings.XARRAY - ) - ), - ProtocolSpecialization( - specialization=OT2Specialization("opentrons_toy_protocol_labop.py") - ), - ], - namespace="https://labop.io/examples/protocols/opentrons/", - protocol_name="opentrons_toy", - protocol_long_name="OT2 simple toy demonstration", - protocol_version="1.0", - protocol_description="Example Opentrons Protocol as LabOP", -) - if __name__ == "__main__": + harness = ProtocolHarness( + entry_point=opentrons_toy_protocol, + artifacts=[ + ProtocolSpecialization( + specialization=MarkdownSpecialization( + "opentrons_toy_protocol.md", sample_format=Strings.XARRAY + ) + ), + ProtocolSpecialization( + specialization=OT2Specialization("opentrons_toy_protocol_labop.py") + ), + ], + namespace="https://labop.io/examples/protocols/opentrons/", + protocol_name="opentrons_toy", + protocol_long_name="OT2 simple toy demonstration", + protocol_version="1.0", + protocol_description="Example Opentrons Protocol as LabOP", + ) harness.run() diff --git a/examples/protocols/pH_calibration/pH_calibration.py b/examples/protocols/pH_calibration/pH_calibration.py index c3c90d4d..af9e13cc 100644 --- a/examples/protocols/pH_calibration/pH_calibration.py +++ b/examples/protocols/pH_calibration/pH_calibration.py @@ -18,7 +18,7 @@ import examples.pH_calibration.ph_calibration_utils as util import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine logger: logging.Logger = logging.Logger("pH_calibration") @@ -439,7 +439,10 @@ def main(): ] try: execution = ee.execute( - new_protocol, agent, id="test_execution", parameter_values=parameter_values + new_protocol, + agent, + id="test_execution", + parameter_values=parameter_values, ) except Exception as e: logger.exception(e) diff --git a/interlab-growth-curve.ipynb b/interlab-growth-curve.ipynb index e1e1a334..4076e08c 100644 --- a/interlab-growth-curve.ipynb +++ b/interlab-growth-curve.ipynb @@ -14,7 +14,7 @@ "import uml\n", "import sbol3\n", "from tyto import OM\n", - "from labop.execution_engine import ExecutionEngine\n", + "from labop.execution.execution_engine import ExecutionEngine\n", "from labop_convert.markdown.markdown_specialization import MarkdownSpecialization\n", "\n", "\n", diff --git a/interlab-growth-curve.py b/interlab-growth-curve.py index b2785794..50f5f6e5 100644 --- a/interlab-growth-curve.py +++ b/interlab-growth-curve.py @@ -9,7 +9,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert.markdown.markdown_specialization import MarkdownSpecialization doc = sbol3.Document() diff --git a/labop/__init__.py b/labop/__init__.py index 879befe1..67153c06 100644 --- a/labop/__init__.py +++ b/labop/__init__.py @@ -4,7 +4,6 @@ from . import inner -from .utils import * from .parameter_value import * from .sample_collection import * from .activity_edge_flow import * @@ -22,9 +21,7 @@ from .container_spec import * from .data import * -from .execution_engine import * -from .execution_engine_utils import * -from .lab_interface import * +from .execution import * from .material import * from .primitive_array import * @@ -40,6 +37,12 @@ from .library import * +from .execution import * +from .utils import * + +# from .constants import * + + ######################################### # Kludge for getting parents and TopLevels - workaround for pySBOL3 issue #234 # TODO: remove after resolution of https://github.com/SynBioDex/pySBOL3/issues/234 diff --git a/labop/activity_edge_flow.py b/labop/activity_edge_flow.py index 0ea7cdbe..c8143af8 100644 --- a/labop/activity_edge_flow.py +++ b/labop/activity_edge_flow.py @@ -7,6 +7,7 @@ import sbol3 from uml import CallBehaviorAction, InputPin, LiteralReference, Parameter +from uml.activity_edge import ActivityEdge from . import inner from .protocol import Protocol @@ -16,7 +17,7 @@ class ActivityEdgeFlow(inner.ActivityEdgeFlow): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - def get_edge(self): + def get_edge(self) -> ActivityEdge: return self.edge.lookup() def get_value(self): diff --git a/labop/call_behavior_execution.py b/labop/call_behavior_execution.py index 5c670b25..c3aa8222 100644 --- a/labop/call_behavior_execution.py +++ b/labop/call_behavior_execution.py @@ -123,14 +123,18 @@ def check_next_tokens( for token in tokens: edge = token.get_edge() if isinstance(edge, ObjectFlow): - target: OutputPin = edge.get_target() # target is an OutputPin - call.parameter_values += [ - ParameterValue( - parameter=self.get_parameter(name=target.name, ordered=True), - value=literal(v.get_value(), reference=True), - ) - for v in token.get_value() - ] + target = edge.get_target() + # only want output pin tokens. It is possible that the target is a subprotocol ActivityParameterNode. + if isinstance(target, OutputPin): + for v in token.get_value(): + call.parameter_values.append( + ParameterValue( + parameter=self.get_parameter( + name=target.get_name(), ordered=True + ), + value=literal(v.get_value(), reference=True), + ) + ) ### Check that the same parameter names are sane: # 1. unbounded parameters can appear 0+ times @@ -139,7 +143,7 @@ def check_next_tokens( pin_sets = {} for pv in call.parameter_values: - name = pv.get_parameter().name + name = pv.get_name() value = pv.value.get_value() if pv.value else None if name not in pin_sets: pin_sets[name] = [] diff --git a/labop/constants.py b/labop/constants.py index 1992f7de..e0c4df92 100644 --- a/labop/constants.py +++ b/labop/constants.py @@ -2,6 +2,7 @@ import rdflib as rdfl import sbol3 +import tyto CONT_NS = rdfl.Namespace("https://sift.net/container-ontology/container-ontology#") OM_NS = rdfl.Namespace("http://www.ontology-of-units-of-measure.org/resource/om-2/") @@ -14,3 +15,37 @@ ludox = sbol3.Component("LUDOX", "https://identifiers.org/pubchem.substance:24866361") ludox.name = "LUDOX(R) CL-X colloidal silica, 45 wt. % suspension in H2O" + +pbs = sbol3.Component("pbs", "https://pubchem.ncbi.nlm.nih.gov/compound/24978514") +pbs.name = "Phosphate Buffered Saline" + +silica_beads = sbol3.Component( + "silica_beads", + "https://nanocym.com/wp-content/uploads/2018/07/NanoCym-All-Datasheets-.pdf", +) +silica_beads.name = "NanoCym 950 nm monodisperse silica nanoparticles" +silica_beads.description = "3e9 NanoCym microspheres" + +fluorescein = sbol3.Component( + "fluorescein", "https://pubchem.ncbi.nlm.nih.gov/substance/329753341" +) +fluorescein.name = "Fluorescein" + +cascade_blue = sbol3.Component( + "cascade_blue", "https://pubchem.ncbi.nlm.nih.gov/substance/57269662" +) +cascade_blue.name = "Cascade Blue" + +sulforhodamine = sbol3.Component( + "sulforhodamine", "https://pubchem.ncbi.nlm.nih.gov/compound/139216224" +) +sulforhodamine.name = "Sulforhodamine" + +rpm = sbol3.UnitDivision( + "rpm", + name="rpm", + symbol="rpm", + label="revolutions per minute", + numerator=tyto.OM.revolution, + denominator=tyto.OM.minute, +) diff --git a/labop/execution/__init__.py b/labop/execution/__init__.py new file mode 100644 index 00000000..415d4c5a --- /dev/null +++ b/labop/execution/__init__.py @@ -0,0 +1,4 @@ +from .execution_engine import * +from .execution_context import * +from .execution_engine_utils import * +from .harness import * diff --git a/labop_convert/behavior_dynamics.py b/labop/execution/behavior_dynamics.py similarity index 99% rename from labop_convert/behavior_dynamics.py rename to labop/execution/behavior_dynamics.py index c2aa7282..52449733 100644 --- a/labop_convert/behavior_dynamics.py +++ b/labop/execution/behavior_dynamics.py @@ -71,7 +71,9 @@ def update(self, record: ActivityNodeExecution) -> None: if new_nodes: self.graph = self.update_graph(new_nodes) self.to_dot().render( - os.path.join(self.outdir, f"{self.name}_{self.exec_tick}") + os.path.join(self.outdir, f"{self.name}_{self.exec_tick}"), + cleanup=True, + overwrite_source=True, ) self.exec_tick += 1 else: diff --git a/labop/execution_context.py b/labop/execution/execution_context.py similarity index 99% rename from labop/execution_context.py rename to labop/execution/execution_context.py index fc84cca8..bb72d003 100644 --- a/labop/execution_context.py +++ b/labop/execution/execution_context.py @@ -2,6 +2,8 @@ import sbol3 +from labop.call_behavior_execution import CallBehaviorExecution +from labop.parameter_value import ParameterValue from uml import ( Action, Activity, @@ -23,9 +25,6 @@ from uml.final_node import FinalNode from uml.initial_node import InitialNode -from .call_behavior_execution import CallBehaviorExecution -from .parameter_value import ParameterValue - class ExecutionContext(object): """ @@ -211,7 +210,7 @@ def get_invocation_edge(self, source: ActivityNode, target: ActivityNode): ) ) except StopIteration: - raise Exception(f"Could not find invocation edge from {source}") + raise Exception(f"Could not find invocation edge from {source} to {target}") def get_nodes(self): nodes = [] diff --git a/labop/execution_engine.py b/labop/execution/execution_engine.py similarity index 97% rename from labop/execution_engine.py rename to labop/execution/execution_engine.py index 5f513757..6ddf49c1 100644 --- a/labop/execution_engine.py +++ b/labop/execution/execution_engine.py @@ -11,7 +11,17 @@ import sbol3 from numpy import record -from labop_convert.behavior_dynamics import SampleProvenanceObserver +from labop.activity_edge_flow import ActivityEdgeFlow +from labop.activity_node_execution import ActivityNodeExecution +from labop.behavior_execution import BehaviorExecution +from labop.call_behavior_execution import CallBehaviorExecution +from labop.dataset import Dataset +from labop.parameter_value import ParameterValue +from labop.primitive import Primitive +from labop.protocol import Protocol +from labop.protocol_execution import ProtocolExecution +from labop.sample_data import SampleData +from labop.strings import Strings from uml import ActivityNode, CallBehaviorAction from uml.activity import Activity from uml.activity_edge import ActivityEdge @@ -21,18 +31,8 @@ from uml.pin import Pin from uml.utils import WellFormednessIssue, WellformednessLevels, literal -from .activity_edge_flow import ActivityEdgeFlow -from .activity_node_execution import ActivityNodeExecution -from .behavior_execution import BehaviorExecution -from .call_behavior_execution import CallBehaviorExecution -from .dataset import Dataset +from .behavior_dynamics import SampleProvenanceObserver from .execution_context import ExecutionContext -from .parameter_value import ParameterValue -from .primitive import Primitive -from .protocol import Protocol -from .protocol_execution import ProtocolExecution -from .sample_data import SampleData -from .strings import Strings l: logging.Logger = logging.getLogger(__file__) l.setLevel(logging.ERROR) @@ -534,9 +534,12 @@ def next_tokens( ActivityEdgeFlow( edge=new_execution_context.get_invocation_edge( token_consumed.get_edge().get_source(), + activity_parameter_node, ), token_source=token_consumed.token_source, - value=[literal(token_consumed.value, reference=True)], + value=[ + literal(v, reference=True) for v in token_consumed.value + ], ) for token_consumed in record.get_incoming_flows() if isinstance(token_consumed.get_edge().get_source(), Pin) diff --git a/labop/execution_engine_utils.py b/labop/execution/execution_engine_utils.py similarity index 96% rename from labop/execution_engine_utils.py rename to labop/execution/execution_engine_utils.py index 35e67549..fd3ca2b4 100644 --- a/labop/execution_engine_utils.py +++ b/labop/execution/execution_engine_utils.py @@ -1,10 +1,9 @@ import logging from labop import ActivityEdgeFlow +from labop.activity_node_execution import ActivityNodeExecution from uml import CallBehaviorAction, Pin -from .activity_node_execution import ActivityNodeExecution - l = logging.getLogger(__file__) l.setLevel(logging.ERROR) diff --git a/labop/execution/harness.py b/labop/execution/harness.py new file mode 100644 index 00000000..bb62ece7 --- /dev/null +++ b/labop/execution/harness.py @@ -0,0 +1,728 @@ +import filecmp +import glob +import json +import logging +import os +import shutil +from abc import ABC +from datetime import datetime +from importlib.machinery import SourceFileLoader +from importlib.util import module_from_spec, spec_from_loader +from typing import Any, Callable, Dict, List, Optional, Union + +import sbol3 + +from labop import ProtocolExecution +from labop.execution import ExecutionEngine +from labop.library import import_library +from labop.parameter_value import ParameterValue +from labop.protocol import Protocol +from labop.utils.helpers import file_diff, prepare_document +from labop_convert import BehaviorSpecialization + +l = logging.Logger(__file__) +l.setLevel(logging.INFO) +ConsoleOutputHandler = logging.StreamHandler() +l.addHandler(ConsoleOutputHandler) + + +class ProtocolArtifactStatus: + PASS = "pass" + FAIL = "fail" + PENDING = "pending" + + +class ProtocolArtifact(ABC): + results: Dict[str, Any] = None + status: str = None + filename: str = None + + def __init__(self, *args, **kwargs): + super().__init__(*args) + self.status = ProtocolArtifactStatus.PENDING + self.results = {} + + def results_summary(self) -> str: + return f"{json.dumps(self.results, indent=4)}" + + def configuration_summary(self, verbose=False) -> str: + return "" + + +class ProtocolNTuples(ProtocolArtifact): + cached_protocol_file: Optional[str] = None + namespace: str + protocol_name: str + protocol_long_name: str + protocol_version: str + protocol_description: str + _protocol: Protocol = None + _doc: sbol3.Document = None + next: Optional[ProtocolArtifact] = None + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.cached_protocol_file = ( + kwargs["cached_protocol_file"] if "cached_protocol_file" in kwargs else None + ) + self.namespace = kwargs["namespace"] if "namespace" in kwargs else None + self.protocol_name = ( + kwargs["protocol_name"] if "protocol_name" in kwargs else None + ) + self.protocol_long_name = ( + kwargs["protocol_long_name"] if "protocol_long_name" in kwargs else None + ) + self.protocol_version = ( + kwargs["protocol_version"] if "protocol_version" in kwargs else None + ) + self.protocol_description = ( + kwargs["protocol_description"] if "protocol_description" in kwargs else None + ) + self.next = kwargs["next"] if "next" in kwargs else None + self._doc = self.prepare_document() + self._protocol = None + + def read_protocol(self, filename: str = None): + filename = self.cached_protocol_file if filename is None else filename + self._doc.read(filename, "nt") + self._protocol = self._doc.find(f"{self.namespace}{self.protocol_name}") + return self._protocol, self._doc + + def import_libraries(self, libraries: List[str]): + self.results["libraries"] = [] + for library in libraries: + import_library(library) + self.results["libraries"].append(library) + + def generate_protocol(self, harness: "ProtocolHarness") -> Protocol: + self.import_libraries(harness.libraries) + entry_point = harness.entry_point + self._protocol = Protocol(harness.protocol_name) + self._protocol.name = harness.protocol_long_name + self._protocol.version = harness.protocol_version + self._protocol.description = harness.protocol_description + self.results["protocol"] = { + "name": self.protocol_name, + "version": self._protocol.version, + } + self._doc.add(self._protocol) + self._protocol = entry_point(self._doc, self._protocol) + l.info("Validating and writing protocol") + v = self._doc.validate() + + if len(v) > 0: + self.results["protocol"]["validation"] = "".join(f"\n {e}" for e in v) + self.status = ProtocolArtifactStatus.FAIL + else: + self.results["protocol"]["validation"] = ProtocolArtifactStatus.PASS + self.status = ProtocolArtifactStatus.PASS + + return self._protocol + + def prepare_document(self) -> sbol3.Document: + self._doc = prepare_document(namespace=self.namespace) + self.results["document"] = {"namespace": self.namespace} + return self._doc + + def ntuples_filename(self, filename_prefix) -> str: + return filename_prefix + ".nt" + + def generate_artifact(self, harness: "ProtocolHarness"): + if self.cached_protocol_file is not None: + l.info(f"Bypassing Protocol Generation, looking for existing .nt file ...") + if os.path.exists(self.cached_protocol_file): + l.info(f"Found .nt file: {self.cached_protocol_file}") + self.read_protocol() + + self.filename = ( + os.path.join( + harness.full_output_dir, + self.ntuples_filename(harness.filename_prefix()), + ) + if self.filename is None + else self.filename + ) + try: + self.generate_protocol(harness) + + assert self._protocol is not None, f"Protocol was not generated ... " + + # with open(self.filename, "w") as f: + l.info(f"Saving protocol [{self.filename}].") + # f.write(self._doc.write_string(sbol3.SORTED_NTRIPLES).strip()) + self.results["nt_filename"] = self.filename + # self._doc.write(self.filename, sbol3.SORTED_NTRIPLES) + with open(self.filename, "w") as f: + f.write(self._doc.write_string(sbol3.SORTED_NTRIPLES).strip()) + + except Exception as e: + self.status = ProtocolArtifactStatus.FAIL + self.results["exception"] = str(e) + + +class ProtocolDownstreamArtifact(ProtocolArtifact): + protocol_artifact: ProtocolNTuples = None + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.protocol_artifact = ( + kwargs["protocol_artifact"] if "protocol_artifact" in kwargs else None + ) + + def protocol(self): + return self.protocol_artifact._protocol + + def protocol_name(self): + return self.protocol_artifact.protocol_name + + +class ProtocolDiagram(ProtocolDownstreamArtifact): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def diagram_filename(self, filename_prefix: str) -> str: + return filename_prefix + ".diagram" + + def generate_artifact(self, harness: "ProtocolHarness"): + self.filename = ( + os.path.join( + harness.full_output_dir, + self.diagram_filename(harness.filename_prefix()), + ) + if self.filename is None + else self.filename + ) + try: + self.protocol().to_dot().render( + self.filename, cleanup=True, overwrite_source=True + ) + self.results["filename"] = self.filename + self.status = ProtocolArtifactStatus.PASS + except Exception as e: + self.results["exception"] = str(e) + self.status = ProtocolArtifactStatus.FAIL + + +class ProtocolRubric(ProtocolDownstreamArtifact): + filename: str = None + + def __init__(self, filename, *args, **kwargs): + super().__init__(*args, **kwargs) + self.filename = filename + + def generate_artifact(self, harness: "ProtocolHarness"): + # diff = "" + try: + diff = file_diff(self.filename, self.protocol_artifact.filename) + # print(f"Difference: {diff}") + assert filecmp.cmp( + self.protocol_artifact.filename, self.filename + ), "Files are not identical" + self.results["filename"] = self.filename + self.status = ProtocolArtifactStatus.PASS + except Exception as e: + self.results["exception"] = str(e) + self.status = ProtocolArtifactStatus.FAIL + self.results["diff"] = diff + + +class ProtocolExecutionNTuples(ProtocolDownstreamArtifact): + agent: Union[sbol3.Agent, str] = None + execution: ProtocolExecution = None + execution_id: str = None + parameter_values: List[ParameterValue] = None + execution_engine: ExecutionEngine = None + specializations: List[BehaviorSpecialization] = None + dataset_filename: str = None + execution_kwargs: Dict[str, Any] = None + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.agent = ( + kwargs["agent"] if "agent" in kwargs else sbol3.Agent("labop_harness") + ) + if isinstance(self.agent, str): + self.agent = sbol3.Agent(self.agent) + + self.execution_id = ( + kwargs["execution_id"] if "execution_id" in kwargs else self.execution_id + ) + self.parameter_values = ( + kwargs["parameter_values"] + if "parameter_values" in kwargs + else self.parameter_values + ) + + self.dataset_filename = ( + kwargs["dataset_filename"] + if "dataset_filename" in kwargs + else "dataset.xslx" + ) + self.specializations = ( + kwargs["specializations"] + if "specializations" in kwargs + else self.specializations + ) + self.execution_kwargs = ( + kwargs["execution_kwargs"] if "execution_kwargs" in kwargs else {} + ) + self.execution_engine = None + + def _execution_engine(self, output_dir) -> ExecutionEngine: + specializations = [s.specialization for s in self.specializations] + kwargs = { + "out_dir": output_dir, + "specializations": specializations, + "failsafe": False, + "sample_format": "xarray", + "dataset_file": self.dataset_filename, + } + kwargs.update(self.execution_kwargs) + + return ExecutionEngine(**kwargs) + + def ntuples_filename(self, filename_prefix) -> str: + return filename_prefix + ".nt" + + def get_execution_id(self) -> str: + if self.execution_id is None: + self.execution_id = ( + (f"harness_execution_{self.protocol_name()}_{datetime.now()}") + .replace(" ", "_") + .replace("-", "_") + .replace(":", "_") + .replace(".", "_") + ) + return self.execution_id + + def generate_artifact(self, harness: "ProtocolHarness"): + self.execution_engine = self._execution_engine(harness.full_output_dir) + self.execution: ProtocolExecution = self.execution_engine.execute( + self.protocol(), + self.agent, + id=self.get_execution_id(), + parameter_values=self.parameter_values, + ) + + try: + self.filename = ( + os.path.join( + harness.full_output_dir, + self.ntuples_filename(harness.filename_prefix()), + ) + if self.filename is None + else self.filename + ) + with open(self.filename, "w") as f: + f.write( + self.protocol().document.write_string(sbol3.SORTED_NTRIPLES).strip() + ) + self.results["filename"] = self.filename + self.status = ProtocolArtifactStatus.PASS + + except Exception as e: + self.status = ProtocolArtifactStatus.FAIL + self.results["exception"] = str(e) + + +class ProtocolExecutionDownstreamArtifact(ProtocolDownstreamArtifact): + protocol_execution_artifact: ProtocolExecutionNTuples = None + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.protocol_execution_artifact = ( + kwargs["protocol_execution_artifact"] + if "protocol_execution_artifact" in kwargs + else None + ) + + +class ProtocolExecutionRubric(ProtocolExecutionDownstreamArtifact): + filename: str = None + overwrite_rubric: bool = False + + def __init__(self, filename, *args, **kwargs): + super().__init__(*args, **kwargs) + self.filename = filename + + self.overwrite_rubric = ( + kwargs["overwrite_rubric"] + if "overwrite_rubric" in kwargs + else self.overwrite_rubric + ) + + def generate_artifact(self, harness: "ProtocolHarness"): + diff = "" + try: + if self.overwrite_rubric: + l.warn( + f"Overwriting rubric at: {self.filename} with {self.protocol_execution_artifact.filename}" + ) + shutil.copyfile( + self.protocol_execution_artifact.filename, self.filename + ) + + diff = file_diff(self.filename, self.protocol_execution_artifact.filename) + + # print(f"Difference: {diff}") + assert filecmp.cmp( + self.protocol_execution_artifact.filename, self.filename + ), "Files are not identical" + self.results["filename"] = self.filename + self.status = ProtocolArtifactStatus.PASS + except Exception as e: + self.results["exception"] = str(e) + self.status = ProtocolArtifactStatus.FAIL + self.results["diff"] = diff + + +class ProtocolExecutionDiagram(ProtocolExecutionDownstreamArtifact): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def diagram_filename(self, filename_prefix: str) -> str: + return filename_prefix + ".execution.diagram" + + def generate_artifact( + self, + harness: "ProtocolHarness", + ): + self.filename = ( + os.path.join( + harness.full_output_dir, + self.diagram_filename(harness.filename_prefix()), + ) + if self.filename is None + else self.filename + ) + try: + self.protocol_execution_artifact.execution.to_dot().render( + self.filename, + cleanup=True, + overwrite_source=True, + ) + self.results["filename"] = self.filename + self.status = ProtocolArtifactStatus.PASS + except Exception as e: + self.results["exception"] = str(e) + self.status = ProtocolArtifactStatus.FAIL + + +class ProtocolSampleTrace(ProtocolExecutionDownstreamArtifact): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def generate_artifact(self, harness: "ProtocolHarness"): + try: + results = glob.glob(f"{harness.full_output_dir}/sample_graph*") + sample_trace_dir = os.path.join(harness.full_output_dir, "sample_traces") + os.makedirs(sample_trace_dir, exist_ok=True) + for i, result in enumerate(results): + # extension = mimetypes.guess_extension(magic.Magic(mime=True).from_file(result)) + shutil.move(result, sample_trace_dir) + self.filename = sample_trace_dir + self.status = ProtocolArtifactStatus.PASS + self.results["filename"] = self.filename + except Exception as e: + self.status = ProtocolArtifactStatus.FAIL + self.results["exception"] = str(e) + l.exception(f"Protocol Sample Trace failed: {e}") + + +class ProtocolSpecialization(ProtocolArtifact): + specialization: BehaviorSpecialization + + def __init__(self, specialization: BehaviorSpecialization) -> None: + super().__init__() + self.specialization = specialization + + def write_output(self, filename_prefix: str): + pass + + def generate_artifact(self, harness: "ProtocolHarness"): + try: + results = self.specialization.data + specialization_classname = self.specialization.__class__.__name__ + specialization_dir = os.path.join( + harness.full_output_dir, specialization_classname + ) + os.makedirs(specialization_dir, exist_ok=True) + for i, result in enumerate(results): + # extension = mimetypes.guess_extension(magic.Magic(mime=True).from_file(result)) + extension = "json" + result_file = os.path.join( + specialization_dir, + f"{specialization_classname}_result_{i}.{extension}", + ) + with open(result_file, "w") as f: + f.write(str(result)) + self.status = ProtocolArtifactStatus.PASS + self.results["filename"] = specialization_dir + except Exception as e: + self.status = ProtocolArtifactStatus.FAIL + self.results["exception"] = str(e) + l.exception(f"Protocol Specialization {self.specialization} failed: {e}") + + +class ProtocolHarness: + namespace: str = None + protocol_name: str = None + protocol_long_name: str = None + protocol_version: str = None + protocol_description: str = None + entry_point: Callable + artifacts: List[ProtocolArtifact] = None + base_artifacts: List[ProtocolArtifact] = None + output_dir: str = None + base_dir: str = None + full_output_dir: str = None + libraries: List[str] = None + parameter_values: List[ParameterValue] = None + execution_id: str = None + agent: Union[sbol3.Agent, str] = None + execution_kwargs: Dict[str, Any] = None + _results: Dict[str, Any] = None + clean_output: bool = False + + def __init__(self, *args, **kwargs): + self.namespace = ( + kwargs["namespace"] if "namespace" in kwargs else "https://labop.io/" + ) + sbol3.set_namespace(self.namespace) + self.protocol_name = ( + kwargs["protocol_name"] if "protocol_name" in kwargs else "default_name" + ) + self.protocol_long_name = ( + kwargs["protocol_long_name"] + if "protocol_long_name" in kwargs + else "default name" + ) + + self.protocol_version = ( + kwargs["protocol_version"] if "protocol_version" in kwargs else "1.0" + ) + + self.protocol_description = ( + kwargs["protocol_description"] + if "protocol_description" in kwargs + else "default description" + ) + + self.clean_output = ( + kwargs["clean_output"] if "clean_output" in kwargs else self.clean_output + ) + + self.execution_kwargs = ( + kwargs["execution_kwargs"] if "execution_kwargs" in kwargs else {} + ) + + self.base_dir = kwargs["base_dir"] if "base_dir" in kwargs else "." + self.output_dir = ( + kwargs["output_dir"] if "output_dir" in kwargs else "artifacts" + ) + self.full_output_dir = os.path.join(self.base_dir, self.output_dir) + + # Store outputs in full_output_dir + os.makedirs(self.full_output_dir, exist_ok=True) + l.info(f"Writing protocol artifacts to: {self.full_output_dir}") + + self.entry_point = kwargs["entry_point"] + self.artifacts = kwargs["artifacts"] if "artifacts" in kwargs else [] + + self.libraries = ( + kwargs["libraries"] + if "libraries" in kwargs + else [ + "liquid_handling", + "plate_handling", + "spectrophotometry", + "sample_arrays", + ] + ) + self.parameter_values = ( + kwargs["parameter_values"] if "parameter_values" in kwargs else [] + ) + self.execution_id = ( + kwargs["execution_id"] if "execution_id" in kwargs else self.execution_id + ) + self.agent = ( + kwargs["agent"] if "agent" in kwargs else sbol3.Agent("labop_harness") + ) + + if "base_artifacts" in kwargs: + self.base_artifacts = kwargs["base_artifacts"] + else: + protocol_artifact = ProtocolNTuples( + namespace=self.namespace, + protocol_name=self.protocol_name, + protocol_long_name=self.protocol_long_name, + protocol_version=self.protocol_version, + protocol_description=self.protocol_description, + ) + + dataset_filename = os.path.join( + self.full_output_dir, self.dataset_filename() + ) + + specializations = [ + a for a in self.artifacts if isinstance(a, ProtocolSpecialization) + ] + + protocol_execution_artifact = ProtocolExecutionNTuples( + protocol_artifact=protocol_artifact, + agent=self.agent, + execution_id=self.execution_id, + parameter_values=self.parameter_values, + specializations=specializations, + dataset_filename=dataset_filename, + execution_kwargs=self.execution_kwargs, + ) + sample_traces = [ + a for a in self.artifacts if isinstance(a, ProtocolSampleTrace) + ] + if len(sample_traces) == 0: + sample_traces = [ + ProtocolSampleTrace( + protocol_execution_artifact=protocol_execution_artifact + ) + ] + self.base_artifacts = ( + kwargs["base_artifacts"] + if "base_artifacts" in kwargs + else [ + protocol_artifact, + ProtocolDiagram(protocol_artifact=protocol_artifact), + protocol_execution_artifact, + ProtocolExecutionDiagram( + protocol_execution_artifact=protocol_execution_artifact + ), + ] + + sample_traces + ) + for a in self.artifacts: + if isinstance(a, ProtocolRubric): + a.protocol_artifact = protocol_artifact + for a in self.artifacts: + if isinstance(a, ProtocolExecutionRubric): + a.protocol_execution_artifact = protocol_execution_artifact + + self.all_artifacts = self.base_artifacts + self.artifacts + self._results = {} + + def filename_prefix(self) -> str: + return self.entry_point.__name__ + + def dataset_filename(self) -> str: + return self.filename_prefix() + ".data.xslx" + + def artifacts_summary(self, verbose=False) -> str: + summary = "" + for a in self.base_artifacts + self.artifacts: + summary += f" - {a.__class__.__name__}" + if verbose: + summary += f": {a.configuration_summary(verbose=verbose)}\n" + else: + summary += "\n" + summary = f""" +{'*'*80} + + LabOP Protocol Harness + + Configuration: + -------------- + Artifacts: +{summary} +{'*'*80} + """ + return summary + + def artifacts_results_summary(self, verbose=False) -> str: + summary = "" + for a in self.base_artifacts + self.artifacts: + summary += f" {'-'*76}\n - {a.__class__.__name__} ({a.status}): \n" + if verbose: + summary += f" {'-'*76}\n{a.results_summary()}\n" + summary = f""" +{'*'*80} + + Harness Results Summary + + Artifacts: +{summary} +{'*'*80} + """ + return summary + + def artifacts_of_type(self, artifact_type) -> List[ProtocolArtifact]: + try: + ea = [a for a in self.all_artifacts if isinstance(a, artifact_type)] + return ea + except Exception as e: + l.exception(f"Could not find an artifacts of type {artifact_type}: {e}") + raise e + + def run(self, verbose=False): + self.initialize(verbose=verbose) + self.main(verbose=verbose) + self.finalize(verbose=verbose) + + def initialize(self, verbose=False): + if self.clean_output: + l.warn(f"Deleting contents of output directory: {self.full_output_dir}") + for root, dirs, files in os.walk(self.full_output_dir): + for f in files: + os.unlink(os.path.join(root, f)) + for d in dirs: + shutil.rmtree(os.path.join(root, d)) + l.info(self.artifacts_summary(verbose=verbose)) + + def errors(self) -> List[ProtocolArtifact]: + return [ + a for a in self.all_artifacts if a.status == ProtocolArtifactStatus.FAIL + ] + + def main(self, verbose=False): + artifact_order = [ + ProtocolNTuples, + ProtocolRubric, + ProtocolDiagram, + ProtocolExecutionNTuples, + ProtocolExecutionRubric, + ProtocolExecutionDiagram, + ProtocolSampleTrace, + ProtocolSpecialization, + ] + for a_type in artifact_order: + for a in self.artifacts_of_type(a_type): + a.generate_artifact(self) + + def finalize(self, verbose=False): + summary = self.artifacts_results_summary(verbose=verbose) + + l.info(summary) + results_file = os.path.join(self.full_output_dir, "harness.out") + with open(results_file, "w") as f: + f.write(self.artifacts_results_summary(verbose=True)) + + +class ProtocolLoader: + filename: str = None + entrypoint_name: str = None + module = None + + def __init__(self, filename: str, entrypoint_name: str): + self.filename = filename + self.entrypoint_name = entrypoint_name + + self.module = self.load_module() + + def load_module(self): + loader = SourceFileLoader(self.entrypoint_name, self.filename) + spec = spec_from_loader(loader.name, loader) + module = module_from_spec(spec) + loader.exec_module(module) + return module + + def generate_protocol(self, doc: sbol3.Document, protocol: Protocol) -> Protocol: + entrypoint = getattr(self.module, self.entrypoint_name) + return entrypoint(doc, protocol) diff --git a/labop/lab_interface.py b/labop/execution/lab_interface.py similarity index 96% rename from labop/lab_interface.py rename to labop/execution/lab_interface.py index 5f2a7d2f..04612448 100644 --- a/labop/lab_interface.py +++ b/labop/execution/lab_interface.py @@ -4,8 +4,8 @@ import xarray as xr from numpy import nan -from .data import serialize_sample_format -from .strings import Strings +from ..data import serialize_sample_format +from ..strings import Strings class LabInterface: diff --git a/labop/lib/liquid_handling.py b/labop/lib/liquid_handling.py index 81d844af..809d9146 100644 --- a/labop/lib/liquid_handling.py +++ b/labop/lib/liquid_handling.py @@ -89,6 +89,7 @@ p.add_input("direction", "http://bioprotocols.org/uml#ValueSpecification") p.add_input("diluent", sbol3.SBOL_COMPONENT) p.add_input("amount", sbol3.OM_MEASURE) # Must be volume +p.add_input("dilution_factor", sbol3.OM_MEASURE, optional=True) doc.add(p) diff --git a/labop/lib/liquid_handling.ttl b/labop/lib/liquid_handling.ttl index 8babd003..70ab21ad 100644 --- a/labop/lib/liquid_handling.ttl +++ b/labop/lib/liquid_handling.ttl @@ -71,7 +71,8 @@ ns1:ownedParameter , , , - ; + , + ; sbol:description "Serial Dilution" ; sbol:displayId "SerialDilution" ; sbol:hasNamespace . @@ -957,6 +958,33 @@ ns1:integerValue 1 ; sbol:displayId "LiteralInteger2" . + a ns1:OrderedPropertyValue, + sbol:Identified ; + ns1:indexValue 4 ; + ns1:propertyValue ; + sbol:displayId "OrderedPropertyValue5" . + + a ns1:Parameter, + sbol:Identified ; + ns1:direction ns1:in ; + ns1:isOrdered true ; + ns1:isUnique true ; + ns1:lowerValue ; + ns1:type om:Measure ; + ns1:upperValue ; + sbol:displayId "Parameter1" ; + sbol:name "dilution_factor" . + + a ns1:LiteralInteger, + sbol:Identified ; + ns1:integerValue 1 ; + sbol:displayId "LiteralInteger1" . + + a ns1:LiteralInteger, + sbol:Identified ; + ns1:integerValue 0 ; + sbol:displayId "LiteralInteger2" . + a ns1:OrderedPropertyValue, sbol:Identified ; ns1:indexValue 0 ; diff --git a/labop/parameter_value.py b/labop/parameter_value.py index 12acac9e..62c0f230 100644 --- a/labop/parameter_value.py +++ b/labop/parameter_value.py @@ -21,6 +21,9 @@ def __hash__(self): def get_parameter(self): return self.parameter.lookup().property_value + def get_name(self): + return self.get_parameter().name + @staticmethod def parameter_value_map( parameter_values: List["ParameterValue"], diff --git a/labop/primitive.py b/labop/primitive.py index 90d8ce37..18625f99 100644 --- a/labop/primitive.py +++ b/labop/primitive.py @@ -12,7 +12,6 @@ from . import inner from .dataset import Dataset -from .lab_interface import LabInterface from .library import loaded_libraries from .sample_array import SampleArray from .sample_data import SampleData @@ -136,7 +135,7 @@ def compute_output( """ Compute the value for parameter given the inputs. This default function will be overridden for specific primitives. :param self: - :param inputs: list of labop.ParameterValue + :param inputs: list of ParameterValue :param parameter: Parameter needing value :return: value """ @@ -312,6 +311,7 @@ def measure_absorbance_compute_output( ): samples = input_map["samples"] wl = input_map["wavelength"] + from labop.execution.lab_interface import LabInterface measurements = LabInterface.measure_absorbance( samples, wl.value, sample_format @@ -337,6 +337,7 @@ def measure_fluorescence_compute_output( exwl = input_map["excitationWavelength"] emwl = input_map["emissionWavelength"] bandpass = input_map["emissionBandpassWidth"] + from labop.execution.lab_interface import LabInterface measurements = LabInterface.measure_fluorescence( samples, @@ -405,7 +406,7 @@ def compute_metadata_compute_output( and parameter.type == "http://bioprotocols.org/labop#SampleMetadata" ): for_samples = input_map["for_samples"] - metadata = labop.SampleMetadata.from_sample_graph(for_samples, engine) + metadata = SampleMetadata.from_sample_graph(for_samples, engine) return metadata def transfer_by_map_compute_output( @@ -424,9 +425,7 @@ def transfer_by_map_compute_output( spec = source.container_type contents = self.transfer_out(source, target, plan, sample_format) name = f"{parameter.name}" - result = labop.SampleArray( - name=name, container_type=spec, contents=contents - ) + result = SampleArray(name=name, container_type=spec, contents=contents) elif ( parameter.name == "destinationResult" and parameter.type == "http://bioprotocols.org/labop#SampleCollection" @@ -438,9 +437,7 @@ def transfer_by_map_compute_output( spec = source.container_type contents = self.transfer_in(source, target, plan, sample_format) name = f"{parameter.name}" - result = labop.SampleArray( - name=name, container_type=spec, contents=contents - ) + result = SampleArray(name=name, container_type=spec, contents=contents) return result primitive_to_output_function = { diff --git a/labop/protocol.py b/labop/protocol.py index 522c85d8..a6a3d372 100644 --- a/labop/protocol.py +++ b/labop/protocol.py @@ -21,6 +21,7 @@ ObjectNode, ValueSpecification, ) +from uml.call_behavior_action import CallBehaviorAction from uml.utils import WellFormednessError, WellFormednessIssue from . import inner @@ -102,6 +103,22 @@ def primitive_step(self, primitive: Primitive, **input_pin_map): self.last_step = pe # update the last step return pe + def make_decision_input_activity( + self, + decision_input_behavior: Behavior, + decision_input_source: ActivityNode = None, + ) -> CallBehaviorAction: + input_pin_map = ( + {"decision_input": decision_input_source} + if decision_input_source is not None + else {} + ) + + decision_input = self.execute_primitive( + decision_input_behavior, **input_pin_map + ) + return decision_input + def make_decision_node( self, primary_incoming_node: ActivityNode, @@ -121,37 +138,36 @@ def make_decision_node( """ assert primary_incoming_node - primary_incoming_flow = ( - ControlFlow(source=primary_incoming_node) - if isinstance(primary_incoming_node, ControlNode) - else ObjectFlow(source=primary_incoming_node) - ) - self.edges.append(primary_incoming_flow) - decision_input = None - - if decision_input_behavior: - input_pin_map = {} - decision_input_control = None - if decision_input_source: - input_pin_map["decision_input"] = decision_input_source - if primary_incoming_node: - if isinstance(primary_incoming_node, ObjectNode): - input_pin_map["primary_input"] = primary_incoming_node - else: - # Make a ControlFlow so that decision_input executes first - decision_input_control = ControlFlow(source=primary_incoming_node) - - decision_input = self.execute_primitive( - decision_input_behavior, **input_pin_map + decision_input = ( + self.make_decision_input_activity( + decision_input_behavior, + decision_input_source=decision_input_source, ) - if decision_input_control: - decision_input_control.target = decision_input - self.edges.append(decision_input_control) + if decision_input_behavior is not None + else None + ) + # Link decision input flow decision_input_flow = None - if decision_input_source: - decision_input_flow = ObjectFlow(source=decision_input_source) + + if decision_input: + # if decision_input_source is not None: + # # link decision_input_source to decision_input + # decision_input_flow = ObjectFlow( + # source=decision_input_source, target=decision_input.input_pin("decision_input") + # ) + # self.edges.append(decision_input_flow) + + # Order decision input after primary incoming node + decision_input_control = ControlFlow( + source=primary_incoming_node, target=decision_input + ) + self.edges.append(decision_input_control) + elif decision_input_source is not None: + decision_input_flow = ObjectFlow( + source=decision_input_source, target=decision + ) self.edges.append(decision_input_flow) decision = DecisionNode( @@ -161,15 +177,20 @@ def make_decision_node( self.nodes.append(decision) if decision_input: - # Flow that communicates the return value of the decision_input behavior execution to the decision + # Link Flow that communicates the return value of the decision_input behavior execution to the decision decision_input_to_decision_flow = ObjectFlow( source=decision_input.output_pin("return"), target=decision ) self.edges.append(decision_input_to_decision_flow) - primary_incoming_flow.target = decision - if decision_input_flow: - decision_input_flow.target = decision + # Control nodes and CallBehaviorAction nodes provide control flow. ActivityParameterNode and Pins provide object flows + primary_incoming_flow = ( + ControlFlow(source=primary_incoming_node, target=decision) + if isinstance(primary_incoming_node, ControlNode) + or isinstance(primary_incoming_node, CallBehaviorAction) + else ObjectFlow(source=primary_incoming_node) + ) + self.edges.append(primary_incoming_flow) # Make edges for outgoing_targets if outgoing_targets: @@ -256,3 +277,9 @@ def remove_duplicates(self): def auto_advance(self): return True + + def get_behaviors(self) -> List[Behavior]: + activities = [ + n.get_behavior() for n in self.nodes if isinstance(n, ActivityNode) + ] + return activities diff --git a/labop/protocol_execution.py b/labop/protocol_execution.py index e27d3a39..38f7bda0 100644 --- a/labop/protocol_execution.py +++ b/labop/protocol_execution.py @@ -26,10 +26,6 @@ from . import inner from .behavior_execution import BehaviorExecution from .call_behavior_execution import CallBehaviorExecution -from .execution_engine_utils import ( - JSONProtocolExecutionExtractor, - ProtocolExecutionExtractor, -) from .material import Material from .protocol import Protocol from .sample_data import SampleData @@ -39,6 +35,9 @@ class ProtocolExecution(inner.ProtocolExecution, BehaviorExecution): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + def get_protocol(self) -> Protocol: + return self.protocol.lookup() + def get_ordered_executions(self): protocol = self.protocol.lookup() try: @@ -341,8 +340,15 @@ def to_dot( def backtrace( self, stack=None, - extractor: ProtocolExecutionExtractor = JSONProtocolExecutionExtractor(), + extractor: "ProtocolExecutionExtractor" = None, ): + from labop.execution.execution_engine_utils import ( + JSONProtocolExecutionExtractor, + ) + + if extractor is None: + extractor = JSONProtocolExecutionExtractor() + stack = self.executions if stack is None else stack if len(stack) == 0: return set([]), [] @@ -358,6 +364,10 @@ def to_json(self): """ Convert Protocol Execution to JSON """ + from labop.execution.execution_engine_utils import ( + JSONProtocolExecutionExtractor, + ) + p_json = self.backtrace(extractor=JSONProtocolExecutionExtractor())[1] return json.dumps(p_json) diff --git a/labop/sample_mask.py b/labop/sample_mask.py index 3eb39ce3..91b3e888 100644 --- a/labop/sample_mask.py +++ b/labop/sample_mask.py @@ -10,7 +10,7 @@ from .data import deserialize_sample_format, serialize_sample_format from .sample_collection import SampleCollection from .strings import Strings -from .utils import contiguous_coordinates +from .utils.plate_coordinates import contiguous_coordinates class SampleMask(inner.SampleMask, SampleCollection): diff --git a/labop/utils/harness.py b/labop/utils/harness.py deleted file mode 100644 index b75d8619..00000000 --- a/labop/utils/harness.py +++ /dev/null @@ -1,305 +0,0 @@ -import logging -import os -from abc import ABC -from datetime import datetime -from typing import Callable, List - -import sbol3 -from isort import file - -from labop.execution_engine import ExecutionEngine -from labop.library import import_library -from labop.parameter_value import ParameterValue -from labop.protocol import Protocol -from labop.utils.helpers import prepare_document -from labop_convert import BehaviorSpecialization -from labop_convert.behavior_specialization import BehaviorSpecialization - -l = logging.Logger(__file__) -l.setLevel(logging.INFO) -ConsoleOutputHandler = logging.StreamHandler() -l.addHandler(ConsoleOutputHandler) - - -class ProtocolArtifact(ABC): - summary: str = "" - - def summary(self): - return "" - - def results_summary(self): - return self._summary - - -class ProtocolDiagram(ProtocolArtifact): - pass - - -class ProtocolNTuples(ProtocolArtifact): - pass - - -class ProtocolExecutionNTuples(ProtocolArtifact): - pass - - -class ProtocolExecutionDiagram(ProtocolArtifact): - pass - - -class ProtocolSampleTrace(ProtocolArtifact): - pass - - -class ProtocolSpecialization(ProtocolArtifact): - specialization: BehaviorSpecialization - - def __init__(self, specialization: BehaviorSpecialization) -> None: - super().__init__() - self.specialization = specialization - - def write_output(self, filename_prefix: str): - pass - - -class ProtocolHarness: - entry_point: Callable - artifacts: List[ProtocolArtifact] = [] - base_artifacts: List[ProtocolArtifact] = [ - ProtocolNTuples(), - ProtocolDiagram(), - ProtocolExecutionDiagram(), - ProtocolSampleTrace(), - ProtocolExecutionNTuples(), - ] - namespace: str - protocol_name: str - protocol_long_name: str - protocol_version: str - protocol_description: str - output_dir: str = "artifacts" - libraries: List[str] = [ - "liquid_handling", - "plate_handling", - "spectrophotometry", - "sample_arrays", - ] - parameter_values: List[ParameterValue] = [] - execution_id: str = None - agent: sbol3.Agent = sbol3.Agent("labop_harness") - _doc: sbol3.Document = None - _protocol: Protocol = None - - def __init__(self, *args, **kwargs): - self.entry_point = kwargs["entry_point"] - self.artifacts = ( - kwargs["artifacts"] if "artifacts" in kwargs else self.artifacts - ) - self.artifacts = ( - kwargs["base_artifacts"] - if "base_artifacts" in kwargs - else self.base_artifacts - ) - self.namespace = kwargs["namespace"] - self.protocol_name = kwargs["protocol_name"] - self.protocol_long_name = kwargs["protocol_long_name"] - self.protocol_version = kwargs["protocol_version"] - self.protocol_description = kwargs["protocol_description"] - self.output_dir = ( - kwargs["output_dir"] if "output_dir" in kwargs else self.output_dir - ) - self.libraries = ( - kwargs["libraries"] if "libraries" in kwargs else self.libraries - ) - self.parameter_values = ( - kwargs["parameter_values"] - if "parameter_values" in kwargs - else self.parameter_values - ) - self.execution_id = ( - kwargs["execution_id"] if "execution_id" in kwargs else self.execution_id - ) - self.agent = kwargs["agent"] if "agent" in kwargs else self.agent - self._doc = None - self._protocol = None - - def import_libraries(self): - for library in self.libraries: - import_library(library) - - def generate_protocol(self) -> Protocol: - self.import_libraries() - self._protocol = Protocol(self.protocol_name) - self._protocol.name = self.protocol_long_name - self._protocol.version = self.protocol_version - self._protocol.description = self.protocol_description - self._doc.add(self._protocol) - self._protocol = self.entry_point(self._doc, self._protocol) - l.info("Validating and writing protocol") - v = self._doc.validate() - assert len(v) == 0, "".join(f"\n {e}" for e in v) - - return self._protocol - - def prepare_document(self) -> sbol3.Document: - self._doc = prepare_document(namespace=self.namespace) - return self._doc - - def filename_prefix(self) -> str: - return self.entry_point.__name__ - - def ntuples_filename(self) -> str: - return self.filename_prefix() + ".nt" - - def diagram_filename(self) -> str: - return self.filename_prefix() + ".diagram" - - def dataset_filename(self) -> str: - return self.filename_prefix() + ".data.xslx" - - def read_protocol(self, filename: str = None): - filename = self.ntuples_filename() if filename is None else filename - self.prepare_document() - self._doc.read(filename, "nt") - self._protocol = doc.find(f"{self.namespace}{self.protocol_name}") - - return self._protocol, self._doc - - def execution_engine( - self, - specializations: List[BehaviorSpecialization], - dataset_filename: str, - ) -> ExecutionEngine: - return ExecutionEngine( - out_dir=self.output_dir, - specializations=specializations, - failsafe=False, - sample_format="xarray", - dataset_file=dataset_filename, - ) - - def get_execution_id(self) -> str: - if self.execution_id is None: - self.execution_id = ( - (f"harness_execution_{self.protocol_name}_{datetime.now()}") - .replace(" ", "_") - .replace("-", "_") - .replace(":", "_") - .replace(".", "_") - ) - return self.execution_id - - def artifacts_summary(self) -> str: - summary = "" - for a in self.artifacts: - summary += f" - {a.__class__.__name__}: {a.summary()}\n" - return summary - - def artifacts_results_summary(self) -> str: - summary = "" - for a in self.artifacts: - summary += f" - {a.__class__.__name__}: {a.results_summary()}\n" - return summary - - def run(self, base_dir="."): - l.info( - f""" -{'*'*80} - - LabOP Protocol Harness - - Configuration: - -------------- - Artifacts: -{self.artifacts_summary()} -{'*'*80} - """ - ) - full_output_dir = os.path.join(base_dir, self.output_dir) - # Store outputs in full_output_dir - os.makedirs(full_output_dir, exist_ok=True) - l.info("Writing protocol artifacts to: {full_output_dir}") - - all_artifacts = self.base_artifacts + self.artifacts - - generate_nt_file = any( - a for a in all_artifacts if isinstance(a, ProtocolNTuples) - ) - nt_filename = os.path.join(full_output_dir, self.ntuples_filename()) - - # 1) Get the self._protocol either by generating it or reading it - if generate_nt_file: - self.prepare_document() - self.generate_protocol() - else: - l.info(f"Bypassing Protocol Generation, looking for existing .nt file ...") - if os.path.exists(nt_filename): - l.info(f"Found .nt file: {nt_filename}") - self.read_protocol() - - # 2) Create any protocol-specific artifacts - if generate_nt_file: - with open(nt_filename, "w") as f: - l.info(f"Saving protocol [{nt_filename}].") - f.write(self._doc.write_string(sbol3.SORTED_NTRIPLES).strip()) - if any(a for a in all_artifacts if isinstance(a, ProtocolDiagram)): - self._protocol.to_dot().render( - os.path.join(full_output_dir, self.diagram_filename()), - cleanup=True, - ) - - # 3) Generate execution-specific artifacts - sample_trace = any( - a for a in all_artifacts if isinstance(a, ProtocolSampleTrace) - ) - dataset_filename = ( - os.path.join(full_output_dir, self.dataset_filename()) - if sample_trace - else None - ) - - specializations = [ - a for a in all_artifacts if isinstance(a, ProtocolSpecialization) - ] - - ee = self.execution_engine( - [s.specialization for s in specializations], dataset_filename - ) - - execution = ee.execute( - self._protocol, - self.agent, - id=self.get_execution_id(), - parameter_values=self.parameter_values, - ) - - if any(a for a in all_artifacts if isinstance(a, ProtocolExecutionNTuples)): - with open(nt_filename, "w") as f: - f.write(self._doc.write_string(sbol3.SORTED_NTRIPLES).strip()) - - for specialization in specializations: - results = specialization.output() - specialization_classname = specialization.__class__.__name__ - specialization_dir = os.path.join(full_output_dir, specialization_classname) - os.makedirs(specialization_dir, exist_ok=True) - for i, result in enumerate(results): - # extension = mimetypes.guess_extension(magic.Magic(mime=True).from_file(result)) - extension = "json" - result_file = os.path.join( - specialization_dir, - f"{specialization_classname}_result_{i}.{extension}", - ) - with open(result_file, "w") as f: - f.write(result) - - l.info( - f""" -{'*'*80} - - Harness Results Summary - - Artifacts: -{self.artifacts_results_summary()} -{'*'*80} - """ - ) diff --git a/labop_convert/behavior_specialization.py b/labop_convert/behavior_specialization.py index 03671da2..4b1b20ea 100644 --- a/labop_convert/behavior_specialization.py +++ b/labop_convert/behavior_specialization.py @@ -6,7 +6,6 @@ import tyto -from labop import Protocol, ProtocolExecution from uml import CallBehaviorAction l = logging.getLogger(__file__) @@ -82,7 +81,7 @@ def output(self) -> List[Any]: results = self.data return results - def process(self, record, execution: ProtocolExecution, timepoint="start"): + def process(self, record, execution: "ProtocolExecution", timepoint="start"): try: node = record.node.lookup() if not isinstance(node, CallBehaviorAction): @@ -90,6 +89,8 @@ def process(self, record, execution: ProtocolExecution, timepoint="start"): elif node.get_parent().identity in self.mapped_subprotocols: return + from labop import Protocol + # Subprotocol specializations behavior = node.behavior.lookup() if ( diff --git a/labop_convert/emeraldcloud/ecl_specialization.py b/labop_convert/emeraldcloud/ecl_specialization.py index 2ecfc510..82588c3a 100644 --- a/labop_convert/emeraldcloud/ecl_specialization.py +++ b/labop_convert/emeraldcloud/ecl_specialization.py @@ -106,7 +106,7 @@ def handle_process_failure(self, record, exception): super().handle_process_failure(record, exception) self.script_steps.append(f"# Failure processing record: {record.identity}") - def on_begin(self, ex: labop.ProtocolExecution): + def on_begin(self, ex: "ProtocolExecution"): protocol = self.execution.protocol.lookup() self.data = [] @@ -142,13 +142,13 @@ def _compile_script(self): return script def define_container( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + self, record: "ActivityNodeExecution", ex: "ProtocolExecution" ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - spec = parameter_value_map["specification"]["value"] - samples = parameter_value_map["samples"]["value"] + spec = parameter_value_map["specification"] + samples = parameter_value_map["samples"] name = spec.name if spec.name else spec.display_id container_types = self.resolve_container_spec(spec) @@ -167,17 +167,17 @@ def define_container( def vortex( self, - record: labop.ActivityNodeExecution, - execution: labop.ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() duration = None if "duration" in parameter_value_map: duration_measure = ecl_measure( - parameter_value_map["duration"]["value"], use_star=True + parameter_value_map["duration"], use_star=True ) - samples = parameter_value_map["samples"]["value"] + samples = parameter_value_map["samples"] spec = samples.get_container_type() if str(spec) in self.resolutions: sample = self.resolutions[str(spec)] @@ -197,26 +197,20 @@ def vortex( else: self.script_steps += [text] - def time_wait( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution - ): + def time_wait(self, record: "ActivityNodeExecution", ex: "ProtocolExecution"): results = {} call = record.call.lookup() parameter_value_map = call.parameter_value_map() - value = parameter_value_map["amount"]["value"].value - units = parameter_value_map["amount"]["value"].unit + value = parameter_value_map["amount"].value + units = parameter_value_map["amount"].unit self.script_steps += [f"time.sleep(value)"] - def provision( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution - ): + def provision(self, record: "ActivityNodeExecution", ex: "ProtocolExecution"): results = {} call = record.call.lookup() parameter_value_map = call.parameter_value_map() - destination = parameter_value_map["destination"]["value"] - resource = source = self.resolutions[ - parameter_value_map["resource"]["value"].identity - ] + destination = parameter_value_map["destination"] + resource = source = self.resolutions[parameter_value_map["resource"].identity] if type(destination) is labop.SampleMask: dest_container = destination.source.lookup().container_type.lookup() @@ -225,7 +219,7 @@ def provision( dest_container = destination.container_type.lookup() dest_wells = None - amount = ecl_measure(parameter_value_map["amount"]["value"]) + amount = ecl_measure(parameter_value_map["amount"]) text = ecl_transfer( source, f'"{dest_container}"', amount, dest_wells=dest_wells ) @@ -235,15 +229,13 @@ def provision( # else: self.script_steps += [text] - def transfer_to( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution - ): + def transfer_to(self, record: "ActivityNodeExecution", ex: "ProtocolExecution"): results = {} call = record.call.lookup() parameter_value_map = call.parameter_value_map() - source = parameter_value_map["source"]["value"] - destination = parameter_value_map["destination"]["value"] - amount = ecl_measure(parameter_value_map["amount"]["value"]) + source = parameter_value_map["source"] + destination = parameter_value_map["destination"] + amount = ecl_measure(parameter_value_map["amount"]) if type(source) is labop.SampleMask: source_container = source.source.lookup().container_type.lookup() @@ -278,35 +270,33 @@ def transfer_to( # else: self.script_steps += [text] - def transfer_by_map( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution - ): + def transfer_by_map(self, record: "ActivityNodeExecution", ex: "ProtocolExecution"): results = {} call = record.call.lookup() parameter_value_map = call.parameter_value_map() - destination = parameter_value_map["destination"]["value"] - source = parameter_value_map["source"]["value"] - plan = parameter_value_map["plan"]["value"] - temperature = parameter_value_map["temperature"]["value"] - value = parameter_value_map["amount"]["value"].value + destination = parameter_value_map["destination"] + source = parameter_value_map["source"] + plan = parameter_value_map["plan"] + temperature = parameter_value_map["temperature"] + value = parameter_value_map["amount"].value def plate_coordinates( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + self, record: "ActivityNodeExecution", ex: "ProtocolExecution" ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - source = parameter_value_map["source"]["value"] - coords = parameter_value_map["coordinates"]["value"] - samples = parameter_value_map["samples"]["value"] + source = parameter_value_map["source"] + coords = parameter_value_map["coordinates"] + samples = parameter_value_map["samples"] def measure_absorbance( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + self, record: "ActivityNodeExecution", ex: "ProtocolExecution" ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - wavelength = ecl_measure(parameter_value_map["wavelength"]["value"]) - samples = parameter_value_map["samples"]["value"] + wavelength = ecl_measure(parameter_value_map["wavelength"]) + samples = parameter_value_map["samples"] if type(samples) is labop.SampleMask: samples = samples.source.lookup() @@ -324,21 +314,21 @@ def measure_absorbance( self.script_steps += [text] def measure_fluorescence( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + self, record: "ActivityNodeExecution", ex: "ProtocolExecution" ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - excitation = ecl_measure(parameter_value_map["excitationWavelength"]["value"]) - emission = ecl_measure(parameter_value_map["emissionWavelength"]["value"]) - bandpass = ecl_measure(parameter_value_map["emissionBandpassWidth"]["value"]) - samples = parameter_value_map["samples"]["value"] + excitation = ecl_measure(parameter_value_map["excitationWavelength"]) + emission = ecl_measure(parameter_value_map["emissionWavelength"]) + bandpass = ecl_measure(parameter_value_map["emissionBandpassWidth"]) + samples = parameter_value_map["samples"] timepoints = ( - parameter_value_map["timepoints"]["value"] + parameter_value_map["timepoints"] if "timepoints" in parameter_value_map else None ) - measurements = parameter_value_map["measurements"]["value"] + measurements = parameter_value_map["measurements"] if type(samples) is labop.SampleMask: samples = samples.source.lookup() @@ -353,80 +343,70 @@ def measure_fluorescence( ]""" self.script_steps += [text] - def define_rack( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution - ): + def define_rack(self, record: "ActivityNodeExecution", ex: "ProtocolExecution"): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - spec = parameter_value_map["specification"]["value"] - slots = parameter_value_map["slots"]["value"] + spec = parameter_value_map["specification"] + slots = parameter_value_map["slots"] def load_container_in_rack( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + self, record: "ActivityNodeExecution", ex: "ProtocolExecution" ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() container: labop.ContainerSpec = parameter_value_map["container"]["value"] coords: str = ( - parameter_value_map["coordinates"]["value"] + parameter_value_map["coordinates"] if "coordinates" in parameter_value_map else "A1" ) - slots: labop.SampleCollection = parameter_value_map["slots"]["value"] - samples: labop.SampleMask = parameter_value_map["samples"]["value"] + slots: "SampleCollection" = parameter_value_map["slots"] + samples: labop.SampleMask = parameter_value_map["samples"] def load_container_on_instrument( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution + self, record: "ActivityNodeExecution", ex: "ProtocolExecution" ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - container_spec: labop.ContainerSpec = parameter_value_map["specification"][ - "value" - ] + container_spec: labop.ContainerSpec = parameter_value_map["specification"] slots: str = ( - parameter_value_map["slots"]["value"] - if "slots" in parameter_value_map - else "A1" + parameter_value_map["slots"] if "slots" in parameter_value_map else "A1" ) - instrument: sbol3.Agent = parameter_value_map["instrument"]["value"] - samples: labop.SampleArray = parameter_value_map["samples"]["value"] + instrument: sbol3.Agent = parameter_value_map["instrument"] + samples: labop.SampleArray = parameter_value_map["samples"] - def load_racks( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution - ): + def load_racks(self, record: "ActivityNodeExecution", ex: "ProtocolExecution"): call = record.call.lookup() node = record.node.lookup() parameter_value_map = call.parameter_value_map() coords: str = ( - parameter_value_map["coordinates"]["value"] + parameter_value_map["coordinates"] if "coordinates" in parameter_value_map else "1" ) - rack: labop.ContainerSpec = parameter_value_map["rack"]["value"] + rack: labop.ContainerSpec = parameter_value_map["rack"] - def configure_robot( - self, record: labop.ActivityNodeExecution, ex: labop.ProtocolExecution - ): + def configure_robot(self, record: "ActivityNodeExecution", ex: "ProtocolExecution"): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - instrument = parameter_value_map["instrument"]["value"] - mount = parameter_value_map["mount"]["value"] + instrument = parameter_value_map["instrument"] + mount = parameter_value_map["mount"] def pcr( self, - record: labop.ActivityNodeExecution, - execution: labop.ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - cycles = parameter_value_map["cycles"]["value"] - annealing_temp = parameter_value_map["annealing_temp"]["value"] - extension_temp = parameter_value_map["extension_temp"]["value"] - denaturation_temp = parameter_value_map["denaturation_temp"]["value"] - annealing_time = parameter_value_map["annealing_time"]["value"] - extension_time = parameter_value_map["extension_time"]["value"] - denaturation_time = parameter_value_map["denaturation_time"]["value"] + cycles = parameter_value_map["cycles"] + annealing_temp = parameter_value_map["annealing_temp"] + extension_temp = parameter_value_map["extension_temp"] + denaturation_temp = parameter_value_map["denaturation_temp"] + annealing_time = parameter_value_map["annealing_time"] + extension_time = parameter_value_map["extension_time"] + denaturation_time = parameter_value_map["denaturation_time"] def get_instrument_deck(self, instrument: sbol3.Agent) -> str: for deck, agent in self.configuration.items(): @@ -438,15 +418,15 @@ def get_instrument_deck(self, instrument: sbol3.Agent) -> str: def serial_dilution( self, - record: labop.ActivityNodeExecution, - execution: labop.ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - source = parameter_value_map["samples"]["value"] - destination = parameter_value_map["samples"]["value"] - amount = ecl_measure(parameter_value_map["amount"]["value"]) + source = parameter_value_map["samples"] + destination = parameter_value_map["samples"] + amount = ecl_measure(parameter_value_map["amount"]) if isinstance(source, labop.SampleMask): source = source.source.lookup() @@ -483,17 +463,17 @@ def serial_dilution( def resuspend( self, - record: labop.ActivityNodeExecution, - execution: labop.ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): pass # call = record.call.lookup() # parameter_value_map = call.parameter_value_map() - # source = parameter_value_map["source"]["value"] - # destination = parameter_value_map["destination"]["value"] - # amount = ecl_measure(parameter_value_map["amount"]["value"]) + # source = parameter_value_map["source"] + # destination = parameter_value_map["destination"] + # amount = ecl_measure(parameter_value_map["amount"]) # if isinstance(source, labop.SampleMask): # source = source.source.lookup() @@ -524,17 +504,15 @@ def resuspend( # ] """ # ] - def prepare_solution( - self, record: labop.ActivityNodeExecution, execution: labop.Protocol - ): + def prepare_solution(self, record: "ActivityNodeExecution", execution: "Protocol"): call = record.call.lookup() parameter_value_map = call.parameter_value_map() - spec = parameter_value_map["specification"]["value"] + spec = parameter_value_map["specification"] self.current_independent_subprotocol = spec.name - buffer_container = parameter_value_map["buffer_container"]["value"] - buffer = parameter_value_map["buffer"]["value"] + buffer_container = parameter_value_map["buffer_container"] + buffer = parameter_value_map["buffer"] if ( buffer_container.identity in self.resolutions and not self.create_stock_solutions @@ -544,18 +522,14 @@ def prepare_solution( resource = self.resolutions[buffer.identity] else: resource = f'"{buffer_container.name}"' - buffer_vol = ecl_measure( - parameter_value_map["buffer_volume"]["value"], use_star=True - ) + buffer_vol = ecl_measure(parameter_value_map["buffer_volume"], use_star=True) - reagent = parameter_value_map["reagent"]["value"] + reagent = parameter_value_map["reagent"] if reagent.identity in self.resolutions: reagent_resource = self.resolutions[reagent.identity] else: reagent_resource = f'"{reagent.name}"' - reagent_mass = ecl_measure( - parameter_value_map["reagent_mass"]["value"], use_star=True - ) + reagent_mass = ecl_measure(parameter_value_map["reagent_mass"], use_star=True) if self.create_stock_solutions: # Generate a stock solution recipe @@ -578,18 +552,18 @@ def prepare_solution( ] def finalize_prepare_solution( - self, record: labop.ActivityNodeExecution, execution: labop.Protocol + self, record: "ActivityNodeExecution", execution: "Protocol" ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() self.current_independent_subprotocol = None - spec = parameter_value_map["specification"]["value"] + spec = parameter_value_map["specification"] # self.independent_subprotocol_steps[spec.name] += ["}]"] def prepare_reagents( self, - record: labop.ActivityNodeExecution, - execution: labop.ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): pass @@ -659,7 +633,7 @@ def ecl_measure(measure: sbol3.Measure, use_star=False): raise ValueError(tyto.OM.get_term_by_uri(measure.unit) + " is not a supported unit") -def ecl_coordinates(samples: labop.SampleCollection, sample_format=Strings.XARRAY): +def ecl_coordinates(samples: "SampleCollection", sample_format=Strings.XARRAY): if type(samples) is labop.SampleMask: coordinates = flatten_coordinates( samples.sample_coordinates(sample_format=sample_format, as_list=True), diff --git a/labop_convert/markdown/markdown_specialization.py b/labop_convert/markdown/markdown_specialization.py index 7c1f2aa5..8ea3bab0 100644 --- a/labop_convert/markdown/markdown_specialization.py +++ b/labop_convert/markdown/markdown_specialization.py @@ -12,18 +12,11 @@ import tyto import xarray as xr -from labop import ( - ActivityNodeExecution, - ContainerSpec, - Dataset, - ParameterValue, - ProtocolExecution, - SampleArray, - SampleCollection, - SampleMask, - Strings, - deserialize_sample_format, -) +from labop import SampleMask +from labop.data import deserialize_sample_format +from labop.sample_array import SampleArray +from labop.sample_collection import SampleCollection +from labop.strings import Strings from labop_convert.behavior_specialization import DefaultBehaviorSpecialization from uml import ( PARAMETER_IN, @@ -73,7 +66,7 @@ def __init__( self.sample_format = sample_format self.output_subprotocol_inputs = output_subprotocol_inputs - def initialize_protocol(self, execution: ProtocolExecution, out_dir=None): + def initialize_protocol(self, execution: "ProtocolExecution", out_dir=None): super().initialize_protocol(execution, out_dir=out_dir) print(f"Initializing execution {execution.display_id}") # Defines sections of the markdown document @@ -243,7 +236,9 @@ def _materials_markdown(self, protocol, subprotocol_executions): markdown += x.materials return markdown - def _parameter_value_markdown(self, pv: ParameterValue, is_output=False): + def _parameter_value_markdown(self, pv: "ParameterValue", is_output=False): + from labop import Dataset + parameter = pv.parameter.lookup().property_value value = pv.value if isinstance(value, sbol3.Measure): @@ -262,7 +257,7 @@ def _parameter_value_markdown(self, pv: ParameterValue, is_output=False): def _parameter_markdown(self, p: Parameter): return f"* `{p.name}`\n" - def _steps_markdown(self, execution: ProtocolExecution, subprotocol_executions): + def _steps_markdown(self, execution: "ProtocolExecution", subprotocol_executions): markdown = "\n\n## Steps\n" markdown = "" for x in subprotocol_executions: @@ -272,7 +267,7 @@ def _steps_markdown(self, execution: ProtocolExecution, subprotocol_executions): markdown += str(i + 1) + ". " + step + "\n" return markdown - def on_end(self, execution: ProtocolExecution): + def on_end(self, execution: "ProtocolExecution"): protocol = execution.protocol.lookup() subprotocol_executions = execution.get_subprotocol_executions() execution.header += self._header_markdown(protocol) @@ -334,7 +329,9 @@ def on_end(self, execution: ProtocolExecution): self.data = execution.markdown - def reporting_step(self, execution: ProtocolExecution): + def reporting_step(self, execution: "ProtocolExecution"): + from labop import Dataset + output_parameters = [] for i in execution.parameter_values: parameter = i.parameter.lookup() @@ -352,8 +349,8 @@ def reporting_step(self, execution: ProtocolExecution): def define_container( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): results = {} call = record.call.lookup() @@ -404,8 +401,8 @@ def define_container( def define_containers( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): results = {} call = record.call.lookup() @@ -425,6 +422,9 @@ def define_containers( # primitive_execution.py samples.initial_contents = quote(json.dumps({})) samples.format = "json" + + from labop import ContainerSpec + assert type(containers) is ContainerSpec try: # Assume that a simple container class is specified, rather @@ -454,8 +454,8 @@ def define_containers( def provision_container( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): results = {} call = record.call.lookup() @@ -490,8 +490,8 @@ def provision_container( def plate_coordinates( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): results = {} call = record.call.lookup() @@ -513,8 +513,8 @@ def plate_coordinates( def measure_absorbance( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): results = {} call = record.call.lookup() @@ -568,8 +568,8 @@ def measure_absorbance( def measure_fluorescence( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): results = {} call = record.call.lookup() @@ -616,8 +616,8 @@ def measure_fluorescence( def vortex( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -626,7 +626,7 @@ def vortex( duration_measure = parameter_value_map["duration"] duration_scalar = duration_measure.value duration_units = tyto.OM.get_term_by_uri(duration_measure.unit) - samples = parameter_value_map["samples"]["value"] + samples = parameter_value_map["samples"] # Add to markdown text = f"Vortex `{samples.name}`" @@ -637,8 +637,8 @@ def vortex( def discard( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -666,9 +666,11 @@ def discard( def transfer( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): + from labop import SampleArray + call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -807,8 +809,8 @@ def transfer( def transfer_by_map( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -888,8 +890,8 @@ def transfer_by_map( def culture( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -939,8 +941,8 @@ def culture( def incubate( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -963,8 +965,8 @@ def incubate( def hold( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -981,8 +983,8 @@ def hold( def hold_on_ice( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -998,8 +1000,8 @@ def hold_on_ice( def dilute_to_target_od( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1039,8 +1041,8 @@ def dilute_to_target_od( def dilute( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1090,8 +1092,8 @@ def dilute( def transform( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1149,8 +1151,8 @@ def transform( def serial_dilution( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): # FIXME: # num transfers: from samplegraph @@ -1161,10 +1163,10 @@ def serial_dilution( call = record.call.lookup() parameter_value_map = call.parameter_value_map() - samples = parameter_value_map["samples"]["value"] - direction = parameter_value_map["direction"]["value"] - amount = parameter_value_map["amount"]["value"] - diluent = parameter_value_map["diluent"]["value"] + samples = parameter_value_map["samples"] + direction = parameter_value_map["direction"] + amount = parameter_value_map["amount"] + diluent = parameter_value_map["diluent"] sample_array = samples.to_data_array() dilution_factor = 2 # FIXME need to calculate from amount and sample graph @@ -1179,7 +1181,7 @@ def serial_dilution( samples_coordinates = samples.sample_coordinates( sample_format=self.sample_format ) - if isinstance(samples, labop.SampleMask): + if isinstance(samples, SampleMask): samples = samples.source.lookup() # Get samples container type @@ -1210,8 +1212,8 @@ def serial_dilution( def evaporative_seal( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1231,8 +1233,8 @@ def evaporative_seal( def unseal( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1251,8 +1253,8 @@ def unseal( def pool_samples( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1286,8 +1288,8 @@ def pool_samples( def quick_spin( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1307,15 +1309,15 @@ def quick_spin( def subprotocol_specialization( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): pass def embedded_image( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1329,8 +1331,8 @@ def embedded_image( def culture_plates( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1352,8 +1354,8 @@ def culture_plates( def pick_colonies( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1373,8 +1375,8 @@ def pick_colonies( def excel_metadata( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1388,8 +1390,8 @@ def excel_metadata( def join_metadata( self, - record: ActivityNodeExecution, - execution: ProtocolExecution, + record: "ActivityNodeExecution", + execution: "ProtocolExecution", ): call = record.call.lookup() parameter_value_map = call.parameter_value_map() @@ -1397,7 +1399,7 @@ def join_metadata( dataset = parameter_value_map["dataset"] enhanced_dataset = parameter_value_map["enhanced_dataset"] - def dataset_to_text(self, dataset: Dataset): + def dataset_to_text(self, dataset: "Dataset"): # Assumes that the data file is the same name as the markdown file, aside from the extension if self.out_file: xlsx_file = self.out_file.split(".")[0] + ".xlsx" @@ -1415,12 +1417,14 @@ def measurement_to_text(measure: sbol3.Measure): def get_sample_names( - inputs: Union[SampleArray, sbol3.Component], + inputs: Union["SampleArray", sbol3.Component], error_msg, coordinates=None, ) -> List[str]: # Since some behavior inputs may be specified as either a SampleArray or directly as a list # of Components, this provides a convenient way to unpack a list of sample names + from labop import SampleArray + input_names = [] if isinstance(inputs, SampleArray): if inputs.initial_contents: @@ -1458,7 +1462,7 @@ def repeat_for_remaining_samples(names: List[str], repeat_msg: str): return f" {repeat_msg} {remaining}." -def get_sample_label(sample: SampleCollection, record: ActivityNodeExecution) -> str: +def get_sample_label(sample: SampleCollection, record: "ActivityNodeExecution") -> str: # Lookup sample container to get the container name, and use that # as the sample label if isinstance(sample, SampleMask): @@ -1469,6 +1473,8 @@ def get_sample_label(sample: SampleCollection, record: ActivityNodeExecution) -> def write_sample_contents( sample_array: Union[dict, List[sbol3.Component]], replicates=1 ) -> str: + from labop import SampleArray + if isinstance(sample_array, SampleArray): old_contents = read_sample_contents(sample_array) initial_contents = [] diff --git a/labop_convert/opentrons/opentrons_specialization.py b/labop_convert/opentrons/opentrons_specialization.py index 2aba999e..8dbec81c 100644 --- a/labop_convert/opentrons/opentrons_specialization.py +++ b/labop_convert/opentrons/opentrons_specialization.py @@ -83,7 +83,8 @@ ContO[ "Opentrons 24 Tube Rack with Eppendorf 1.5 mL Safe-Lock Snapcap" ]: "opentrons_24_tuberack_eppendorf_1.5ml_safelock_snapcap", - ContO["Corning 96 Well Plate"]: "corning_96_wellplate_360ul_flat", + ContO["Corning 96 Well Plate"]: "corning_96_wellplate_360ul", + ContO["Corning 96 Well Plate 360 uL Flat"]: "corning_96_wellplate_360ul_flat", ContO["Bio-Rad 96 Well Plate 200 µL PCR"]: "biorad_96_wellplate_200ul_pcr", # ContO["NEST 96 Well Plate"]: "nest_96_wellplate_200ul_flat", } diff --git a/notebooks/Autoprotocol.ipynb b/notebooks/Autoprotocol.ipynb index 51ffffe7..8a030751 100644 --- a/notebooks/Autoprotocol.ipynb +++ b/notebooks/Autoprotocol.ipynb @@ -20,7 +20,7 @@ "from labop_convert.autoprotocol.autoprotocol_specialization import AutoprotocolSpecialization\n", "from labop_convert.autoprotocol.strateos_api import StrateosAPI, StrateosConfig\n", "from autoprotocol import container_type as ctype\n", - "from labop.execution_engine import ExecutionEngine\n", + "from labop.execution.execution_engine import ExecutionEngine\n", "from container_api.client_api import matching_containers, strateos_id\n", "\n", "%load_ext autoreload\n", diff --git a/notebooks/ExecutionRecord.ipynb b/notebooks/ExecutionRecord.ipynb index 8689446f..0b6c319f 100644 --- a/notebooks/ExecutionRecord.ipynb +++ b/notebooks/ExecutionRecord.ipynb @@ -12,7 +12,7 @@ "import labop\n", "import tyto\n", "import uml\n", - "from labop.execution_engine import ManualExecutionEngine\n", + "from labop.execution.execution_engine import ManualExecutionEngine\n", "from labop_jupyter import LabOPJupyterExecutionUI\n", "%load_ext autoreload\n", "%autoreload 2" diff --git a/notebooks/Opentrons.ipynb b/notebooks/Opentrons.ipynb index b3d4fdf8..7166cb31 100644 --- a/notebooks/Opentrons.ipynb +++ b/notebooks/Opentrons.ipynb @@ -46,11 +46,12 @@ "# %matplotlib inline\n", "from IPython.display import Image\n", "\n", - "from labop.execution_engine import ExecutionEngine\n", + "from labop.execution.execution_engine import ExecutionEngine\n", "# from labop_check.labop_check import check_doc\n", "from labop_convert.markdown.markdown_specialization import MarkdownSpecialization\n", "from labop_convert.opentrons.opentrons_specialization import OT2Specialization\n", "from labop.utils.opentrons import run_ot2_sim, make_demo_script\n", + "from labop.constants import PREFIX_MAP\n", "\n", "out_dir = os.path.join(os.path.abspath(\"\"), \"out\")\n", "if not os.path.exists(out_dir):\n", @@ -98,12 +99,12 @@ "# plate = protocol.load_labware('corning_96_wellplate_360ul_flat', location='1')\n", "plate_spec = labop.ContainerSpec('sample_plate', name='sample plate', \n", " queryString='cont:Corning96WellPlate360uLFlat', \n", - " prefixMap=labop.constants.PREFIX_MAP)\n", + " prefixMap=PREFIX_MAP)\n", "plate = protocol.primitive_step('EmptyContainer', specification=plate_spec)\n", "load_plate = protocol.primitive_step('LoadRackOnInstrument', rack=plate_spec, coordinates='1')\n", "\n", "# tiprack = protocol.load_labware('opentrons_96_tiprack_300ul', location='2')\n", - "tiprack_spec = labop.ContainerSpec('tiprack', queryString='cont:Opentrons96TipRack300uL', prefixMap=labop.constants.PREFIX_MAP)\n", + "tiprack_spec = labop.ContainerSpec('tiprack', queryString='cont:Opentrons96TipRack300uL', prefixMap=\n", "tiprack = protocol.primitive_step('LoadRackOnInstrument', rack=tiprack_spec, coordinates='2')\n", "\n", "# left_pipette = protocol.load_instrument(\n", diff --git a/notebooks/UItemplate.ipynb b/notebooks/UItemplate.ipynb index 3550fc91..413e2e91 100644 --- a/notebooks/UItemplate.ipynb +++ b/notebooks/UItemplate.ipynb @@ -20,7 +20,7 @@ "import labop\n", "import tyto\n", "import uml\n", - "from labop.execution_engine import ExecutionEngine\n", + "from labop.execution.execution_engine import ExecutionEngine\n", "\n", "%load_ext autoreload\n", "%autoreload 2" diff --git a/notebooks/data_link.ipynb b/notebooks/data_link.ipynb index 6878cd04..f9399207 100644 --- a/notebooks/data_link.ipynb +++ b/notebooks/data_link.ipynb @@ -16,7 +16,7 @@ "import rdflib as rdfl\n", "from IPython.display import Markdown\n", "\n", - "from labop.execution_engine import ExecutionEngine\n", + "from labop.execution.execution_engine import ExecutionEngine\n", "from labop_check.labop_check import check_doc\n", "\n", "import logging\n", diff --git a/notebooks/labop_author_demo.ipynb b/notebooks/labop_author_demo.ipynb index 2c8098e4..77c066d4 100644 --- a/notebooks/labop_author_demo.ipynb +++ b/notebooks/labop_author_demo.ipynb @@ -59,10 +59,10 @@ "from labop.constants import ddh2o, ludox\n", "\n", "\n", - "from labop.execution_engine import ExecutionEngine\n", + "from labop.execution.execution_engine import ExecutionEngine\n", "# from labop_check.labop_check import check_doc\n", "from labop_convert.markdown.markdown_specialization import MarkdownSpecialization\n", - "\n", + "from labop.constants import PREFIX_MAP\n", "%load_ext autoreload\n", "%autoreload 2" ] @@ -213,7 +213,7 @@ " (om:hasNumericalValue only xsd:decimal[>= \"200\"^^xsd:decimal])))\"\"\"\n", "\n", "\n", - "spec = labop.ContainerSpec(queryString=PLATE_SPECIFICATION, prefixMap=labop.constants.labop.constants.PREFIX_MAP, name='plateRequirement')" + "spec = labop.ContainerSpec(queryString=PLATE_SPECIFICATION, prefixMap=PREFIX_MAP, name='plateRequirement')" ] }, { diff --git a/notebooks/labop_demo.ipynb b/notebooks/labop_demo.ipynb index 8ab6c8ed..464d1f7d 100644 --- a/notebooks/labop_demo.ipynb +++ b/notebooks/labop_demo.ipynb @@ -19,10 +19,10 @@ "from IPython.display import Markdown\n", "\n", "\n", - "from labop.execution_engine import ExecutionEngine\n", + "from labop.execution.execution_engine import ExecutionEngine\n", "# from labop_check.labop_check import check_doc\n", "from labop_convert.markdown.markdown_specialization import MarkdownSpecialization\n", - "from labop.constants import ddh2o, ludox\n", + "from labop.constants import ddh2o, ludox, PREFIX_MAP\n", "\n", "%load_ext autoreload\n", "%autoreload 2" @@ -168,7 +168,7 @@ " ((om:hasUnit value om:microlitre) and\n", " (om:hasNumericalValue only xsd:decimal[>= \"200\"^^xsd:decimal])))\"\"\"\n", "\n", - "spec = labop.ContainerSpec('plate_requirement', name='plateRequirement', queryString=PLATE_SPECIFICATION, prefixMap=labop.constants.PREFIX_MAP)" + "spec = labop.ContainerSpec('plate_requirement', name='plateRequirement', queryString=PLATE_SPECIFICATION, prefixMap=PREFIX_MAP)" ] }, { diff --git a/notebooks/markdown.ipynb b/notebooks/markdown.ipynb index 017412a3..694d8d22 100644 --- a/notebooks/markdown.ipynb +++ b/notebooks/markdown.ipynb @@ -15,7 +15,7 @@ "\n", "from labop_convert.markdown.markdown_specialization import MarkdownSpecialization\n", "\n", - "from labop.execution_engine import ExecutionEngine\n", + "from labop.execution.execution_engine import ExecutionEngine\n", "from IPython.display import Markdown\n", "\n", "%load_ext autoreload\n", diff --git a/notebooks/ph_calibration.ipynb b/notebooks/ph_calibration.ipynb index 5118fd31..2e7dd279 100644 --- a/notebooks/ph_calibration.ipynb +++ b/notebooks/ph_calibration.ipynb @@ -8,7 +8,7 @@ "source": [ "from examples.pH_calibration import pH_calibration as pH_calibration\n", "import sbol3\n", - "from labop.execution_engine import ManualExecutionEngine\n", + "from labop.execution.execution_engine import ManualExecutionEngine\n", "import labop\n", "import uml\n", "import tyto\n", diff --git a/revised-interlab-growth-curve.py b/revised-interlab-growth-curve.py index bcf4dbb3..d3a73e5c 100644 --- a/revised-interlab-growth-curve.py +++ b/revised-interlab-growth-curve.py @@ -9,7 +9,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert import MarkdownSpecialization if "unittest" in sys.modules: diff --git a/test/DISABLED_execution.py b/test/DISABLED_execution.py index 4cad3853..a5d46ee8 100644 --- a/test/DISABLED_execution.py +++ b/test/DISABLED_execution.py @@ -6,7 +6,7 @@ import tyto import labop -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine l = logging.getLogger(__file__) l.setLevel(logging.ERROR) @@ -64,7 +64,10 @@ def test_execute_protocol(self): ) ] execution = ee.execute( - protocol, agent, id="test_execution", parameter_values=parameter_values + protocol, + agent, + id="test_execution", + parameter_values=parameter_values, ) # dot = execution.to_dot() diff --git a/test/test_LUDOX_protocol.py b/test/test_LUDOX_protocol.py index a80e8169..7aac7390 100644 --- a/test/test_LUDOX_protocol.py +++ b/test/test_LUDOX_protocol.py @@ -1,22 +1,11 @@ -import filecmp import logging import os -import tempfile import unittest -from importlib.machinery import SourceFileLoader -from importlib.util import module_from_spec, spec_from_loader - -import sbol3 import labop -from labop.utils.helpers import file_diff -# Save testfiles as artifacts when running in CI environment, -# else save them to a local temp directory -if "GH_TMPDIR" in os.environ: - TMPDIR = os.environ["GH_TMPDIR"] -else: - TMPDIR = tempfile.gettempdir() +logger = logging.getLogger("LUDOX_protocol") +logger.setLevel(logging.INFO) OUT_DIR = os.path.join(os.path.dirname(__file__), "out") @@ -28,52 +17,50 @@ ) -def load_ludox_protocol(protocol_filename): - loader = SourceFileLoader("ludox_protocol", protocol_filename) - spec = spec_from_loader(loader.name, loader) - module = module_from_spec(spec) - loader.exec_module(module) - return module - - -protocol_def = load_ludox_protocol(protocol_def_file) - - class TestProtocolEndToEnd(unittest.TestCase): - def test_create_protocol(self): - protocol: labop.Protocol - doc: sbol3.Document - logger = logging.getLogger("LUDOX_protocol") - logger.setLevel(logging.INFO) - protocol, doc = protocol_def.ludox_protocol() - - ######################################## - # Validate and write the document - print("Validating and writing protocol") - v = doc.validate() - assert len(v) == 0, "".join(f"\n {e}" for e in v) + def create_protocol(self, doc, protocol: labop.Protocol) -> labop.Protocol: + protocol = labop.execution.harness.ProtocolLoader( + protocol_def_file, "ludox_protocol" + ).generate_protocol(doc, protocol) + return protocol - temp_name = os.path.join(TMPDIR, "igem_ludox_test.nt") + def test_create_protocol(self): + harness = labop.execution.harness.ProtocolHarness( + clean_output=True, + base_dir=os.path.dirname(__file__), + entry_point=self.create_protocol, + namespace="https://bbn.com/scratch/", + protocol_name="iGEM_LUDOX_OD_calibration_2018", + protocol_long_name="iGEM 2018 LUDOX OD calibration protocol", + protocol_version="1.0", + protocol_description=""" +With this protocol you will use LUDOX CL-X (a 45% colloidal silica suspension) as a single point reference to +obtain a conversion factor to transform absorbance (OD600) data from your plate reader into a comparable +OD600 measurement as would be obtained in a spectrophotometer. This conversion is necessary because plate +reader measurements of absorbance are volume dependent; the depth of the fluid in the well defines the path +length of the light passing through the sample, which can vary slightly from well to well. In a standard +spectrophotometer, the path length is fixed and is defined by the width of the cuvette, which is constant. +Therefore this conversion calculation can transform OD600 measurements from a plate reader (i.e. absorbance +at 600 nm, the basic output of most instruments) into comparable OD600 measurements. The LUDOX solution +is only weakly scattering and so will give a low absorbance value. + """, + artifacts=[ + labop.execution.harness.ProtocolRubric( + filename=os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "testfiles", + "igem_ludox_test.nt", + ), + # overwrite_rubric=True, # Used to update rubric + ) + ], + ) - # At some point, rdflib began inserting an extra newline into - # N-triple serializations, which breaks file comparison. - # Here we strip extraneous newlines, to maintain reverse compatibility - with open(temp_name, "w") as f: - f.write(doc.write_string(sbol3.SORTED_NTRIPLES).strip()) - print(f"Wrote file as {temp_name}") + harness.run(verbose=True) - comparison_file = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - "testfiles", - "igem_ludox_test.nt", + assert len(harness.errors()) == 0, harness.artifacts_results_summary( + verbose=True ) - # with open(comparison_file, "w") as f: - # f.write(doc.write_string(sbol3.SORTED_NTRIPLES).strip()) - print(f"Comparing against {comparison_file}") - diff = "".join(file_diff(comparison_file, temp_name)) - print(f"Difference: {diff}") - assert filecmp.cmp(temp_name, comparison_file), "Files are not identical" - print("File identical with test file") if __name__ == "__main__": diff --git a/test/test_decision_nodes.py b/test/test_decision_nodes.py index 515da976..cef6445c 100644 --- a/test/test_decision_nodes.py +++ b/test/test_decision_nodes.py @@ -1,20 +1,22 @@ -import filecmp import logging import os import tempfile import unittest -from importlib.machinery import SourceFileLoader -from importlib.util import module_from_spec, spec_from_loader import sbol3 -from labop import ExecutionEngine, Primitive, Protocol, SampleData -from labop.utils.helpers import file_diff +# from labop.utils.helpers import file_diff +import labop +from labop.execution.harness import ( + ProtocolExecutionRubric, + ProtocolHarness, + ProtocolLoader, +) from uml import ActivityParameterNode, CallBehaviorAction, InputPin -OUT_DIR = os.path.join(os.path.dirname(__file__), "out") -if not os.path.exists(OUT_DIR): - os.mkdir(OUT_DIR) +# OUT_DIR = os.path.join(os.path.dirname(__file__), "out") +# if not os.path.exists(OUT_DIR): +# os.mkdir(OUT_DIR) # Save testfiles as artifacts when running in CI environment, # else save them to a local temp directory @@ -29,32 +31,15 @@ ) -def load_ludox_protocol(protocol_filename): - loader = SourceFileLoader("ludox_protocol", protocol_filename) - spec = spec_from_loader(loader.name, loader) - module = module_from_spec(spec) - loader.exec_module(module) - return module - - -protocol_def = load_ludox_protocol(protocol_def_file) - - class TestProtocolEndToEnd(unittest.TestCase): - def test_create_protocol(self): - protocol: Protocol - doc: sbol3.Document + def create_protocol(self, doc: sbol3.Document, protocol: labop.Protocol): logger = logging.getLogger("decision_protocol") logger.setLevel(logging.INFO) - doc = sbol3.Document() - sbol3.set_namespace("https://bbn.com/scratch/") - protocol = Protocol("decision_node_test") - doc.add(protocol) initial = protocol.initial() final = protocol.final() - pH_meter_calibrated = Primitive("pHMeterCalibrated") + pH_meter_calibrated = labop.Primitive("pHMeterCalibrated") pH_meter_calibrated.description = "Determine if the pH Meter is calibrated." pH_meter_calibrated.add_output( "return", "http://www.w3.org/2001/XMLSchema#boolean" @@ -78,52 +63,23 @@ def pH_meter_calibrated_compute_output( ], ) - agent = sbol3.Agent("test_agent") - ee = ExecutionEngine( - out_dir=OUT_DIR, use_ordinal_time=True, use_defined_primitives=False - ) - parameter_values = [] - execution = ee.execute( - protocol, - agent, - id="test_execution", - parameter_values=parameter_values, - ) + return protocol - ######################################## - # Validate and write the document - print("Validating and writing protocol") - v = doc.validate() - assert len(v) == 0, "".join(f"\n {e}" for e in v) - - temp_name = os.path.join(TMPDIR, "decision_node_test.nt") - doc.write(temp_name, sbol3.SORTED_NTRIPLES) - print(f"Wrote file as {temp_name}") - - comparison_file = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - "testfiles", - "decision_node_test.nt", - ) - doc.write(comparison_file, sbol3.SORTED_NTRIPLES) - print(f"Comparing against {comparison_file}") - diff = "".join(file_diff(comparison_file, temp_name)) - # print(f"Difference: {diff}") - assert filecmp.cmp(temp_name, comparison_file), "Files are not identical" - print("File identical with test file") - - def test_ludox_calibration_decision(self): - protocol: Protocol - doc: sbol3.Document + def generate_ludox_calibration_decision( + self, doc: sbol3.Document, protocol: labop.Protocol + ) -> labop.Protocol: logger = logging.getLogger("LUDOX_decision_protocol") logger.setLevel(logging.INFO) - protocol, doc = protocol_def.ludox_protocol() - measurment_is_nominal = Primitive("measurementNominal") + protocol = ProtocolLoader( + protocol_def_file, "ludox_protocol" + ).generate_protocol(doc, protocol) + + measurment_is_nominal = labop.Primitive("measurementNominal") measurment_is_nominal.description = ( "Determine if the measurments are acceptable." ) - measurment_is_nominal.add_input("decision_input", SampleData) + measurment_is_nominal.add_input("decision_input", labop.SampleData) measurment_is_nominal.add_output( "return", "http://www.w3.org/2001/XMLSchema#boolean" ) @@ -188,16 +144,86 @@ def measurement_is_nominal_compute_output( sbol3.OM_MEASURE, measure2.output_pin("measurements"), ) + + # primary incoming node is a measurement primitive (because its not a control node, the primary incoming edge is an object flow) + # The protocol is getting two object edges into the decision node (from the measurement and its output pin). There should not be an object edge from the measurement. The outputs are object flows, but are used as control flows. decision = protocol.make_decision_node( + # The first parameter is the primary_incoming activity passing control flow through the decision measure, # .output_pin("measurements"), # primary_incoming + # The decision input behavior is the behavior used to select the flow of the decision node decision_input_behavior=measurment_is_nominal, + # The decision input source determines the object flow that influences the decision input behavior output decision_input_source=measure.output_pin("measurements"), outgoing_targets=[ (True, protocol.final()), (False, measure2), ], ) - # protocol.to_dot().view() + return protocol + + def test_create_protocol(self): + namespace = "https://bbn.com/scratch/" + harness = ProtocolHarness( + clean_output=True, + base_dir=os.path.join( + os.path.dirname(__file__), "out", "out_create_protocol" + ), + namespace=namespace, + execution_id="test_execution", + protocol_name="decision_node_test", + protocol_long_name=None, + protocol_description=None, + entry_point=self.create_protocol, + agent="test_agent", + execution_kwargs={ + "use_ordinal_time": True, + "use_defined_primitives": False, + }, + artifacts=[ + ProtocolExecutionRubric( + filename=os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "testfiles", + "decision_node_test.nt", + ), + overwrite_rubric=True, # Used to update rubric + ) + ], + ) + harness.run(verbose=True) + + assert len(harness.errors()) == 0, harness.artifacts_results_summary( + verbose=True + ) + + # execution_artifact = harness.execution_artifact() + # protocol_artifact = execution_artifact.protocol_artifact + + # agent = sbol3.Agent("test_agent") + # ee = ExecutionEngine( + # out_dir=OUT_DIR, use_ordinal_time=True, use_defined_primitives=False + # ) + # parameter_values = [] + # execution = ee.execute( + # protocol, + # agent, + # id="test_execution", + # parameter_values=parameter_values, + # ) + + def test_ludox_calibration_decision(self): + harness = ProtocolHarness( + clean_output=True, + base_dir=os.path.join( + os.path.dirname(__file__), "out", "out_calibration_decision" + ), + entry_point=self.generate_ludox_calibration_decision, + artifacts=[], + ) + harness.run() + assert len(harness.errors()) == 0, harness.artifacts_results_summary( + verbose=True + ) if __name__ == "__main__": diff --git a/test/test_examples.py b/test/test_examples.py index 821a8999..985fbf1d 100644 --- a/test/test_examples.py +++ b/test/test_examples.py @@ -10,7 +10,7 @@ from parameterized import parameterized -from labop.utils.harness import ProtocolHarness +from labop.execution import ProtocolHarness l = logging.Logger(__file__) l.setLevel(logging.INFO) @@ -45,7 +45,34 @@ def discover_example_protocols(example_directory: str) -> List[str]: expected_failures = { "../examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py": { "description": "Fails because there is a missing primer layout csv." - } + }, + "../examples/protocols/pH_calibration/pH_calibration.py": { + "description": "Fails because it cannot import module." + }, + "../examples/protocols/iGEM/interlab-timepoint-B_AV.py": { + "description": "Fails because it cannot import module." + }, + "../examples/protocols/iGEM/interlab-exp1_MI.py": { + "description": "Fails because it cannot import module." + }, + "../examples/protocols/iGEM/interlab-growth-curve.py": { + "description": "Fails because it cannot import module." + }, + "../examples/protocols/iGEM/interlab-exp2_MI.py": { + "description": "Fails because it cannot import module." + }, + "../examples/protocols/iGEM/revised-interlab-growth-curve.py": { + "description": "Fails due to several well-formedness errors" + }, + "../examples/protocols/iGEM/interlab-timepoint-B.py": { + "description": "Fails because it cannot import module." + }, + "../examples/protocols/iGEM/interlab-exp2_from1.py": { + "description": "Fails because it cannot import module." + }, + "../examples/protocols/iGEM/challenging-interlab-growth-curve.py": { + "description": "Fails due to several well-formedness errors" + }, } diff --git a/test/test_igem_examples.py b/test/test_igem_examples.py index dcc65fc7..a4e8b5c1 100644 --- a/test/test_igem_examples.py +++ b/test/test_igem_examples.py @@ -3,15 +3,17 @@ from importlib.machinery import SourceFileLoader from importlib.util import module_from_spec, spec_from_loader -import sbol3 +import labop +import labop_convert +from labop.execution.harness import ProtocolSpecialization -def fullpath(fname: str) -> str: - return os.path.join(os.path.dirname(__file__), f"../examples/{fname}") +def fullpath(fname: str, path: str = "../examples/protocols/iGEM/") -> str: + return os.path.join(os.path.dirname(__file__), f"{path}{fname}") -def load_protocol(protocol_filename): - testfile_path = fullpath(protocol_filename) +def load_protocol(protocol_filename, path="../examples/protocols/iGEM/"): + testfile_path = fullpath(protocol_filename, path=path) module_name = protocol_filename.replace("-", "_") loader = SourceFileLoader(module_name, testfile_path) spec = spec_from_loader(loader.name, loader) @@ -21,21 +23,86 @@ def load_protocol(protocol_filename): class TestIgemExamples(unittest.TestCase): + def get_harness( + self, + filename: str, + path: str = "../examples/protocols/iGEM/", + use_custom_specialization: bool = True, + ) -> labop.execution.harness.ProtocolHarness: + out_dir = filename.split(".")[0].replace("-", "_") + protocol_module = load_protocol(filename, path=path) + if use_custom_specialization: + specialization = protocol_module.InterlabCustomSpecialization( + specialization=labop_convert.MarkdownSpecialization( + "test_LUDOX_markdown.md" + ) + ) + else: + specialization = ProtocolSpecialization( + specialization=labop_convert.MarkdownSpecialization( + "test_LUDOX_markdown.md" + ) + ) + + harness = labop.execution.harness.ProtocolHarness( + clean_output=True, + protocol_name=out_dir, + base_dir=os.path.join(os.path.dirname(__file__), "out", out_dir), + entry_point=protocol_module.generate_protocol, + agent="test_agent", + libraries=[ + "liquid_handling", + "plate_handling", + "spectrophotometry", + "sample_arrays", + "culturing", + ], + artifacts=[specialization], + execution_kwargs={ + "sample_format": "json", + "track_samples": False, + }, + execution_id="test_execution", + ) + return harness + def test_example1(self): - load_protocol("interlab-endpoint.py") + harness = self.get_harness("interlab-endpoint.py") + harness.run() + assert len(harness.errors()) == 0, harness.artifacts_results_summary( + verbose=True + ) def test_example2(self): - load_protocol("interlab-exp1.py") + harness = self.get_harness("interlab-exp1.py") + harness.run() + assert len(harness.errors()) == 0, harness.artifacts_results_summary( + verbose=True + ) def test_example3(self): - load_protocol("interlab-exp2.py") + harness = self.get_harness("interlab-exp2.py") + harness.run() + assert len(harness.errors()) == 0, harness.artifacts_results_summary( + verbose=True + ) def test_example4(self): - load_protocol("interlab-exp3_challenge.py") + harness = self.get_harness("interlab-exp3_challenge.py") + harness.run() + assert len(harness.errors()) == 0, harness.artifacts_results_summary( + verbose=True + ) def test_example5(self): - load_protocol( - "protocols/multicolor-particle-calibration/multicolor-particle-calibration.py" + harness = self.get_harness( + "multicolor-particle-calibration.py", + path="../examples/protocols/calibration/multicolor-particle-calibration/", + use_custom_specialization=False, + ) + harness.run() + assert len(harness.errors()) == 0, harness.artifacts_results_summary( + verbose=True ) diff --git a/test/test_inputs.py b/test/test_inputs.py index a18e6639..1f65abf0 100644 --- a/test/test_inputs.py +++ b/test/test_inputs.py @@ -5,7 +5,7 @@ import labop import uml -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert import MarkdownSpecialization from labop_convert.behavior_specialization import DefaultBehaviorSpecialization diff --git a/test/test_opentrons.py b/test/test_opentrons.py index f5833c67..db4ccf19 100644 --- a/test/test_opentrons.py +++ b/test/test_opentrons.py @@ -1,5 +1,3 @@ -import filecmp -import logging import os import tempfile import unittest @@ -9,7 +7,9 @@ import sbol3 import labop -from labop.execution_engine import ExecutionEngine +from build.lib.labop_convert.opentrons import opentrons_specialization +from labop.execution.execution_engine import ExecutionEngine +from labop.execution.harness import ProtocolSpecialization from labop.utils.helpers import file_diff from labop_convert.opentrons.opentrons_specialization import OT2Specialization @@ -42,64 +42,49 @@ def load_protocol(protocol_def_fn, protocol_filename): class TestProtocolEndToEnd(unittest.TestCase): - def test_create_protocol(self): - protocol: labop.Protocol - doc: sbol3.Document - logger = logging.getLogger("opentrons_toy_protocol") - logger.setLevel(logging.INFO) - protocol, doc = protocol_def.opentrons_toy_protocol() - - protocol.to_dot().render( - filename=os.path.join(OUT_DIR, protocol.display_name), format="png" - ) + def create_protocol( + self, doc: sbol3.Document, protocol: labop.Protocol + ) -> labop.Protocol: + protocol = labop.execution.harness.ProtocolLoader( + protocol_def_file, "opentrons_toy_protocol" + ).generate_protocol(doc, protocol) + return protocol - agent = sbol3.Agent("ot2_machine", name="OT2 machine") - - # Execute the protocol - # In order to get repeatable timings, we use ordinal time in the test - # where each timepoint is one second after the previous time point - ee = ExecutionEngine( - use_ordinal_time=True, - specializations=[OT2Specialization(os.path.join(OUT_DIR, "opentrons_toy"))], - failsafe=False, - ) - parameter_values = [] - execution = ee.execute( - protocol, - agent, - id="test_execution_1", - parameter_values=parameter_values, + def test_create_protocol(self): + harness = labop.execution.harness.ProtocolHarness( + clean_output=True, + base_dir=os.path.dirname(__file__), + entry_point=self.create_protocol, + agent="ot2_machine", + execution_id="test_execution_1", + namespace="https://labop.io/scratch/", + protocol_name="OT2_demo", + protocol_long_name="OT2 demo", + protocol_description="Example Opentrons Protocol as LabOP", + execution_kwargs={ + "use_ordinal_time": True, + "failsafe": False, + }, + artifacts=[ + ProtocolSpecialization( + specialization=OT2Specialization("opentrons_toy") + ), + labop.execution.harness.ProtocolExecutionRubric( + filename=os.path.join( + os.path.dirname(os.path.realpath(__file__)), + "testfiles", + "opentrons_toy.nt", + ), + # overwrite_rubric=True, # Used to update rubric + ), + ], ) - ######################################## - # Validate and write the document - - print("Validating and writing protocol") - v = doc.validate() - assert len(v) == 0, "".join(f"\n {e}" for e in v) - - nt_file = "opentrons_toy.nt" - temp_name = os.path.join(TMPDIR, nt_file) - - # At some point, rdflib began inserting an extra newline into - # N-triple serializations, which breaks file comparison. - # Here we strip extraneous newlines, to maintain reverse compatibility - with open(temp_name, "w") as f: - f.write(doc.write_string(sbol3.SORTED_NTRIPLES).strip()) - print(f"Wrote file as {temp_name}") + harness.run(verbose=True) - comparison_file = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - "testfiles", - nt_file, + assert len(harness.errors()) == 0, harness.artifacts_results_summary( + verbose=True ) - # with open(comparison_file, "w") as f: - # f.write(doc.write_string(sbol3.SORTED_NTRIPLES).strip()) - print(f"Comparing against {comparison_file}") - diff = "".join(file_diff(comparison_file, temp_name)) - print(f"Difference:\n{diff}") - assert filecmp.cmp(temp_name, comparison_file), "Files are not identical" - print("File identical with test file") if __name__ == "__main__": diff --git a/test/test_outputs.py b/test/test_outputs.py index b3ac1f28..a9555244 100644 --- a/test/test_outputs.py +++ b/test/test_outputs.py @@ -5,7 +5,7 @@ import tyto import labop -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop_convert import MarkdownSpecialization from labop_convert.behavior_specialization import DefaultBehaviorSpecialization from uml import LiteralReference diff --git a/test/test_protocol_outputs.py b/test/test_protocol_outputs.py index 7e57efd7..da54fcf1 100644 --- a/test/test_protocol_outputs.py +++ b/test/test_protocol_outputs.py @@ -1,13 +1,14 @@ +import os import unittest import sbol3 import tyto import labop -from labop.execution_engine import ExecutionEngine -from labop_convert import MarkdownSpecialization -from labop_convert.behavior_specialization import DefaultBehaviorSpecialization -from uml import LiteralReference +import labop_convert +import uml +from labop.execution.harness import ProtocolExecutionNTuples +from labop.protocol_execution import ProtocolExecution PARAMETER_IN = "http://bioprotocols.org/uml#in" PARAMETER_OUT = "http://bioprotocols.org/uml#out" @@ -18,12 +19,9 @@ class TestProtocolOutputs(unittest.TestCase): - def setUp(self): - protocol_name = "test_protocol" - protocol, doc = labop.Protocol.initialize_protocol( - display_id=protocol_name, name=protocol_name - ) - + def generate_protocol( + self, doc: sbol3.Document, protocol: labop.Protocol + ) -> labop.Protocol: plate_spec = labop.ContainerSpec( "my_absorbance_measurement_plate", name="my absorbance measurement plate", @@ -47,6 +45,13 @@ def setUp(self): self.protocol = protocol self.output = measure_absorbance.output_pin("measurements") + self.protocol.designate_output( + "measurements", + "http://bioprotocols.org/labop#SampleData", + source=self.output, + ) + return protocol + # @unittest.expectedFailure # def test_protocol_outputs_not_designated(self): # # TODO: catch output parameters that aren't explicitly designated @@ -57,19 +62,22 @@ def setUp(self): def test_protocol_outputs(self): # This test confirms generation of designated output objects - self.protocol.designate_output( - "measurements", - "http://bioprotocols.org/labop#SampleData", - source=self.output, - ) - - agent = sbol3.Agent("test_agent") - ee = ExecutionEngine( - specializations=[MarkdownSpecialization("test_LUDOX_markdown.md")] + harness = labop.execution.harness.ProtocolHarness( + base_dir=os.path.join(os.path.dirname(__file__), "out"), + entry_point=self.generate_protocol, + artifacts=[ + labop.execution.harness.ProtocolSpecialization( + specialization=labop_convert.MarkdownSpecialization( + "test_LUDOX_markdown.md" + ) + ) + ], ) - ex = ee.execute(self.protocol, agent, id="test_execution", parameter_values=[]) + harness.run() - self.assertTrue(isinstance(ex.parameter_values[0].value, LiteralReference)) + execution_artifacts = harness.artifacts_of_type(ProtocolExecutionNTuples) + ex = next(iter(execution_artifacts)).execution + self.assertTrue(isinstance(ex.parameter_values[0].value, uml.LiteralReference)) self.assertTrue( isinstance(ex.parameter_values[0].value.value.lookup(), labop.Dataset) ) diff --git a/test/test_sampledata.py b/test/test_sampledata.py index 3d210a59..1897e985 100644 --- a/test/test_sampledata.py +++ b/test/test_sampledata.py @@ -15,7 +15,7 @@ import labop import uml from labop import Protocol -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop.utils.helpers import file_diff from labop.utils.plate_coordinates import get_sample_list diff --git a/test/test_samplemap.py b/test/test_samplemap.py index 8aa51e9d..0bacb371 100644 --- a/test/test_samplemap.py +++ b/test/test_samplemap.py @@ -10,7 +10,7 @@ import xarray as xr from labop import ContainerSpec, Protocol, SampleMap, Strings, serialize_sample_format -from labop.execution_engine import ExecutionEngine +from labop.execution.execution_engine import ExecutionEngine from labop.strings import Strings from labop.utils.helpers import file_diff from labop.utils.plate_coordinates import ( diff --git a/test/test_subprotocols.py b/test/test_subprotocols.py index 83833f16..7c20a82d 100644 --- a/test/test_subprotocols.py +++ b/test/test_subprotocols.py @@ -1,19 +1,16 @@ +import os import unittest import sbol3 import labop -from labop.execution_engine import ExecutionEngine +from labop.execution.harness import ProtocolExecutionNTuples class TestSubprotocols(unittest.TestCase): - def test_subexecutions(self): - protocol, doc = labop.Protocol.initialize_protocol( - display_id="protocol", - name="Protocol", - namespace="http://bbn.com/scratch/", - ) - + def generate_protocol( + self, doc: sbol3.Document, protocol: labop.Protocol + ) -> labop.Protocol: subprotocol1 = labop.Protocol.create_protocol(display_id="sub1", name="sub1") subprotocol2 = labop.Protocol.create_protocol(display_id="sub2", name="sub2") primitive1 = labop.Primitive("primitive1") @@ -26,16 +23,26 @@ def test_subexecutions(self): protocol.primitive_step(primitive1) protocol.primitive_step(subprotocol2) - ee = ExecutionEngine() - ee.specializations[0]._behavior_func_map[ - primitive1.identity - ] = lambda call, ex: None # Register custom primitives in the execution engine - ex = ee.execute( - protocol, - sbol3.Agent("test_agent"), - id="test_execution1", - parameter_values=[], + return protocol + + def test_subexecutions(self): + harness = labop.execution.harness.ProtocolHarness( + namespace="http://bbn.com/scratch/", + base_dir=os.path.join(os.path.dirname(__file__), "out"), + entry_point=self.generate_protocol, + execution_id="test_execution1", ) + execution_artifacts = harness.artifacts_of_type(ProtocolExecutionNTuples) + + # execution_artifact.execution_engine.specializations[0]._behavior_func_map[ + # primitive1.identity + # ] = ( + # lambda call, ex: None + # ) # Register custom primitives in the execution engine + harness.run() + ea = next(iter(execution_artifacts)) + ex = ea.execution + ee = ea.execution_engine ordered_executions = ex.get_ordered_executions() self.assertListEqual( @@ -53,11 +60,17 @@ def test_subexecutions(self): ], ) if not ee.is_asynchronous: + # FIXME There is no synchronous mode at this time and the subprotocol executions are part of the top-level execution + # Asynchronous execution will not include subprotocol executions, rather just the tokens inside them that execution. + protocol = ex.get_protocol() + behaviors = protocol.get_behaviors() + subprotocols = [b for b in behaviors if isinstance(b, labop.Protocol)] + subprotocols.sort(key=lambda x: x.identity) subprotocol_executions = ex.get_subprotocol_executions() self.assertListEqual( - [x.protocol.lookup() for x in subprotocol_executions], - [subprotocol1, subprotocol2], + [x.get_protocol for x in subprotocol_executions], + subprotocols, ) diff --git a/test/testfiles/decision_node_test.nt b/test/testfiles/decision_node_test.nt index 096c7279..d8c23c5e 100644 --- a/test/testfiles/decision_node_test.nt +++ b/test/testfiles/decision_node_test.nt @@ -15,12 +15,12 @@ . . . - . + . "ControlFlow2" . . . . - . + . "ControlFlow3" . . . @@ -283,7 +283,7 @@ . . . - . + . . "ActivityNodeExecution4" . . @@ -319,7 +319,7 @@ . . . - . + . . "CallBehaviorExecution2" . . @@ -392,4 +392,4 @@ . "2000-01-01T00:00:04"^^ . . - "2000-01-01T00:00:00"^^ . + "2000-01-01T00:00:00"^^ . \ No newline at end of file diff --git a/uml/activity_edge.py b/uml/activity_edge.py index 810a40b2..77126b3f 100644 --- a/uml/activity_edge.py +++ b/uml/activity_edge.py @@ -7,6 +7,8 @@ import graphviz +from uml.activity_node import ActivityNode + from . import inner from .action import Action from .input_pin import InputPin @@ -21,10 +23,10 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._where_defined = self.get_where_defined() - def get_source(self): + def get_source(self) -> ActivityNode: return self.source.lookup() if self.source else self.source - def get_target(self): + def get_target(self) -> ActivityNode: return self.target.lookup() if self.target else self.target def gv_sanitize(self, id: str): @@ -58,7 +60,7 @@ def to_dot(self, dot: graphviz.Graph, namespace=""): source = self.get_source() target = self.get_target() src_id = source.label(namespace=namespace) - dest_id = self.get_target().label(namespace=namespace) + dest_id = target.label(namespace=namespace) edge_id = self.label() # edge.identity.replace(":", "_") if isinstance(target, CallBehaviorAction): dest_id = f"{dest_id}:node" diff --git a/uml/behavior.py b/uml/behavior.py index 85c47d85..d824cac9 100644 --- a/uml/behavior.py +++ b/uml/behavior.py @@ -115,8 +115,8 @@ def get_input(self, name) -> Parameter: else: return found[0] - def get_output(self, name) -> Parameter: - """Return a specific input Parameter for this Behavior + def get_output(self, name: str) -> Parameter: + """Return a specific output Parameter for this Behavior Note: assumes that type is all either in or out Returns @@ -139,6 +139,26 @@ def get_output(self, name) -> Parameter: else: return found[0] + def get_outputs( + self, ordered=False, required=False + ) -> Iterable[Union[Parameter, OrderedPropertyValue]]: + return self.get_parameters( + ordered=ordered, + required=required, + input_only=False, + output_only=True, + ) + + def get_inputs( + self, ordered=False, required=False + ) -> Iterable[Union[Parameter, OrderedPropertyValue]]: + return self.get_parameters( + ordered=ordered, + required=required, + input_only=True, + output_only=False, + ) + def get_parameters( self, ordered=False, required=False, input_only=False, output_only=False ) -> Iterable[Union[Parameter, OrderedPropertyValue]]: diff --git a/uml/object_node.py b/uml/object_node.py index 22157c5e..b54f4a53 100644 --- a/uml/object_node.py +++ b/uml/object_node.py @@ -37,3 +37,6 @@ def enabled( bool if self is enabled """ return all([len(edge_values[e]) > 0 for e in edge_values]) or engine.permissive + + def get_name(self) -> str: + return self.name if self.name else self.get_parameter().name From 9d40972f833240c5f94a235bcdd765e1d14f1488 Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:42:44 -0500 Subject: [PATCH 09/12] fix tests --- .../multicolor-particle-calibration-small.py | 2 +- labop/execution/behavior_dynamics.py | 6 +- labop/execution/execution_engine.py | 196 +++++++++++- labop/execution/harness.py | 6 +- labop/execution/primitive_execution.py | 291 +++++++++++++++++ labop/primitive.py | 301 +----------------- labop/sample_metadata.py | 2 +- .../markdown/markdown_specialization.py | 2 +- test/test_LUDOX_protocol.py | 2 +- test/test_decision_nodes.py | 2 +- uml/action.py | 29 +- uml/activity_node.py | 22 -- uml/activity_parameter_node.py | 33 -- uml/call_behavior_action.py | 66 +--- uml/fork_node.py | 29 -- uml/input_pin.py | 29 +- uml/output_pin.py | 31 -- 17 files changed, 508 insertions(+), 541 deletions(-) create mode 100644 labop/execution/primitive_execution.py diff --git a/examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py b/examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py index 728a28d7..f06e1a2b 100644 --- a/examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py +++ b/examples/protocols/calibration/multicolor-protocol-calibration-small/multicolor-particle-calibration-small.py @@ -315,7 +315,7 @@ parameter_values=[], ) -execution.to_dot().view() +# execution.to_dot().view() with open(os.path.join(OUT_DIR, f"{filename}.nt"), "w") as f: f.write(doc.write_string(sbol3.SORTED_NTRIPLES).strip()) diff --git a/labop/execution/behavior_dynamics.py b/labop/execution/behavior_dynamics.py index 52449733..8244b4db 100644 --- a/labop/execution/behavior_dynamics.py +++ b/labop/execution/behavior_dynamics.py @@ -16,10 +16,14 @@ # Project packages import uml -from labop import ActivityNodeExecution, SampleArray, SampleCollection, SampleMap from labop.data import deserialize_sample_format, serialize_sample_format from labop.strings import Strings +from ..activity_node_execution import ActivityNodeExecution +from ..sample_array import SampleArray +from ..sample_collection import SampleCollection +from ..sample_map import SampleMap + class SampleProvenanceObserver: """ diff --git a/labop/execution/execution_engine.py b/labop/execution/execution_engine.py index 6ddf49c1..dc971f1e 100644 --- a/labop/execution/execution_engine.py +++ b/labop/execution/execution_engine.py @@ -2,6 +2,7 @@ import hashlib import logging import os +import types import uuid from abc import ABC from typing import Callable, Dict, List, Optional, Tuple, Union @@ -23,16 +24,21 @@ from labop.sample_data import SampleData from labop.strings import Strings from uml import ActivityNode, CallBehaviorAction +from uml.action import Action from uml.activity import Activity from uml.activity_edge import ActivityEdge from uml.activity_parameter_node import ActivityParameterNode +from uml.fork_node import ForkNode +from uml.literal_specification import LiteralSpecification from uml.object_flow import ObjectFlow from uml.output_pin import OutputPin +from uml.parameter import Parameter from uml.pin import Pin from uml.utils import WellFormednessIssue, WellformednessLevels, literal from .behavior_dynamics import SampleProvenanceObserver from .execution_context import ExecutionContext +from .primitive_execution import primitive_to_output_function l: logging.Logger = logging.getLogger(__file__) l.setLevel(logging.ERROR) @@ -182,6 +188,16 @@ def get_current_time(self, as_string: bool = False): cur_time = self.start_time + rel_start return cur_time if not as_string else str(cur_time) + def initialize_primitive_compute_output(self, doc: sbol3.Document): + for k, v in primitive_to_output_function.items(): + try: + p = Primitive.get_primitive(doc, k, copy_to_doc=False) + p.compute_output = types.MethodType(v, p) + except Exception as e: + l.warning( + f"Could not set compute_output() for primitive {k}, did you import the correct library?" + ) + def initialize( self, protocol: Protocol, @@ -198,7 +214,7 @@ def initialize( if self.use_defined_primitives: # Define the compute_output function for known primitives - Primitive.initialize_primitive_compute_output(doc) + self.initialize_primitive_compute_output(doc) # First, set up the record for the protocol and parameter values if self.ex is not None and overwrite_execution: @@ -468,7 +484,8 @@ def next_tokens( ActivityEdgeFlow( edge=edge, token_source=record, - value=node.get_value( + value=self.get_value( + node, edge, parameter_value_map, node_outputs, @@ -505,7 +522,8 @@ def next_tokens( ActivityEdgeFlow( edge=edge, token_source=record, - value=node.get_value( + value=self.get_value( + node, edge, parameter_value_map, node_outputs, @@ -559,6 +577,178 @@ def next_tokens( return new_tokens + def get_value( + self, + node: ActivityNode, + edge: "ActivityEdge", + node_inputs: Dict[str, Union[List[LiteralSpecification], LiteralSpecification]], + node_outputs: Callable, + sample_format: str, + invocation_hash: int, + ): + value = "" + reference = False + from uml.control_flow import ControlFlow + from uml.object_flow import ObjectFlow + + if isinstance(edge, ControlFlow): + value = ["uml.ControlFlow"] + elif isinstance(edge, ObjectFlow): + if isinstance(node, Pin): + value = self.get_pin_value( + node, + edge, + node_inputs, + node_outputs, + sample_format, + invocation_hash, + ) + elif isinstance(node, ForkNode): + value = self.get_fork_node_value( + node, + edge, + node_inputs, + node_outputs, + sample_format, + invocation_hash, + ) + elif isinstance(node, ActivityParameterNode): + value = self.get_activity_parameter_node_value( + node, + edge, + node_inputs, + node_outputs, + sample_format, + invocation_hash, + ) + elif isinstance(node, Action): + value = self.get_action_value( + node, + edge, + node_inputs, + node_outputs, + sample_format, + invocation_hash, + ) + + reference = lambda v: (isinstance(v, sbol3.Identified) and v.identity != None) + if isinstance(value, list): + value = [literal(v, reference=reference(v)) for v in value] + else: + value = [literal(value, reference=reference(value))] + return value + + # from OutputPin + def get_pin_value( + self, + node: "Pin", + edge: "ActivityEdge", + node_inputs: Dict[str, Union[List[LiteralSpecification], LiteralSpecification]], + node_outputs: Callable, + sample_format: str, + invocation_hash: int, + ): + value = node_inputs[node.name] + return value + + # from ForkNode + def get_fork_node_value( + self, + node: "ForkNode", + edge: "ActivityEdge", + parameter_value_map: Dict[str, List[LiteralSpecification]], + node_outputs: Callable, + sample_format: str, + invocation_hash: int, + ): + value = next(iter(parameter_value_map.values())) + return value + + # from ActivityParameterNode + def get_activity_parameter_node_value( + self, + node: ActivityParameterNode, + edge: "ActivityEdge", + parameter_value_map: Dict[str, List[LiteralSpecification]], + node_outputs: Callable, + sample_format: str, + invocation_hash: int, + ): + if node.is_output(): + value = parameter_value_map[node.name] + else: + value = "" + return value + + # from Action + def get_action_value( + self, + node: Action, + edge: "ActivityEdge", + parameter_value_map: Dict[str, List[LiteralSpecification]], + node_outputs: Callable, + sample_format: str, + invocation_hash: int, + ): + parameter = node.get_parameter(name=edge.get_target().name) + value = self.get_parameter_value( + node, + parameter, + parameter_value_map, + node_outputs, + sample_format, + invocation_hash, + ) + + return value + + # from CBA + def get_call_behavior_action_value( + self, + node: CallBehaviorAction, + edge: "ActivityEdge", + parameter_value_map: Dict[str, List[LiteralSpecification]], + node_outputs: Callable, + sample_format: str, + invocation_hash: int, + ): + from .activity import Activity + + if isinstance(node.get_behavior(), Activity): + # Activity Invocations do not send objects to their output pins + # The activity output parameters will send object to the output pins. + value = "uml.ControlFlow" + reference = False + else: + parameter = node.get_parameter(name=edge.get_target().name) + value = node_outputs( + parameter, parameter_value_map, sample_format, invocation_hash + ) + return value + + def get_parameter_value( + self, + call_behavior_action: CallBehaviorAction, + parameter: Parameter, + parameter_value_map: Dict[str, List[LiteralSpecification]], + node_outputs: Callable, + sample_format: str, + invocation_hash: int, + ): + if node_outputs: + value = node_outputs(self, parameter) + elif hasattr(call_behavior_action.get_behavior(), "compute_output"): + value = call_behavior_action.get_behavior().compute_output( + parameter_value_map, + parameter, + sample_format, + invocation_hash, + self, + ) + else: + value = f"{parameter.name}" + return value + def possible_calling_behaviors(self, node: ActivityNode): # Get all CallBehaviorAction nodes that correspond to a CallBehaviorExecution that supports the current execution of the ActivityNode tokens_supporting_node = [ diff --git a/labop/execution/harness.py b/labop/execution/harness.py index bb62ece7..da088503 100644 --- a/labop/execution/harness.py +++ b/labop/execution/harness.py @@ -518,7 +518,9 @@ def __init__(self, *args, **kwargs): self.base_dir = kwargs["base_dir"] if "base_dir" in kwargs else "." self.output_dir = ( - kwargs["output_dir"] if "output_dir" in kwargs else "artifacts" + kwargs["output_dir"] + if "output_dir" in kwargs + else f"{self.protocol_name}/artifacts" ) self.full_output_dir = os.path.join(self.base_dir, self.output_dir) @@ -610,7 +612,7 @@ def __init__(self, *args, **kwargs): self._results = {} def filename_prefix(self) -> str: - return self.entry_point.__name__ + return self.protocol_name def dataset_filename(self) -> str: return self.filename_prefix() + ".data.xslx" diff --git a/labop/execution/primitive_execution.py b/labop/execution/primitive_execution.py new file mode 100644 index 00000000..a86514a7 --- /dev/null +++ b/labop/execution/primitive_execution.py @@ -0,0 +1,291 @@ +import logging + +from ..dataset import Dataset +from ..sample_array import SampleArray +from ..sample_data import SampleData +from ..sample_mask import SampleMask +from ..sample_metadata import SampleMetadata +from ..utils.helpers import get_short_uuid + +PRIMITIVE_BASE_NAMESPACE = "https://bioprotocols.org/labop/primitives/" + + +l = logging.Logger(__file__) +l.setLevel(logging.INFO) + + +def transfer_out(self, source, target, plan, sample_format): + if sample_format == "xarray": + sourceResult, targetResult = self.transfer(source, target, plan, sample_format) + return sourceResult + else: + raise Exception(f"Cannot initialize contents of: {self.identity}") + + +def transfer_in(self, source, target, plan, sample_format): + if sample_format == "xarray": + sourceResult, targetResult = self.transfer(source, target, plan, sample_format) + return targetResult + else: + raise Exception(f"Cannot initialize contents of: {self.identity}") + + +def transfer(self, source, target, plan, sample_format): + if sample_format == "xarray": + source_contents = source.to_data_array() + target_contents = target.to_data_array() + transfer = plan.get_map() + if ( + source.name in transfer.source_array + and target.name in transfer.target_array + ): + source_result = source_contents.rename( + {"aliquot": "source_aliquot", "array": "source_array"} + ) + target_result = target_contents.rename( + {"aliquot": "target_aliquot", "array": "target_array"} + ) + source_concentration = source_result / source_result.sum(dim="contents") + + amount_transferred = source_concentration * transfer + + source_result = source_result - amount_transferred.sum( + dim=["target_aliquot", "target_array"] + ) + target_result = target_result + amount_transferred.sum( + dim=["source_aliquot", "source_array"] + ) + + return source_result, target_result + else: + return source_contents, target_contents + else: + raise Exception(f"Cannot initialize contents of: {self.identity}") + + +def empty_container_compute_output( + self, input_map, parameter, sample_format, call_behavior_execution_hash, engine +): + if ( + parameter.name == "samples" + and parameter.type == "http://bioprotocols.org/labop#SampleArray" + ): + # Make a SampleArray + spec = input_map["specification"] + sample_array = ( + input_map["sample_array"] if "sample_array" in input_map else None + ) + + if not sample_array: + sample_array = SampleArray.from_container_spec( + spec, sample_format=sample_format + ) + sample_array.name = spec.name + + # This attribute isn't formally specified in the ontology yet, but supports handling of different sample formats by BehaviorSpecialiations + # sample_array.format = sample_format + return sample_array + else: + return None + + +def empty_rack_compute_output( + self, input_map, parameter, sample_format, call_behavior_execution_hash, engine +): + if ( + parameter.name == "slots" + and parameter.type == "http://bioprotocols.org/labop#SampleArray" + ): + # Make a SampleArray + spec = input_map["specification"] + sample_array = SampleArray.from_container_spec( + spec, sample_format=sample_format + ) + return sample_array + else: + return None + + +def load_container_on_instrument_compute_output( + self, input_map, parameter, sample_format, call_behavior_execution_hash, engine +): + if ( + parameter.name == "samples" + and parameter.type == "http://bioprotocols.org/labop#SampleArray" + ): + # Make a SampleArray + spec = input_map["specification"] + sample_array = SampleArray.from_container_spec( + spec, sample_format=sample_format + ) + return sample_array + else: + return None + + +def plate_coordinates_compute_output( + self, input_map, parameter, sample_format, call_behavior_execution_hash, engine +): + if ( + parameter.name == "samples" + and parameter.type == "http://bioprotocols.org/labop#SampleCollection" + ): + source = input_map["source"] + coordinates = input_map["coordinates"] + # convert coordinates into a boolean sample mask array + # 1. read source contents into array + # 2. create parallel array for entries noted in coordinates + mask = SampleMask.from_coordinates( + source, coordinates, sample_format=sample_format + ) + + return mask + + +def measure_absorbance_compute_output( + self, input_map, parameter, sample_format, call_behavior_execution_hash, engine +): + if ( + parameter.name == "measurements" + and parameter.type == "http://bioprotocols.org/labop#Dataset" + ): + samples = input_map["samples"] + wl = input_map["wavelength"] + from labop.execution.lab_interface import LabInterface + + measurements = LabInterface.measure_absorbance(samples, wl.value, sample_format) + name = f"{self.display_id}.{parameter.name}.{get_short_uuid(call_behavior_execution_hash+hash(parameter))}" + sample_data = SampleData(name=name, from_samples=samples, values=measurements) + sample_metadata = SampleMetadata.for_primitive( + self, input_map, samples, sample_format=sample_format + ) + sample_dataset = Dataset(data=sample_data, metadata=[sample_metadata]) + return sample_dataset + + +def measure_fluorescence_compute_output( + self, input_map, parameter, sample_format, call_behavior_execution_hash, engine +): + if ( + parameter.name == "measurements" + and parameter.type == "http://bioprotocols.org/labop#Dataset" + ): + samples = input_map["samples"] + exwl = input_map["excitationWavelength"] + emwl = input_map["emissionWavelength"] + bandpass = input_map["emissionBandpassWidth"] + from labop.execution.lab_interface import LabInterface + + measurements = LabInterface.measure_fluorescence( + samples, + exwl.value, + emwl.value, + bandpass.value, + sample_format, + ) + name = f"{self.display_id}.{parameter.name}.{get_short_uuid(get_short_uuid(call_behavior_execution_hash+hash(parameter)))}" + sample_data = SampleData(name=name, from_samples=samples, values=measurements) + sample_metadata = SampleMetadata.for_primitive( + self, input_map, samples, sample_format=sample_format + ) + sample_dataset = Dataset(data=sample_data, metadata=[sample_metadata]) + return sample_dataset + + +def join_metadata_compute_output( + self, input_map, parameter, sample_format, call_behavior_execution_hash, engine +): + if ( + parameter.name == "enhanced_dataset" + and parameter.type == "http://bioprotocols.org/labop#Dataset" + ): + dataset = input_map["dataset"] + metadata = input_map["metadata"] + enhanced_dataset = Dataset(dataset=[dataset], linked_metadata=[metadata]) + return enhanced_dataset + + +def join_datasets_compute_output( + self, input_map, parameter, sample_format, call_behavior_execution_hash, engine +): + if ( + parameter.name == "joint_dataset" + and parameter.type == "http://bioprotocols.org/labop#Dataset" + ): + datasets = input_map["dataset"] + metadata = ( + input_map["metadata"] + if "metadata" in input_map and input_map["metadata"] + else [] + ) + joint_dataset = Dataset(dataset=datasets, linked_metadata=metadata) + return joint_dataset + + +def excel_metadata_compute_output( + self, input_map, parameter, sample_format, call_behavior_execution_hash, engine +): + if ( + parameter.name == "metadata" + and parameter.type == "http://bioprotocols.org/labop#SampleMetadata" + ): + filename = input_map["filename"] + for_samples = input_map["for_samples"] # check dataarray + metadata = SampleMetadata.from_excel( + filename, for_samples, sample_format=sample_format + ) + return metadata + + +def compute_metadata_compute_output( + self, input_map, parameter, sample_format, call_behavior_execution_hash, engine +): + if ( + parameter.name == "metadata" + and parameter.type == "http://bioprotocols.org/labop#SampleMetadata" + ): + for_samples = input_map["for_samples"] + metadata = SampleMetadata.from_sample_graph(for_samples, engine) + return metadata + + +def transfer_by_map_compute_output(self, inputs, parameter, sample_format, engine): + if ( + parameter.name == "sourceResult" + and parameter.type == "http://bioprotocols.org/labop#SampleCollection" + ): + source = input_map["source"] + target = input_map["destination"] + plan = input_map["plan"] + spec = source.container_type + contents = self.transfer_out(source, target, plan, sample_format) + name = f"{parameter.name}" + result = SampleArray(name=name, container_type=spec, contents=contents) + elif ( + parameter.name == "destinationResult" + and parameter.type == "http://bioprotocols.org/labop#SampleCollection" + ): + input_map = input_parameter_map(inputs) + source = input_map["source"] + target = input_map["destination"] + plan = input_map["plan"] + spec = source.container_type + contents = self.transfer_in(source, target, plan, sample_format) + name = f"{parameter.name}" + result = SampleArray(name=name, container_type=spec, contents=contents) + return result + + +primitive_to_output_function = { + "EmptyContainer": empty_container_compute_output, + "PlateCoordinates": plate_coordinates_compute_output, + "MeasureAbsorbance": measure_absorbance_compute_output, + "MeasureFluorescence": measure_fluorescence_compute_output, + "EmptyInstrument": empty_rack_compute_output, + "EmptyRack": empty_rack_compute_output, + "LoadContainerOnInstrument": load_container_on_instrument_compute_output, + "JoinMetadata": join_metadata_compute_output, + "JoinDatasets": join_datasets_compute_output, + "ExcelMetadata": excel_metadata_compute_output, + "ComputeMetadata": compute_metadata_compute_output, +} diff --git a/labop/primitive.py b/labop/primitive.py index 18625f99..48e5b4cf 100644 --- a/labop/primitive.py +++ b/labop/primitive.py @@ -3,7 +3,6 @@ """ import logging -import types from typing import Dict, List import sbol3 @@ -11,13 +10,7 @@ from uml import PARAMETER_IN, PARAMETER_OUT, Behavior, inner_to_outer from . import inner -from .dataset import Dataset from .library import loaded_libraries -from .sample_array import SampleArray -from .sample_data import SampleData -from .sample_mask import SampleMask -from .sample_metadata import SampleMetadata -from .utils.helpers import get_short_uuid PRIMITIVE_BASE_NAMESPACE = "https://bioprotocols.org/labop/primitives/" @@ -130,7 +123,12 @@ def mark_optional(parameter): """ def compute_output( - self, inputs, parameter, sample_format, call_behavior_execution_hash + self, + inputs, + parameter, + sample_format, + call_behavior_execution_hash, + engine, ): """ Compute the value for parameter given the inputs. This default function will be overridden for specific primitives. @@ -177,293 +175,6 @@ def compute_output( ) return f"{parameter.name}" - def transfer_out(self, source, target, plan, sample_format): - if sample_format == "xarray": - sourceResult, targetResult = self.transfer( - source, target, plan, sample_format - ) - return sourceResult - else: - raise Exception(f"Cannot initialize contents of: {self.identity}") - - def transfer_in(self, source, target, plan, sample_format): - if sample_format == "xarray": - sourceResult, targetResult = self.transfer( - source, target, plan, sample_format - ) - return targetResult - else: - raise Exception(f"Cannot initialize contents of: {self.identity}") - - def transfer(self, source, target, plan, sample_format): - if sample_format == "xarray": - source_contents = source.to_data_array() - target_contents = target.to_data_array() - transfer = plan.get_map() - if ( - source.name in transfer.source_array - and target.name in transfer.target_array - ): - source_result = source_contents.rename( - {"aliquot": "source_aliquot", "array": "source_array"} - ) - target_result = target_contents.rename( - {"aliquot": "target_aliquot", "array": "target_array"} - ) - source_concentration = source_result / source_result.sum(dim="contents") - - amount_transferred = source_concentration * transfer - - source_result = source_result - amount_transferred.sum( - dim=["target_aliquot", "target_array"] - ) - target_result = target_result + amount_transferred.sum( - dim=["source_aliquot", "source_array"] - ) - - return source_result, target_result - else: - return source_contents, target_contents - else: - raise Exception(f"Cannot initialize contents of: {self.identity}") - - def empty_container_compute_output( - self, input_map, parameter, sample_format, call_behavior_execution_hash - ): - if ( - parameter.name == "samples" - and parameter.type == "http://bioprotocols.org/labop#SampleArray" - ): - # Make a SampleArray - spec = input_map["specification"] - sample_array = ( - input_map["sample_array"] if "sample_array" in input_map else None - ) - - if not sample_array: - sample_array = SampleArray.from_container_spec( - spec, sample_format=sample_format - ) - sample_array.name = spec.name - - # This attribute isn't formally specified in the ontology yet, but supports handling of different sample formats by BehaviorSpecialiations - # sample_array.format = sample_format - return sample_array - else: - return None - - def empty_rack_compute_output( - self, input_map, parameter, sample_format, call_behavior_execution_hash - ): - if ( - parameter.name == "slots" - and parameter.type == "http://bioprotocols.org/labop#SampleArray" - ): - # Make a SampleArray - spec = input_map["specification"] - sample_array = SampleArray.from_container_spec( - spec, sample_format=sample_format - ) - return sample_array - else: - return None - - def load_container_on_instrument_compute_output( - self, input_map, parameter, sample_format, call_behavior_execution_hash - ): - if ( - parameter.name == "samples" - and parameter.type == "http://bioprotocols.org/labop#SampleArray" - ): - # Make a SampleArray - spec = input_map["specification"] - sample_array = SampleArray.from_container_spec( - spec, sample_format=sample_format - ) - return sample_array - else: - return None - - def plate_coordinates_compute_output( - self, input_map, parameter, sample_format, call_behavior_execution_hash - ): - if ( - parameter.name == "samples" - and parameter.type == "http://bioprotocols.org/labop#SampleCollection" - ): - source = input_map["source"] - coordinates = input_map["coordinates"] - # convert coordinates into a boolean sample mask array - # 1. read source contents into array - # 2. create parallel array for entries noted in coordinates - mask = SampleMask.from_coordinates( - source, coordinates, sample_format=sample_format - ) - - return mask - - def measure_absorbance_compute_output( - self, input_map, parameter, sample_format, call_behavior_execution_hash - ): - if ( - parameter.name == "measurements" - and parameter.type == "http://bioprotocols.org/labop#Dataset" - ): - samples = input_map["samples"] - wl = input_map["wavelength"] - from labop.execution.lab_interface import LabInterface - - measurements = LabInterface.measure_absorbance( - samples, wl.value, sample_format - ) - name = f"{self.display_id}.{parameter.name}.{get_short_uuid(call_behavior_execution_hash+hash(parameter))}" - sample_data = SampleData( - name=name, from_samples=samples, values=measurements - ) - sample_metadata = SampleMetadata.for_primitive( - self, input_map, samples, sample_format=sample_format - ) - sample_dataset = Dataset(data=sample_data, metadata=[sample_metadata]) - return sample_dataset - - def measure_fluorescence_compute_output( - self, input_map, parameter, sample_format, call_behavior_execution_hash - ): - if ( - parameter.name == "measurements" - and parameter.type == "http://bioprotocols.org/labop#Dataset" - ): - samples = input_map["samples"] - exwl = input_map["excitationWavelength"] - emwl = input_map["emissionWavelength"] - bandpass = input_map["emissionBandpassWidth"] - from labop.execution.lab_interface import LabInterface - - measurements = LabInterface.measure_fluorescence( - samples, - exwl.value, - emwl.value, - bandpass.value, - sample_format, - ) - name = f"{self.display_id}.{parameter.name}.{get_short_uuid(get_short_uuid(call_behavior_execution_hash+hash(parameter)))}" - sample_data = SampleData( - name=name, from_samples=samples, values=measurements - ) - sample_metadata = SampleMetadata.for_primitive( - self, input_map, samples, sample_format=sample_format - ) - sample_dataset = Dataset(data=sample_data, metadata=[sample_metadata]) - return sample_dataset - - def join_metadata_compute_output( - self, input_map, parameter, sample_format, call_behavior_execution_hash - ): - if ( - parameter.name == "enhanced_dataset" - and parameter.type == "http://bioprotocols.org/labop#Dataset" - ): - dataset = input_map["dataset"] - metadata = input_map["metadata"] - enhanced_dataset = Dataset(dataset=[dataset], linked_metadata=[metadata]) - return enhanced_dataset - - def join_datasets_compute_output( - self, input_map, parameter, sample_format, call_behavior_execution_hash - ): - if ( - parameter.name == "joint_dataset" - and parameter.type == "http://bioprotocols.org/labop#Dataset" - ): - datasets = input_map["dataset"] - metadata = ( - input_map["metadata"] - if "metadata" in input_map and input_map["metadata"] - else [] - ) - joint_dataset = Dataset(dataset=datasets, linked_metadata=metadata) - return joint_dataset - - def excel_metadata_compute_output( - self, input_map, parameter, sample_format, call_behavior_execution_hash - ): - if ( - parameter.name == "metadata" - and parameter.type == "http://bioprotocols.org/labop#SampleMetadata" - ): - filename = input_map["filename"] - for_samples = input_map["for_samples"] # check dataarray - metadata = SampleMetadata.from_excel( - filename, for_samples, sample_format=sample_format - ) - return metadata - - def compute_metadata_compute_output( - self, input_map, parameter, sample_format, call_behavior_execution_hash - ): - if ( - parameter.name == "metadata" - and parameter.type == "http://bioprotocols.org/labop#SampleMetadata" - ): - for_samples = input_map["for_samples"] - metadata = SampleMetadata.from_sample_graph(for_samples, engine) - return metadata - - def transfer_by_map_compute_output( - self, - inputs, - parameter, - sample_format, - ): - if ( - parameter.name == "sourceResult" - and parameter.type == "http://bioprotocols.org/labop#SampleCollection" - ): - source = input_map["source"] - target = input_map["destination"] - plan = input_map["plan"] - spec = source.container_type - contents = self.transfer_out(source, target, plan, sample_format) - name = f"{parameter.name}" - result = SampleArray(name=name, container_type=spec, contents=contents) - elif ( - parameter.name == "destinationResult" - and parameter.type == "http://bioprotocols.org/labop#SampleCollection" - ): - input_map = input_parameter_map(inputs) - source = input_map["source"] - target = input_map["destination"] - plan = input_map["plan"] - spec = source.container_type - contents = self.transfer_in(source, target, plan, sample_format) - name = f"{parameter.name}" - result = SampleArray(name=name, container_type=spec, contents=contents) - return result - - primitive_to_output_function = { - "EmptyContainer": empty_container_compute_output, - "PlateCoordinates": plate_coordinates_compute_output, - "MeasureAbsorbance": measure_absorbance_compute_output, - "MeasureFluorescence": measure_fluorescence_compute_output, - "EmptyInstrument": empty_rack_compute_output, - "EmptyRack": empty_rack_compute_output, - "LoadContainerOnInstrument": load_container_on_instrument_compute_output, - "JoinMetadata": join_metadata_compute_output, - "JoinDatasets": join_datasets_compute_output, - "ExcelMetadata": excel_metadata_compute_output, - "ComputeMetadata": compute_metadata_compute_output, - } - - def initialize_primitive_compute_output(doc: sbol3.Document): - for k, v in Primitive.primitive_to_output_function.items(): - try: - p = Primitive.get_primitive(doc, k, copy_to_doc=False) - p.compute_output = types.MethodType(v, p) - except Exception as e: - l.warning( - f"Could not set compute_output() for primitive {k}, did you import the correct library?" - ) - def declare_primitive( document: sbol3.Document, library: str, diff --git a/labop/sample_metadata.py b/labop/sample_metadata.py index 93477d4f..5c007f2b 100644 --- a/labop/sample_metadata.py +++ b/labop/sample_metadata.py @@ -128,7 +128,7 @@ def to_dataarray(self): return deserialize_sample_format(self.descriptions, parent=self) def from_sample_graph(for_samples, engine, record_source=False): - metadata = labop.SampleMetadata(for_samples=for_samples) + metadata = SampleMetadata(for_samples=for_samples) if engine.sample_format == Strings.XARRAY: # Convert pd.DataFrame into xr.DataArray diff --git a/labop_convert/markdown/markdown_specialization.py b/labop_convert/markdown/markdown_specialization.py index 8ea3bab0..cf428a86 100644 --- a/labop_convert/markdown/markdown_specialization.py +++ b/labop_convert/markdown/markdown_specialization.py @@ -12,10 +12,10 @@ import tyto import xarray as xr -from labop import SampleMask from labop.data import deserialize_sample_format from labop.sample_array import SampleArray from labop.sample_collection import SampleCollection +from labop.sample_mask import SampleMask from labop.strings import Strings from labop_convert.behavior_specialization import DefaultBehaviorSpecialization from uml import ( diff --git a/test/test_LUDOX_protocol.py b/test/test_LUDOX_protocol.py index 7aac7390..6e50914b 100644 --- a/test/test_LUDOX_protocol.py +++ b/test/test_LUDOX_protocol.py @@ -27,7 +27,7 @@ def create_protocol(self, doc, protocol: labop.Protocol) -> labop.Protocol: def test_create_protocol(self): harness = labop.execution.harness.ProtocolHarness( clean_output=True, - base_dir=os.path.dirname(__file__), + base_dir=os.path.join(os.path.dirname(__file__), "out"), entry_point=self.create_protocol, namespace="https://bbn.com/scratch/", protocol_name="iGEM_LUDOX_OD_calibration_2018", diff --git a/test/test_decision_nodes.py b/test/test_decision_nodes.py index cef6445c..359b246e 100644 --- a/test/test_decision_nodes.py +++ b/test/test_decision_nodes.py @@ -47,7 +47,7 @@ def create_protocol(self, doc: sbol3.Document, protocol: labop.Protocol): doc.add(pH_meter_calibrated) def pH_meter_calibrated_compute_output( - inputs, parameter, sample_format, record_hash + inputs, parameter, sample_format, record_hash, engine ): return True diff --git a/uml/action.py b/uml/action.py index 84314d5f..e0b8380d 100644 --- a/uml/action.py +++ b/uml/action.py @@ -2,7 +2,7 @@ The Action class defines the functions corresponding to the dynamically generated labop class Action """ -from typing import Callable, Dict, List +from typing import Dict, List import sbol3 @@ -161,7 +161,7 @@ def get_parameter(self, name: str = None, ordered=False): return next(iter(params)) else: raise ValueError( - f"Invalid parameter {name} provided for Primitive {behavior.display_id}" + f"Invalid parameter {name} provided for Primitive {self.get_behavior().display_id}" ) def is_well_formed(self) -> List[WellFormednessIssue]: @@ -270,28 +270,3 @@ def enabled( else: return control_tokens_present - - def get_value( - self, - edge: "ActivityEdge", - parameter_value_map: Dict[str, List[LiteralSpecification]], - node_outputs: Callable, - sample_format: str, - ): - from .control_flow import ControlFlow - from .object_flow import ObjectFlow - - value = "" - reference = False - - if isinstance(edge, ControlFlow): - value = "uml.ControlFlow" - elif isinstance(edge, ObjectFlow): - parameter = self.get_parameter(name=edge.get_source().name) - value = self.get_parameter_value( - parameter, parameter_value_map, node_outputs, sample_format - ) - reference = isinstance(value, sbol3.Identified) and value.identity != None - - value = [literal(value, reference=reference)] - return value diff --git a/uml/activity_node.py b/uml/activity_node.py index 3cb4306a..5b9e8582 100644 --- a/uml/activity_node.py +++ b/uml/activity_node.py @@ -186,28 +186,6 @@ def next_tokens_callback( edge_tokens[edge] = edge_value return edge_tokens - def get_value( - self, - edge: "ActivityEdge", - parameter_value_map: Dict[str, List[LiteralSpecification]], - node_outputs: Callable, - sample_format: str, - invocation_hash: int, - ): - from .control_flow import ControlFlow - from .object_flow import ObjectFlow - - value = "" - reference = False - - if isinstance(edge, ControlFlow): - value = "uml.ControlFlow" - elif isinstance(edge, ObjectFlow): - raise Exception("ActivityNode cannot get_value of outgoing ObjectFlow") - - value = [literal(value, reference=reference)] - return value - def is_well_formed(self) -> List[WellFormednessIssue]: return [] diff --git a/uml/activity_parameter_node.py b/uml/activity_parameter_node.py index 5fc5cd34..b5452fd2 100644 --- a/uml/activity_parameter_node.py +++ b/uml/activity_parameter_node.py @@ -36,18 +36,6 @@ def is_output(self): def is_input(self): return self.get_parameter().is_input() - # def get_value(self) -> Dict[Parameter, LiteralSpecification]: - # values = [ - # i.value.get_value() - # for i in self.incoming_flows - # if isinstance(i.edge.lookup(), ObjectFlow) - # ] - # assert len(values) < 2, "ActivityParameterNode has too many incoming values" - # if len(values) == 1: - # return values[0] - # else: - # return None - def next_tokens_callback( self, node_inputs: Dict["ActivityEdge", LiteralSpecification], @@ -101,24 +89,3 @@ def next_tokens_callback( else: edge_tokens = [] return edge_tokens - - def get_value( - self, - edge: "ActivityEdge", - parameter_value_map: Dict[str, List[LiteralSpecification]], - node_outputs: Callable, - sample_format: str, - invocation_hash: int, - ): - value = "" - reference = False - - if isinstance(edge, ControlFlow): - value = "uml.ControlFlow" - elif isinstance(edge, ObjectFlow): - if self.is_output(): - value = parameter_value_map[self.name] - reference = True - - value = [literal(value, reference=reference)] - return value diff --git a/uml/call_behavior_action.py b/uml/call_behavior_action.py index bc8e979b..e2d240da 100644 --- a/uml/call_behavior_action.py +++ b/uml/call_behavior_action.py @@ -3,7 +3,7 @@ dynamically generated labop class CallBehaviorAction """ -from typing import Callable, Dict, List +from typing import List import graphviz import sbol3 @@ -98,70 +98,6 @@ def dot_attrs(self, incoming_edges: List["ActivityEdge"]): shape = "none" return {"label": label, "shape": shape, "style": "rounded"} - def get_value( - self, - edge: "ActivityEdge", - parameter_value_map: Dict[str, List[LiteralSpecification]], - node_outputs: Callable, - sample_format: str, - invocation_hash: int, - ): - from .activity import Activity - - if isinstance(edge, ControlFlow): - return ActivityNode.get_value( - self, - edge, - parameter_value_map, - node_outputs, - sample_format, - invocation_hash, - ) - elif isinstance(edge, ObjectFlow): - if isinstance(self.get_behavior(), Activity): - # Activity Invocations do not send objects to their output pins - # The activity output parameters will send object to the output pins. - value = "uml.ControlFlow" - reference = False - else: - parameter = self.get_parameter(name=edge.get_target().name) - value = self.get_parameter_value( - parameter, - parameter_value_map, - node_outputs, - sample_format, - invocation_hash, - ) - - reference = ( - isinstance(value, sbol3.Identified) and value.identity != None - ) - if isinstance(value, list) or isinstance( - value, sbol3.ownedobject.OwnedObjectListProperty - ): - value = [literal(v, reference=reference) for v in value] - else: - value = [literal(value, reference=reference)] - return value - - def get_parameter_value( - self, - parameter: Parameter, - parameter_value_map: Dict[str, List[LiteralSpecification]], - node_outputs: Callable, - sample_format: str, - invocation_hash: int, - ): - if node_outputs: - value = node_outputs(self, parameter) - elif hasattr(self.get_behavior(), "compute_output"): - value = self.get_behavior().compute_output( - parameter_value_map, parameter, sample_format, invocation_hash - ) - else: - value = f"{parameter.name}" - return value - def auto_advance(self): """ Is the node executable without additional manual input? diff --git a/uml/fork_node.py b/uml/fork_node.py index 76e3ebca..a7a09fc0 100644 --- a/uml/fork_node.py +++ b/uml/fork_node.py @@ -79,32 +79,3 @@ def next_tokens_callback( for edge in out_edges ] return edge_tokens - - def get_value( - self, - edge: "ActivityEdge", - parameter_value_map: Dict[str, List[LiteralSpecification]], - node_outputs: Callable, - sample_format: str, - invocation_hash: int, - ): - if isinstance(edge, ControlFlow): - return ActivityNode.get_value( - self, - edge, - parameter_value_map, - node_outputs, - sample_format, - invocation_hash, - ) - elif isinstance(edge, ObjectFlow): - value = next(iter(parameter_value_map.values())) - reference = True - - if isinstance(value, list) or isinstance( - value, sbol3.ownedobject.OwnedObjectListProperty - ): - value = [literal(v, reference=reference) for v in value] - else: - value = [literal(value, reference=reference)] - return value diff --git a/uml/input_pin.py b/uml/input_pin.py index 5ef0a39c..ea7515be 100644 --- a/uml/input_pin.py +++ b/uml/input_pin.py @@ -2,7 +2,7 @@ The InputPin class defines the functions corresponding to the dynamically generated labop class InputPin """ -from typing import Callable, Dict, List, Union +from typing import Callable, Dict, List import sbol3 @@ -57,33 +57,6 @@ def next_tokens_callback( edge_tokens = [(None, source, pin_value) for pin_value in pin_values] return edge_tokens - def get_value( - self, - edge: "ActivityEdge", - node_inputs: Dict[str, Union[List[LiteralSpecification], LiteralSpecification]], - node_outputs: Callable, - sample_format: str, - invocation_hash: int, - ): - value = "" - reference = False - from .control_flow import ControlFlow - from .object_flow import ObjectFlow - - if isinstance(edge, ControlFlow): - value = "uml.ControlFlow" - elif isinstance(edge, ObjectFlow): - value = node_inputs[self.name] - reference = True - - if isinstance(value, list) or isinstance( - value, sbol3.ownedobject.OwnedObjectListProperty - ): - value = [literal(v, reference=reference) for v in value] - else: - value = [literal(value, reference=reference)] - return value - def is_well_formed(self) -> List[WellFormednessIssue]: """ An InputPin is well formed if: diff --git a/uml/output_pin.py b/uml/output_pin.py index ca8adc17..821a3a55 100644 --- a/uml/output_pin.py +++ b/uml/output_pin.py @@ -2,7 +2,6 @@ The OutputPin class defines the functions corresponding to the dynamically generated labop class OutputPin """ -from typing import Callable, Dict, List, Union from . import inner from .literal_specification import LiteralSpecification @@ -14,33 +13,3 @@ class OutputPin(inner.OutputPin, Pin): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._where_defined = self.get_where_defined() - - def get_value( - self, - edge: "ActivityEdge", - node_inputs: Dict[str, Union[List[LiteralSpecification], LiteralSpecification]], - node_outputs: Callable, - sample_format: str, - invocation_hash: int, - ): - from .control_flow import ControlFlow - from .object_flow import ObjectFlow - - value = "" - reference = False - - if isinstance(edge, ControlFlow): - value = ["uml.ControlFlow"] - elif isinstance(edge, ObjectFlow): - call_node = self.get_parent() - # parameter = call_node.get_parameter( - # edge.get_source().name - # ).property_value - value = node_inputs[self.name] - reference = True - - if isinstance(value, list): - value = [literal(v, reference=reference) for v in value] - else: - value = [literal(value, reference=reference)] - return value From 7be80cc14410efd445f229171dd12e3cf34bfa12 Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:42:44 -0500 Subject: [PATCH 10/12] fix setup.py packages --- setup.py | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/setup.py b/setup.py index bfd46608..17c089e7 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -from setuptools import setup +from setuptools import find_packages, setup test_deps = [ "nbmake", @@ -36,22 +36,7 @@ ], tests_require=test_deps, extras_require=extras, - packages=[ - "labop", - "labop_convert", - "labop_convert.autoprotocol", - "labop_convert.markdown", - "labop_convert.opentrons", - "labop_convert.emeraldcloud", - "labop.lib", - "labop.inner", - "labop.utils", - "labop_time", - "uml", - "uml.inner", - "examples", - "owl_rdf_utils", - ], + packages=find_packages(".", exclude=["*attic", "examples"]), package_data={ "labop": ["inner/labop.ttl", "lib/*.ttl", "container-ontology.ttl"], "labop_convert": ["markdown/template.xlsx"], From f267eb3074ec0cc9b32c11cbc18e90bc9c8ecbfb Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:42:44 -0500 Subject: [PATCH 11/12] bad import --- test/test_opentrons.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_opentrons.py b/test/test_opentrons.py index db4ccf19..58f90328 100644 --- a/test/test_opentrons.py +++ b/test/test_opentrons.py @@ -7,10 +7,10 @@ import sbol3 import labop -from build.lib.labop_convert.opentrons import opentrons_specialization from labop.execution.execution_engine import ExecutionEngine from labop.execution.harness import ProtocolSpecialization from labop.utils.helpers import file_diff +from labop_convert.opentrons import opentrons_specialization from labop_convert.opentrons.opentrons_specialization import OT2Specialization # Save testfiles as artifacts when running in CI environment, From 5b438cba853f151cad27f5e1c67d6b1c1fa587db Mon Sep 17 00:00:00 2001 From: Daniel Bryce Date: Fri, 27 Oct 2023 07:42:44 -0500 Subject: [PATCH 12/12] remove import for constants --- .../protocols/growth-curve/growth_curve.py | 3 +- .../opentrons_ludox_example.py | 2 +- .../opentrons-pcr/opentrons_pcr_example.py | 457 +++++++++--------- .../opentrons-toy/opentrons_toy_protocol.py | 3 +- test/test_inputs.py | 10 +- 5 files changed, 237 insertions(+), 238 deletions(-) diff --git a/examples/protocols/growth-curve/growth_curve.py b/examples/protocols/growth-curve/growth_curve.py index 9d2b0afe..005b9406 100644 --- a/examples/protocols/growth-curve/growth_curve.py +++ b/examples/protocols/growth-curve/growth_curve.py @@ -2,13 +2,14 @@ import tyto import labop -from labop.constants import rpm from labop.execution.harness import ProtocolHarness, ProtocolSpecialization from labop.strings import Strings from labop_convert.markdown.markdown_specialization import MarkdownSpecialization def generate_protocol(doc, protocol: labop.Protocol) -> labop.Protocol: + from labop.constants import rpm + doc.add(rpm) ############################################# # Create the protocols diff --git a/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py b/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py index e27ce02f..9649655d 100644 --- a/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py +++ b/examples/protocols/opentrons/opentrons-ludox/opentrons_ludox_example.py @@ -2,7 +2,6 @@ import tyto import labop -from labop.constants import PREFIX_MAP, ddh2o, ludox from labop.execution.harness import ProtocolHarness, ProtocolSpecialization from labop.protocol import Protocol from labop.strings import Strings @@ -14,6 +13,7 @@ def generate_protocol(doc: sbol3.Document, activity: Protocol) -> Protocol: # create the materials to be provisioned + from labop.constants import PREFIX_MAP, ddh2o, ludox doc.add(ddh2o) doc.add(ludox) diff --git a/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py b/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py index cc91f22d..a5b46233 100644 --- a/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py +++ b/examples/protocols/opentrons/opentrons-pcr/opentrons_pcr_example.py @@ -1,13 +1,10 @@ import csv +import os -import rdflib as rdfl import sbol3 import tyto import labop -import uml -from labop.constants import PREFIX_MAP, ddh2o, ludox -from labop.execution.execution_engine import ExecutionEngine from labop_convert.opentrons.opentrons_specialization import OT2Specialization # Dev Note: This is a test of the initial version of the OT2 specialization. Any specs shown here can be changed in the future. Use at your own risk. Here be dragons. @@ -91,245 +88,245 @@ def load_pcr_plan(fname: str, doc: sbol3.Document): return plan -############################################# -# set up the document -print("Setting up document") -doc = sbol3.Document() -sbol3.set_namespace("https://bbn.com/scratch/") - -############################################# -# Import the primitive libraries -print("Importing libraries") -labop.import_library("liquid_handling") -print("... Imported liquid handling") -labop.import_library("plate_handling") -print("... Imported plate handling") -labop.import_library("spectrophotometry") -print("... Imported spectrophotometry") -labop.import_library("sample_arrays") -print("... Imported sample arrays") -labop.import_library("pcr") -print("... Imported pcr") - -############################3 -# load pcr setup -primer_layout = load_primer_layout("primer_layout.csv", doc) -templates = load_templates("pcr_plan.csv", doc) -pcr_plan = load_pcr_plan("pcr_plan.csv", doc) - - -activity = labop.Protocol("pcr_example") -activity.name = "Opentrons PCR Demo" -doc.add(activity) - - -doc.add(ddh2o) -doc.add(ludox) - -p300 = sbol3.Agent("p300_single", name="P300 Single") -doc.add(p300) - -# Configure OT2 and load it with labware -load = activity.primitive_step( - "ConfigureRobot", - instrument=OT2Specialization.EQUIPMENT["p300_single"], - mount="left", -) -load = activity.primitive_step( - "ConfigureRobot", - instrument=OT2Specialization.EQUIPMENT["thermocycler"], - mount="7", -) -# load = protocol.primitive_step('ConfigureRobot', instrument=OT2Specialization.EQUIPMENT['thermocycler'], mount='10') -spec_tiprack = labop.ContainerSpec( - "tiprack", queryString="cont:Opentrons96TipRack300uL", prefixMap=PREFIX_MAP -) -load = activity.primitive_step( - "LoadRackOnInstrument", rack=spec_tiprack, coordinates="1" -) - - -# Set up rack for reagents -reagent_rack = labop.ContainerSpec( - "reagent_rack", - name="Tube rack for reagents", - queryString="cont:Opentrons24TubeRackwithEppendorf1.5mLSafe-LockSnapcap", - prefixMap=PREFIX_MAP, -) -rack = activity.primitive_step("EmptyRack", specification=reagent_rack) -load_rack = activity.primitive_step( - "LoadRackOnInstrument", rack=reagent_rack, coordinates="2" -) - -# Set up primers plate -primer_plate = labop.ContainerSpec( - "primer_plate", - name="primers in 96-well plate", - queryString="cont:Corning96WellPlate360uLFlat", - prefixMap=PREFIX_MAP, -) -load = activity.primitive_step( - "LoadRackOnInstrument", rack=primer_plate, coordinates="3" -) -primer_plate = activity.primitive_step("EmptyContainer", specification=primer_plate) - -# Set up DNA polymerase -polymerase = labop.ContainerSpec( - "polymerase", - name="DNA Polymerase", - queryString="cont:StockReagent", - prefixMap=PREFIX_MAP, -) -load_reagents = activity.primitive_step( - "LoadContainerInRack", - slots=rack.output_pin("slots"), - container=polymerase, - coordinates="A1", -) - -# Set up water -load_water = activity.primitive_step( - "LoadContainerInRack", - slots=rack.output_pin("slots"), - container=labop.ContainerSpec( - "water", - name="tube for water", - queryString="cont:MicrofugeTube", +def create_protocol(doc, activity: labop.Protocol) -> labop.Protocol: + from labop.constants import PREFIX_MAP, ddh2o, ludox + + ############################3 + # load pcr setup + primer_layout = load_primer_layout("primer_layout.csv", doc) + templates = load_templates("pcr_plan.csv", doc) + pcr_plan = load_pcr_plan("pcr_plan.csv", doc) + + doc.add(ddh2o) + doc.add(ludox) + + p300 = sbol3.Agent("p300_single", name="P300 Single") + doc.add(p300) + + # Configure OT2 and load it with labware + load = activity.primitive_step( + "ConfigureRobot", + instrument=OT2Specialization.EQUIPMENT["p300_single"], + mount="left", + ) + load = activity.primitive_step( + "ConfigureRobot", + instrument=OT2Specialization.EQUIPMENT["thermocycler"], + mount="7", + ) + # load = protocol.primitive_step('ConfigureRobot', instrument=OT2Specialization.EQUIPMENT['thermocycler'], mount='10') + spec_tiprack = labop.ContainerSpec( + "tiprack", + queryString="cont:Opentrons96TipRack300uL", prefixMap=PREFIX_MAP, - ), - coordinates="B1", -) -provision_water = activity.primitive_step( - "Provision", - resource=ddh2o, - destination=load_water.output_pin("samples"), - amount=sbol3.Measure(500, tyto.OM.microliter), -) - - -# Template DNA samples are assumed to be in microfuge tubes -# which will be added to a tube rack -template_layout = {} -for coordinate, template in templates.to_dict().items(): - template = doc.find(template) - template_container = labop.ContainerSpec( - template.display_id + "_container", - name="container of " + template.name, - queryString="cont:MicrofugeTube", + ) + load = activity.primitive_step( + "LoadRackOnInstrument", rack=spec_tiprack, coordinates="1" + ) + + # Set up rack for reagents + reagent_rack = labop.ContainerSpec( + "reagent_rack", + name="Tube rack for reagents", + queryString="cont:Opentrons24TubeRackwithEppendorf1.5mLSafe-LockSnapcap", prefixMap=PREFIX_MAP, ) - load_template = activity.primitive_step( - "LoadContainerInRack", - slots=rack.output_pin("slots"), - container=template_container, - coordinates=coordinate, + rack = activity.primitive_step("EmptyRack", specification=reagent_rack) + load_rack = activity.primitive_step( + "LoadRackOnInstrument", rack=reagent_rack, coordinates="2" ) - template_layout[template.name] = load_template.output_pin("samples") - -# Set up PCR machine -pcr_plate = labop.ContainerSpec( - "pcr_plate", - name="PCR plate", - queryString="cont:Biorad96WellPCRPlate", - prefixMap=PREFIX_MAP, -) -load_pcr_plate_on_thermocycler = activity.primitive_step( - "LoadContainerOnInstrument", - specification=pcr_plate, - instrument=OT2Specialization.EQUIPMENT["thermocycler"], - slots="A1:H12", -) - -# Pipette PCR reactions -for target_well, reaction in pcr_plan.items(): - f_primer = reaction["Forward"] - [f_primer_coordinates] = [ - c for c, p in primer_layout.to_dict().items() if doc.find(p).name == f_primer - ] - r_primer = reaction["Reverse"] - [r_primer_coordinates] = [ - c for c, p in primer_layout.to_dict().items() if doc.find(p).name == r_primer - ] - template = template_layout[reaction["Template"]] - target_sample = activity.primitive_step( - "PlateCoordinates", - source=load_pcr_plate_on_thermocycler.output_pin("samples"), - coordinates=target_well, + # Set up primers plate + primer_plate = labop.ContainerSpec( + "primer_plate", + name="primers in 96-well plate", + queryString="cont:Corning96WellPlate360uLFlat", + prefixMap=PREFIX_MAP, ) + load = activity.primitive_step( + "LoadRackOnInstrument", rack=primer_plate, coordinates="3" + ) + primer_plate = activity.primitive_step("EmptyContainer", specification=primer_plate) - # Transfer water - transfer = activity.primitive_step( - "Transfer", - source=load_water.output_pin("samples"), - destination=target_sample.output_pin("samples"), - amount=sbol3.Measure(6, tyto.OM.microliter), + # Set up DNA polymerase + polymerase = labop.ContainerSpec( + "polymerase", + name="DNA Polymerase", + queryString="cont:StockReagent", + prefixMap=PREFIX_MAP, + ) + load_reagents = activity.primitive_step( + "LoadContainerInRack", + slots=rack.output_pin("slots"), + container=polymerase, + coordinates="A1", ) - transfer.name = "Add water" - # Transfer forward primer - f_primer_sample = activity.primitive_step( - "PlateCoordinates", - source=primer_plate.output_pin("samples"), - coordinates=f_primer_coordinates, + # Set up water + load_water = activity.primitive_step( + "LoadContainerInRack", + slots=rack.output_pin("slots"), + container=labop.ContainerSpec( + "water", + name="tube for water", + queryString="cont:MicrofugeTube", + prefixMap=PREFIX_MAP, + ), + coordinates="B1", ) - transfer = activity.primitive_step( - "Transfer", - source=f_primer_sample.output_pin("samples"), - destination=target_sample.output_pin("samples"), - amount=sbol3.Measure(1, tyto.OM.microliter), + provision_water = activity.primitive_step( + "Provision", + resource=ddh2o, + destination=load_water.output_pin("samples"), + amount=sbol3.Measure(500, tyto.OM.microliter), ) - transfer.name = "Add F primer" - # Transfer reverse primer - r_primer_sample = activity.primitive_step( - "PlateCoordinates", - source=primer_plate.output_pin("samples"), - coordinates=r_primer_coordinates, + # Template DNA samples are assumed to be in microfuge tubes + # which will be added to a tube rack + template_layout = {} + for coordinate, template in templates.to_dict().items(): + template = doc.find(template) + template_container = labop.ContainerSpec( + template.display_id + "_container", + name="container of " + template.name, + queryString="cont:MicrofugeTube", + prefixMap=PREFIX_MAP, + ) + load_template = activity.primitive_step( + "LoadContainerInRack", + slots=rack.output_pin("slots"), + container=template_container, + coordinates=coordinate, + ) + template_layout[template.name] = load_template.output_pin("samples") + + # Set up PCR machine + pcr_plate = labop.ContainerSpec( + "pcr_plate", + name="PCR plate", + queryString="cont:Biorad96WellPCRPlate", + prefixMap=PREFIX_MAP, ) - transfer = activity.primitive_step( - "Transfer", - source=r_primer_sample.output_pin("samples"), - destination=target_sample.output_pin("samples"), - amount=sbol3.Measure(1, tyto.OM.microliter), + load_pcr_plate_on_thermocycler = activity.primitive_step( + "LoadContainerOnInstrument", + specification=pcr_plate, + instrument=OT2Specialization.EQUIPMENT["thermocycler"], + slots="A1:H12", ) - transfer.name = "Add R primer" - - # Transfer template - transfer = activity.primitive_step( - "Transfer", - source=template, - destination=target_sample.output_pin("samples"), - amount=sbol3.Measure(1, tyto.OM.microliter), + + # Pipette PCR reactions + for target_well, reaction in pcr_plan.items(): + f_primer = reaction["Forward"] + [f_primer_coordinates] = [ + c + for c, p in primer_layout.to_dict().items() + if doc.find(p).name == f_primer + ] + r_primer = reaction["Reverse"] + [r_primer_coordinates] = [ + c + for c, p in primer_layout.to_dict().items() + if doc.find(p).name == r_primer + ] + template = template_layout[reaction["Template"]] + + target_sample = activity.primitive_step( + "PlateCoordinates", + source=load_pcr_plate_on_thermocycler.output_pin("samples"), + coordinates=target_well, + ) + + # Transfer water + transfer = activity.primitive_step( + "Transfer", + source=load_water.output_pin("samples"), + destination=target_sample.output_pin("samples"), + amount=sbol3.Measure(6, tyto.OM.microliter), + ) + transfer.name = "Add water" + + # Transfer forward primer + f_primer_sample = activity.primitive_step( + "PlateCoordinates", + source=primer_plate.output_pin("samples"), + coordinates=f_primer_coordinates, + ) + transfer = activity.primitive_step( + "Transfer", + source=f_primer_sample.output_pin("samples"), + destination=target_sample.output_pin("samples"), + amount=sbol3.Measure(1, tyto.OM.microliter), + ) + transfer.name = "Add F primer" + + # Transfer reverse primer + r_primer_sample = activity.primitive_step( + "PlateCoordinates", + source=primer_plate.output_pin("samples"), + coordinates=r_primer_coordinates, + ) + transfer = activity.primitive_step( + "Transfer", + source=r_primer_sample.output_pin("samples"), + destination=target_sample.output_pin("samples"), + amount=sbol3.Measure(1, tyto.OM.microliter), + ) + transfer.name = "Add R primer" + + # Transfer template + transfer = activity.primitive_step( + "Transfer", + source=template, + destination=target_sample.output_pin("samples"), + amount=sbol3.Measure(1, tyto.OM.microliter), + ) + transfer.name = "Add template" + + # Transfer polymerase + transfer = activity.primitive_step( + "Transfer", + source=load_reagents.output_pin("samples"), + destination=target_sample.output_pin("samples"), + amount=sbol3.Measure(1, tyto.OM.microliter), + ) + transfer.name = "Add polymerase" + + pcr = activity.primitive_step( + "PCR", + denaturation_temp=sbol3.Measure(98.0, tyto.OM.degree_Celsius), + denaturation_time=sbol3.Measure(10, tyto.OM.second), + annealing_temp=sbol3.Measure(45.0, tyto.OM.degree_Celsius), + annealing_time=sbol3.Measure(5, tyto.OM.second), + extension_temp=sbol3.Measure(65.0, tyto.OM.degree_Celsius), + extension_time=sbol3.Measure(60, tyto.OM.second), + cycles=30, ) - transfer.name = "Add template" - - # Transfer polymerase - transfer = activity.primitive_step( - "Transfer", - source=load_reagents.output_pin("samples"), - destination=target_sample.output_pin("samples"), - amount=sbol3.Measure(1, tyto.OM.microliter), + + return activity + + +if __name__ == "__main__": + harness = labop.execution.harness.ProtocolHarness( + base_dir=os.path.dirname(__file__), + entry_point=create_protocol, + artifacts=[ + labop.execution.harness.ProtocolSpecialization( + specialization=OT2Specialization("ot2_pcr_labop") + ) + ], + libraries=[ + "liquid_handling", + "plate_handling", + "spectrophotometry", + "sample_arrays", + "pcr", + ], + namespace="https://bbn.com/scratch/", + protocol_name="pcr_example", + protocol_long_name="Opentrons PCR Demo", + protocol_version="1.0", + agent="ot2_machine", + execution_flags={"failsafe": False}, + execution_id="test_execution", ) - transfer.name = "Add polymerase" - -pcr = activity.primitive_step( - "PCR", - denaturation_temp=sbol3.Measure(98.0, tyto.OM.degree_Celsius), - denaturation_time=sbol3.Measure(10, tyto.OM.second), - annealing_temp=sbol3.Measure(45.0, tyto.OM.degree_Celsius), - annealing_time=sbol3.Measure(5, tyto.OM.second), - extension_temp=sbol3.Measure(65.0, tyto.OM.degree_Celsius), - extension_time=sbol3.Measure(60, tyto.OM.second), - cycles=30, -) - -filename = "ot2_pcr_labop" -agent = sbol3.Agent("ot2_machine", name="OT2 machine") -ee = ExecutionEngine(specializations=[OT2Specialization(filename)], failsafe=False) -parameter_values = [] -execution = ee.execute(activity, agent, id="test_execution") - -# ee = ExecutionEngine(specializations=[MarkdownSpecialization(filename + '.md')], failsafe=False, sample_format='json') -# parameter_values = [] -# execution = ee.execute(protocol, agent, id="test_execution") + harness.run(verbose=True) diff --git a/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py b/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py index 34baed8d..02f48baf 100644 --- a/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py +++ b/examples/protocols/opentrons/opentrons-toy/opentrons_toy_protocol.py @@ -5,7 +5,6 @@ from sbol3 import Document import labop -from labop.constants import PREFIX_MAP from labop.execution import ProtocolHarness, ProtocolSpecialization from labop.protocol import Protocol from labop.strings import Strings @@ -46,6 +45,8 @@ def create_protocol() -> labop.Protocol: def get_container(protocol: labop.Protocol, container_name: str, container_type: str): + from labop.constants import PREFIX_MAP + query_string = REVERSE_LABWARE_MAP[container_type] plate_spec = labop.ContainerSpec( container_name.replace(" ", "_"), diff --git a/test/test_inputs.py b/test/test_inputs.py index 1f65abf0..b626eb1a 100644 --- a/test/test_inputs.py +++ b/test/test_inputs.py @@ -1,13 +1,10 @@ +import os import unittest import sbol3 -import tyto import labop -import uml from labop.execution.execution_engine import ExecutionEngine -from labop_convert import MarkdownSpecialization -from labop_convert.behavior_specialization import DefaultBehaviorSpecialization PARAMETER_IN = "http://bioprotocols.org/uml#in" PARAMETER_OUT = "http://bioprotocols.org/uml#out" @@ -69,7 +66,10 @@ def container_set_execution(record): container = parameter_value_map["specification"] samples = parameter_value_map["samples"] - ee = ExecutionEngine() + if not os.path.exists("out"): + os.makedirs("out", exist_ok=True) + + ee = ExecutionEngine(out_dir="out") ee.specializations[0]._behavior_func_map[p.identity] = lambda record, ex: None ex = ee.execute( protocol,