initial commit
This commit is contained in:
11
src/submissions/backend/db/models/__init__.py
Normal file
11
src/submissions/backend/db/models/__init__.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
Base = declarative_base()
|
||||
metadata = Base.metadata
|
||||
|
||||
from .controls import Control, ControlType
|
||||
from .kits import KitType, ReagentType, Reagent
|
||||
from .submissions import BasicSubmission, BacterialCulture, Wastewater
|
||||
from .organizations import Organization, Contact
|
||||
from .samples import Sample
|
||||
36
src/submissions/backend/db/models/controls.py
Normal file
36
src/submissions/backend/db/models/controls.py
Normal file
@@ -0,0 +1,36 @@
|
||||
from . import Base
|
||||
from sqlalchemy import Column, String, TIMESTAMP, text, JSON, INTEGER, ForeignKey, UniqueConstraint
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
class ControlType(Base):
|
||||
"""
|
||||
Base class of a control archetype.
|
||||
"""
|
||||
__tablename__ = '_control_types'
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
name = Column(String(255), unique=True) #: controltype name (e.g. MCS)
|
||||
targets = Column(JSON) #: organisms checked for
|
||||
# instances_id = Column(INTEGER, ForeignKey("_control_samples.id", ondelete="SET NULL", name="fk_ctype_instances_id"))
|
||||
instances = relationship("Control", back_populates="controltype") #: control samples created of this type.
|
||||
# UniqueConstraint('name', name='uq_controltype_name')
|
||||
|
||||
|
||||
class Control(Base):
|
||||
"""
|
||||
Base class of a control sample.
|
||||
"""
|
||||
|
||||
__tablename__ = '_control_samples'
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
parent_id = Column(String, ForeignKey("_control_types.id", name="fk_control_parent_id")) #: primary key of control type
|
||||
controltype = relationship("ControlType", back_populates="instances", foreign_keys=[parent_id]) #: reference to parent control type
|
||||
name = Column(String(255), unique=True) #: Sample ID
|
||||
submitted_date = Column(TIMESTAMP) #: Date submitted to Robotics
|
||||
contains = Column(JSON) #: unstructured hashes in contains.tsv for each organism
|
||||
matches = Column(JSON) #: unstructured hashes in matches.tsv for each organism
|
||||
kraken = Column(JSON) #: unstructured output from kraken_report
|
||||
# UniqueConstraint('name', name='uq_control_name')
|
||||
submissions = relationship("BacterialCulture", back_populates="control")
|
||||
|
||||
68
src/submissions/backend/db/models/kits.py
Normal file
68
src/submissions/backend/db/models/kits.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from . import Base
|
||||
from sqlalchemy import Column, String, TIMESTAMP, JSON, INTEGER, ForeignKey, Interval, Table, FLOAT
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
|
||||
reagenttypes_kittypes = Table("_reagentstypes_kittypes", Base.metadata, Column("reagent_types_id", INTEGER, ForeignKey("_reagent_types.id")), Column("kits_id", INTEGER, ForeignKey("_kits.id")))
|
||||
|
||||
|
||||
class KitType(Base):
|
||||
|
||||
__tablename__ = "_kits"
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
name = Column(String(64), unique=True)
|
||||
submissions = relationship("BasicSubmission", back_populates="extraction_kit")
|
||||
used_for = Column(JSON)
|
||||
cost_per_run = Column(FLOAT(2))
|
||||
reagent_types = relationship("ReagentType", back_populates="kits", uselist=True, secondary=reagenttypes_kittypes)
|
||||
reagent_types_id = Column(INTEGER, ForeignKey("_reagent_types.id", ondelete='SET NULL', use_alter=True, name="fk_KT_reagentstype_id"))
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class ReagentType(Base):
|
||||
|
||||
__tablename__ = "_reagent_types"
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
name = Column(String(64))
|
||||
kit_id = Column(INTEGER, ForeignKey("_kits.id", ondelete="SET NULL", use_alter=True, name="fk_RT_kits_id"))
|
||||
kits = relationship("KitType", back_populates="reagent_types", uselist=True, foreign_keys=[kit_id])
|
||||
instances = relationship("Reagent", back_populates="type")
|
||||
# instances_id = Column(INTEGER, ForeignKey("_reagents.id", ondelete='SET NULL'))
|
||||
eol_ext = Column(Interval())
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Reagent(Base):
|
||||
|
||||
__tablename__ = "_reagents"
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
type = relationship("ReagentType", back_populates="instances")
|
||||
type_id = Column(INTEGER, ForeignKey("_reagent_types.id", ondelete='SET NULL', name="fk_reagent_type_id"))
|
||||
name = Column(String(64))
|
||||
lot = Column(String(64))
|
||||
expiry = Column(TIMESTAMP)
|
||||
submissions = relationship("BasicSubmission", back_populates="reagents", uselist=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.lot
|
||||
|
||||
def to_sub_dict(self):
|
||||
try:
|
||||
type = self.type.name.replace("_", " ").title()
|
||||
except AttributeError:
|
||||
type = "Unknown"
|
||||
return {
|
||||
"type": type,
|
||||
"lot": self.lot,
|
||||
"expiry": self.expiry.strftime("%Y-%m-%d")
|
||||
}
|
||||
|
||||
|
||||
|
||||
34
src/submissions/backend/db/models/organizations.py
Normal file
34
src/submissions/backend/db/models/organizations.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from . import Base
|
||||
from sqlalchemy import Column, String, TIMESTAMP, JSON, Float, INTEGER, ForeignKey, UniqueConstraint, Table
|
||||
from sqlalchemy.orm import relationship, validates
|
||||
|
||||
|
||||
orgs_contacts = Table("_orgs_contacts", Base.metadata, Column("org_id", INTEGER, ForeignKey("_organizations.id")), Column("contact_id", INTEGER, ForeignKey("_contacts.id")))
|
||||
|
||||
|
||||
class Organization(Base):
|
||||
|
||||
__tablename__ = "_organizations"
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
name = Column(String(64))
|
||||
submissions = relationship("BasicSubmission", back_populates="submitting_lab")
|
||||
cost_centre = Column(String())
|
||||
contacts = relationship("Contact", back_populates="organization", secondary=orgs_contacts)
|
||||
contact_ids = Column(INTEGER, ForeignKey("_contacts.id", ondelete="SET NULL", name="fk_org_contact_id"))
|
||||
|
||||
def __str__(self):
|
||||
return self.name.replace("_", " ").title()
|
||||
|
||||
|
||||
class Contact(Base):
|
||||
|
||||
__tablename__ = "_contacts"
|
||||
|
||||
id = id = Column(INTEGER, primary_key=True) #: primary key
|
||||
name = Column(String(64))
|
||||
email = Column(String(64))
|
||||
phone = Column(String(32))
|
||||
organization = relationship("Organization", back_populates="contacts", uselist=True)
|
||||
# organization_id = Column(INTEGER, ForeignKey("_organizations.id"))
|
||||
|
||||
27
src/submissions/backend/db/models/samples.py
Normal file
27
src/submissions/backend/db/models/samples.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from . import Base
|
||||
from sqlalchemy import Column, String, TIMESTAMP, text, JSON, INTEGER, ForeignKey, FLOAT, BOOLEAN
|
||||
from sqlalchemy.orm import relationship, relationships
|
||||
|
||||
|
||||
class Sample(Base):
|
||||
|
||||
__tablename__ = "_ww_samples"
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
ww_processing_num = Column(String(64))
|
||||
ww_sample_full_id = Column(String(64))
|
||||
rsl_number = Column(String(64))
|
||||
rsl_plate = relationship("Wastewater", back_populates="samples")
|
||||
collection_date = Column(TIMESTAMP) #: Date submission received
|
||||
testing_type = Column(String(64))
|
||||
site_status = Column(String(64))
|
||||
notes = Column(String(2000))
|
||||
ct_n1 = Column(FLOAT(2))
|
||||
ct_n2 = Column(FLOAT(2))
|
||||
seq_submitted = Column(BOOLEAN())
|
||||
ww_seq_run_id = Column(String(64))
|
||||
sample_type = Column(String(8))
|
||||
|
||||
|
||||
|
||||
|
||||
103
src/submissions/backend/db/models/submissions.py
Normal file
103
src/submissions/backend/db/models/submissions.py
Normal file
@@ -0,0 +1,103 @@
|
||||
from . import Base
|
||||
from sqlalchemy import Column, String, TIMESTAMP, text, JSON, INTEGER, ForeignKey, UniqueConstraint, Table
|
||||
from sqlalchemy.orm import relationship, relationships
|
||||
from datetime import datetime as dt
|
||||
|
||||
reagents_submissions = Table("_reagents_submissions", Base.metadata, Column("reagent_id", INTEGER, ForeignKey("_reagents.id")), Column("submission_id", INTEGER, ForeignKey("_submissions.id")))
|
||||
|
||||
class BasicSubmission(Base):
|
||||
|
||||
# TODO: Figure out if I want seperate tables for different sample types.
|
||||
__tablename__ = "_submissions"
|
||||
|
||||
id = Column(INTEGER, primary_key=True) #: primary key
|
||||
rsl_plate_num = Column(String(32), unique=True) #: RSL name (e.g. RSL-22-0012)
|
||||
submitter_plate_num = Column(String(127), unique=True) #: The number given to the submission by the submitting lab
|
||||
submitted_date = Column(TIMESTAMP) #: Date submission received
|
||||
submitting_lab = relationship("Organization", back_populates="submissions") #: client
|
||||
submitting_lab_id = Column(INTEGER, ForeignKey("_organizations.id", ondelete="SET NULL"))
|
||||
sample_count = Column(INTEGER) #: Number of samples in the submission
|
||||
extraction_kit = relationship("KitType", back_populates="submissions") #: The extraction kit used
|
||||
extraction_kit_id = Column(INTEGER, ForeignKey("_kits.id", ondelete="SET NULL"))
|
||||
submission_type = Column(String(32))
|
||||
technician = Column(String(64))
|
||||
# Move this into custom types?
|
||||
reagents = relationship("Reagent", back_populates="submissions", secondary=reagents_submissions)
|
||||
reagents_id = Column(String, ForeignKey("_reagents.id", ondelete="SET NULL", name="fk_BS_reagents_id"))
|
||||
|
||||
__mapper_args__ = {
|
||||
"polymorphic_identity": "basic_submission",
|
||||
"polymorphic_on": submission_type,
|
||||
"with_polymorphic": "*",
|
||||
}
|
||||
|
||||
def to_dict(self):
|
||||
print(self.submitting_lab)
|
||||
try:
|
||||
sub_lab = self.submitting_lab.name
|
||||
except AttributeError:
|
||||
sub_lab = None
|
||||
try:
|
||||
sub_lab = sub_lab.replace("_", " ").title()
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
ext_kit = self.extraction_kit.name
|
||||
except AttributeError:
|
||||
ext_kit = None
|
||||
output = {
|
||||
"id": self.id,
|
||||
"Plate Number": self.rsl_plate_num,
|
||||
"Submission Type": self.submission_type.replace("_", " ").title(),
|
||||
"Submitter Plate Number": self.submitter_plate_num,
|
||||
"Submitted Date": self.submitted_date.strftime("%Y-%m-%d"),
|
||||
"Submitting Lab": sub_lab,
|
||||
"Sample Count": self.sample_count,
|
||||
"Extraction Kit": ext_kit,
|
||||
"Technician": self.technician,
|
||||
}
|
||||
return output
|
||||
|
||||
|
||||
def report_dict(self):
|
||||
try:
|
||||
sub_lab = self.submitting_lab.name
|
||||
except AttributeError:
|
||||
sub_lab = None
|
||||
try:
|
||||
sub_lab = sub_lab.replace("_", " ").title()
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
ext_kit = self.extraction_kit.name
|
||||
except AttributeError:
|
||||
ext_kit = None
|
||||
try:
|
||||
cost = self.extraction_kit.cost_per_run
|
||||
except AttributeError:
|
||||
cost = None
|
||||
output = {
|
||||
"id": self.id,
|
||||
"Plate Number": self.rsl_plate_num,
|
||||
"Submission Type": self.submission_type.replace("_", " ").title(),
|
||||
"Submitter Plate Number": self.submitter_plate_num,
|
||||
"Submitted Date": self.submitted_date.strftime("%Y-%m-%d"),
|
||||
"Submitting Lab": sub_lab,
|
||||
"Sample Count": self.sample_count,
|
||||
"Extraction Kit": ext_kit,
|
||||
"Cost": cost
|
||||
}
|
||||
return output
|
||||
|
||||
# Below are the custom submission
|
||||
|
||||
class BacterialCulture(BasicSubmission):
|
||||
control = relationship("Control", back_populates="submissions") #: A control sample added to submission
|
||||
control_id = Column(INTEGER, ForeignKey("_control_samples.id", ondelete="SET NULL", name="fk_BC_control_id"))
|
||||
__mapper_args__ = {"polymorphic_identity": "bacterial_culture", "polymorphic_load": "inline"}
|
||||
|
||||
|
||||
class Wastewater(BasicSubmission):
|
||||
samples = relationship("Sample", back_populates="rsl_plate")
|
||||
sample_id = Column(String, ForeignKey("_ww_samples.id", ondelete="SET NULL", name="fk_WW_sample_id"))
|
||||
__mapper_args__ = {"polymorphic_identity": "wastewater", "polymorphic_load": "inline"}
|
||||
Reference in New Issue
Block a user