Skip to content

Commit

Permalink
Feature: Separate pyplate.py into Multiple Files (Merge pull request #32
Browse files Browse the repository at this point in the history
 from ekwan/feature_separate_files)

Created separate files for the various classes of PyPlate. Some which were closely paired (e.g. Recipe and RecipeStep) were kept in the same file, whereas most others were given their own files.
  • Loading branch information
jlw387 authored Aug 26, 2024
2 parents ba8e468 + 000156c commit 327942d
Show file tree
Hide file tree
Showing 25 changed files with 3,061 additions and 2,981 deletions.
2 changes: 1 addition & 1 deletion examples/Example.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from operator import itemgetter

from pyplate.pyplate import Substance, Container, Plate, Recipe
from pyplate import Substance, Container, Plate, Recipe

# testing #

Expand Down
2 changes: 1 addition & 1 deletion examples/Test_Example.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from pyplate.pyplate import Substance, Container, Recipe, Plate
from pyplate import Substance, Container, Recipe, Plate


water = Substance.liquid('H2O', mol_weight=18.0153, density=1)
Expand Down
88 changes: 39 additions & 49 deletions pyplate/__init__.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,39 @@
from pathlib import Path
import os
import yaml


class Config:
def __init__(self):
file_path = None
for path in [Path(os.environ.get('PYPLATE_CONFIG', '')), Path.home(), Path(os.path.dirname(__file__))]:
path = path.joinpath('pyplate.yaml')
if path.is_file():
file_path = path
break

if file_path is None:
raise RuntimeError("pyplate.yaml not found.")

try:
with file_path.open('r') as config_file:
yaml_config = yaml.safe_load(config_file)
except yaml.YAMLError as exc:
raise RuntimeError("Config file could not be read.") from exc

self.internal_precision = yaml_config['internal_precision']
self.moles_storage_unit = yaml_config['moles_storage_unit']
assert self.moles_storage_unit[-3:] == 'mol'
self.moles_display_unit = yaml_config['moles_display_unit']
assert self.moles_display_unit[-3:] == 'mol'
self.volume_storage_unit = yaml_config['volume_storage_unit']
assert self.volume_storage_unit[-1] == 'L'
self.volume_display_unit = yaml_config['volume_display_unit']
assert self.volume_display_unit[-1] == 'L'

self.concentration_display_unit = yaml_config['concentration_display_unit']
# we can't use Unit to do a full check of the unit, so we just do a cursory check
assert ('/' in self.concentration_display_unit or self.concentration_display_unit[-1] == 'm' or
self.concentration_display_unit[-1] == 'M')
self.default_solid_density = float(yaml_config['default_solid_density'])
self.default_enzyme_density = float(yaml_config['default_enzyme_density'])
self.default_weight_volume_units = yaml_config['default_weight_volume_units']

self.default_colormap = yaml_config['default_colormap']
self.default_diverging_colormap = yaml_config['default_diverging_colormap']
self.precisions = yaml_config['precisions']


# This has to be imported after Config is defined, otherwise there will be a circular import.
from .pyplate import Substance, Container, Plate, Recipe, Unit, RecipeStep # noqa: E402
__all__ = ['Substance', 'Container', 'Plate', 'Recipe', 'Unit', 'Config', 'RecipeStep']
"""
pyplate: a tool for designing chemistry experiments in plate format
Substance: An abstract chemical or biological entity (e.g., reagent, solvent, etc.).
Immutable.
Container: Stores specified quantities of Substances in a vessel with a given maximum volume. Immutable.
Plate: A spatially ordered collection of Containers, like a 96 well plate.
The spatial arrangement must be rectangular. Immutable.
Recipe: A list of instructions for transforming one set of containers into another.
Storage format is defined in pyplate.yaml for volumes and moles.
Example:
# 1e-6 means we will store volumes as microliters
volume_storage: 'uL'
# 1e-6 means we will store moles as micromoles.
moles_storage: 'umol'
All classes in this package are friends and use private methods of other classes freely.
All internal computations are rounded to config.internal_precision to maintain sanity.
Rounding errors quickly compound.
All values returned to the user are rounded to config.precisions for ease of use.
"""

# This is necessary to instantiate the config instance; the unit tests fail without it
from pyplate.config import config, Config

from pyplate.container import Container
from pyplate.plate import Plate
from pyplate.recipe import Recipe, RecipeStep
from pyplate.substance import Substance
from pyplate.unit import Unit
# noqa: E402
__all__ = ['Substance', 'Container', 'Plate', 'Recipe', 'Unit', 'RecipeStep']
45 changes: 45 additions & 0 deletions pyplate/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from pathlib import Path
import os
import yaml

class Config:
def __init__(self):
file_path = None
for path in [Path(os.environ.get('PYPLATE_CONFIG', '')), Path.home(), Path(os.path.dirname(__file__))]:
path = path.joinpath('pyplate.yaml')
if path.is_file():
file_path = path
break

if file_path is None:
raise RuntimeError("pyplate.yaml not found.")

try:
with file_path.open('r') as config_file:
yaml_config = yaml.safe_load(config_file)
except yaml.YAMLError as exc:
raise RuntimeError("Config file could not be read.") from exc

self.internal_precision = yaml_config['internal_precision']
self.moles_storage_unit = yaml_config['moles_storage_unit']
assert self.moles_storage_unit[-3:] == 'mol'
self.moles_display_unit = yaml_config['moles_display_unit']
assert self.moles_display_unit[-3:] == 'mol'
self.volume_storage_unit = yaml_config['volume_storage_unit']
assert self.volume_storage_unit[-1] == 'L'
self.volume_display_unit = yaml_config['volume_display_unit']
assert self.volume_display_unit[-1] == 'L'

self.concentration_display_unit = yaml_config['concentration_display_unit']
# we can't use Unit to do a full check of the unit, so we just do a cursory check
assert ('/' in self.concentration_display_unit or self.concentration_display_unit[-1] == 'm' or
self.concentration_display_unit[-1] == 'M')
self.default_solid_density = float(yaml_config['default_solid_density'])
self.default_enzyme_density = float(yaml_config['default_enzyme_density'])
self.default_weight_volume_units = yaml_config['default_weight_volume_units']

self.default_colormap = yaml_config['default_colormap']
self.default_diverging_colormap = yaml_config['default_diverging_colormap']
self.precisions = yaml_config['precisions']

config = Config()
Loading

0 comments on commit 327942d

Please sign in to comment.