new parsers/DB objects, pre code cleanup

This commit is contained in:
Landon Wark
2023-09-06 08:41:08 -05:00
parent bc7a3b8f5f
commit e0b80f6c7a
12 changed files with 263 additions and 137 deletions

View File

@@ -2,7 +2,7 @@
All kit and reagent related models
'''
from . import Base
from sqlalchemy import Column, String, TIMESTAMP, JSON, INTEGER, ForeignKey, Interval, Table, FLOAT, CheckConstraint
from sqlalchemy import Column, String, TIMESTAMP, JSON, INTEGER, ForeignKey, Interval, Table, FLOAT
from sqlalchemy.orm import relationship, validates
from sqlalchemy.ext.associationproxy import association_proxy
@@ -22,6 +22,8 @@ logger = logging.getLogger(f'submissions.{__name__}')
# Column("required", INTEGER)
# )
reagenttypes_reagents = Table("_reagenttypes_reagents", Base.metadata, Column("reagent_id", INTEGER, ForeignKey("_reagents.id")), Column("reagenttype_id", INTEGER, ForeignKey("_reagent_types.id")))
class KitType(Base):
"""
@@ -47,7 +49,7 @@ class KitType(Base):
# association proxy of "user_keyword_associations" collection
# to "keyword" attribute
reagent_types = association_proxy("kit_reagenttype_associations", "reagenttype")
reagent_types = association_proxy("kit_reagenttype_associations", "reagent_type")
kit_submissiontype_associations = relationship(
@@ -139,7 +141,7 @@ class ReagentType(Base):
name = Column(String(64)) #: name of reagent type
# kit_id = Column(INTEGER, ForeignKey("_kits.id", ondelete="SET NULL", use_alter=True, name="fk_RT_kits_id")) #: id of joined kit type
# kits = relationship("KitType", back_populates="reagent_types", uselist=True, foreign_keys=[kit_id]) #: kits this reagent is used in
instances = relationship("Reagent", back_populates="type") #: concrete instances of this reagent type
instances = relationship("Reagent", back_populates="type", secondary=reagenttypes_reagents) #: concrete instances of this reagent type
eol_ext = Column(Interval()) #: extension of life interval
# required = Column(INTEGER, server_default="1") #: sqlite boolean to determine if reagent type is essential for the kit
last_used = Column(String(32)) #: last used lot number of this type of reagent
@@ -169,7 +171,7 @@ class Reagent(Base):
__tablename__ = "_reagents"
id = Column(INTEGER, primary_key=True) #: primary key
type = relationship("ReagentType", back_populates="instances") #: joined parent reagent type
type = relationship("ReagentType", back_populates="instances", secondary=reagenttypes_reagents) #: joined parent reagent type
type_id = Column(INTEGER, ForeignKey("_reagent_types.id", ondelete='SET NULL', name="fk_reagent_type_id")) #: id of parent reagent type
name = Column(String(64)) #: reagent name
lot = Column(String(64)) #: lot number of reagent
@@ -192,19 +194,26 @@ class Reagent(Base):
"""
return str(self.lot)
def to_sub_dict(self) -> dict:
def to_sub_dict(self, extraction_kit:KitType=None) -> dict:
"""
dictionary containing values necessary for gui
Returns:
dict: gui friendly dictionary
"""
if extraction_kit != None:
try:
reagent_role = list(set(self.type).intersection(extraction_kit.reagent_types))[0]
except:
reagent_role = self.type[0]
else:
reagent_role = self.type[0]
try:
type = self.type.name.replace("_", " ").title()
rtype = reagent_role.name.replace("_", " ").title()
except AttributeError:
type = "Unknown"
rtype = "Unknown"
try:
place_holder = self.expiry + self.type.eol_ext
place_holder = self.expiry + reagent_role.eol_ext
# logger.debug(f"EOL_ext for {self.lot} -- {self.expiry} + {self.type.eol_ext} = {place_holder}")
except TypeError as e:
place_holder = date.today()
@@ -213,14 +222,14 @@ class Reagent(Base):
place_holder = date.today()
logger.debug(f"We got an attribute error setting {self.lot} expiry: {e}. Setting to today for testing")
return {
"type": type,
"type": rtype,
"lot": self.lot,
"expiry": place_holder.strftime("%Y-%m-%d")
}
def to_reagent_dict(self) -> dict:
return {
"type": self.type.name,
"type": type,
"lot": self.lot,
"expiry": self.expiry.strftime("%Y-%m-%d")
}
@@ -279,4 +288,7 @@ class SubmissionTypeKitTypeAssociation(Base):
self.submission_type = submission_type
self.mutable_cost_column = 0.00
self.mutable_cost_sample = 0.00
self.constant_cost = 0.00
self.constant_cost = 0.00
def __repr__(self) -> str:
return f"<SubmissionTypeKitTypeAssociation({self.submission_type.name})"

View File

@@ -3,7 +3,7 @@ Models for the main submission types.
'''
import math
from . import Base
from sqlalchemy import Column, String, TIMESTAMP, INTEGER, ForeignKey, Table, JSON, FLOAT, BOOLEAN
from sqlalchemy import Column, String, TIMESTAMP, INTEGER, ForeignKey, Table, JSON, FLOAT
from sqlalchemy.orm import relationship, validates
import logging
import json
@@ -106,7 +106,7 @@ class BasicSubmission(Base):
ext_info = None
logger.debug(f"Json error in {self.rsl_plate_num}: {e}")
try:
reagents = [item.to_sub_dict() for item in self.reagents]
reagents = [item.to_sub_dict(extraction_kit=self.extraction_kit) for item in self.reagents]
except Exception as e:
logger.error(f"We got an error retrieving reagents: {e}")
reagents = None
@@ -252,6 +252,8 @@ class Wastewater(BasicSubmission):
"""
# samples = relationship("WWSample", back_populates="rsl_plate", uselist=True)
pcr_info = Column(JSON)
ext_technician = Column(String(64))
pcr_technician = Column(String(64))
# ww_sample_id = Column(String, ForeignKey("_ww_samples.id", ondelete="SET NULL", name="fk_WW_sample_id"))
__mapper_args__ = {"polymorphic_identity": "Wastewater", "polymorphic_load": "inline"}
@@ -267,6 +269,7 @@ class Wastewater(BasicSubmission):
output['pcr_info'] = json.loads(self.pcr_info)
except TypeError as e:
pass
output['Technician'] = f"Enr: {self.technician}, Ext: {self.ext_technician}, PCR: {self.pcr_technician}"
return output
class WastewaterArtic(BasicSubmission):
@@ -460,10 +463,10 @@ class WastewaterSample(BasicSample):
except AttributeError as e:
check = False
if check:
logger.debug(f"Using well info in name.")
# logger.debug(f"Using well info in name.")
sample['name'] = f"{self.submitter_id}\n\t- ct N1: {'{:.2f}'.format(self.assoc.ct_n1)} ({self.assoc.n1_status})\n\t- ct N2: {'{:.2f}'.format(self.assoc.ct_n2)} ({self.assoc.n2_status})"
else:
logger.error(f"Couldn't get the pcr info")
# else:
# logger.error(f"Couldn't get the pcr info")
return sample
def to_hitpick(self, submission_rsl:str) -> dict|None:
@@ -511,7 +514,7 @@ class BacterialCultureSample(BasicSample):
# rsl_plate_id = Column(INTEGER, ForeignKey("_submissions.id", ondelete="SET NULL", name="fk_BCS_sample_id")) #: id of parent plate
# rsl_plate = relationship("BacterialCulture", back_populates="samples") #: relationship to parent plate
__mapper_args__ = {"polymorphic_identity": "bacterial_culture_sample", "polymorphic_load": "inline"}
__mapper_args__ = {"polymorphic_identity": "Bacterial Culture Sample", "polymorphic_load": "inline"}
# def to_string(self) -> str:
# """
@@ -543,10 +546,10 @@ class SubmissionSampleAssociation(Base):
DOC: https://docs.sqlalchemy.org/en/14/orm/extensions/associationproxy.html
"""
__tablename__ = "_submission_sample"
sample_id = Column(INTEGER, ForeignKey("_samples.id"), primary_key=True)
sample_id = Column(INTEGER, ForeignKey("_samples.id"), nullable=False)
submission_id = Column(INTEGER, ForeignKey("_submissions.id"), primary_key=True)
row = Column(INTEGER)
column = Column(INTEGER)
row = Column(INTEGER, primary_key=True)
column = Column(INTEGER, primary_key=True)
submission = relationship(BasicSubmission, back_populates="submission_sample_associations")
@@ -569,6 +572,9 @@ class SubmissionSampleAssociation(Base):
self.row = row
self.column = column
def __repr__(self) -> str:
return f"<SubmissionSampleAssociation({self.submission.rsl_plate_num} & {self.sample.submitter_id})"
class WastewaterAssociation(SubmissionSampleAssociation):
ct_n1 = Column(FLOAT(2)) #: AKA ct for N1