Split Concentration controls on the chart so they are individually selectable.
This commit is contained in:
@@ -80,26 +80,25 @@ class RSLNamer(object):
|
||||
submission_type = cls.retrieve_submission_type(filename=filepath.stem.__str__())
|
||||
return submission_type
|
||||
|
||||
def st_from_str(filename: str) -> str:
|
||||
if filename.startswith("tmp"):
|
||||
def st_from_str(file_name: str) -> str:
|
||||
if file_name.startswith("tmp"):
|
||||
return "Bacterial Culture"
|
||||
regex = BasicSubmission.regex
|
||||
m = regex.search(filename)
|
||||
m = regex.search(file_name)
|
||||
try:
|
||||
submission_type = m.lastgroup
|
||||
sub_type = m.lastgroup
|
||||
except AttributeError as e:
|
||||
submission_type = None
|
||||
sub_type = None
|
||||
logger.critical(f"No submission type found or submission type found!: {e}")
|
||||
return submission_type
|
||||
return sub_type
|
||||
|
||||
match filename:
|
||||
case Path():
|
||||
submission_type = st_from_path(filepath=filename)
|
||||
case str():
|
||||
submission_type = st_from_str(filename=filename)
|
||||
submission_type = st_from_str(file_name=filename)
|
||||
case _:
|
||||
raise TypeError(f"Unsupported filename type: {type(filename)}.")
|
||||
submission_type = None
|
||||
try:
|
||||
check = submission_type is None
|
||||
except UnboundLocalError:
|
||||
@@ -137,7 +136,7 @@ class RSLNamer(object):
|
||||
if m is not None:
|
||||
try:
|
||||
parsed_name = m.group().upper().strip(".")
|
||||
except:
|
||||
except AttributeError:
|
||||
parsed_name = None
|
||||
else:
|
||||
parsed_name = None
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
Collection of pydantic objects to be used in the Gui system.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
import logging
|
||||
from pydantic import BaseModel, field_validator, Field
|
||||
@@ -10,6 +14,7 @@ logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
|
||||
class BaseOmni(BaseModel):
|
||||
|
||||
instance_object: Any | None = Field(default=None)
|
||||
|
||||
def __repr__(self):
|
||||
@@ -23,23 +28,23 @@ class BaseOmni(BaseModel):
|
||||
return cls.class_object.aliases
|
||||
|
||||
def check_all_attributes(self, attributes: dict) -> bool:
|
||||
logger.debug(f"Incoming attributes: {attributes}")
|
||||
# logger.debug(f"Incoming attributes: {attributes}")
|
||||
attributes = {k : v for k, v in attributes.items() if k in self.list_searchables.keys()}
|
||||
for key, value in attributes.items():
|
||||
try:
|
||||
logger.debug(f"Check if {value.__class__} is subclass of {BaseOmni}")
|
||||
# logger.debug(f"Check if {value.__class__} is subclass of {BaseOmni}")
|
||||
check = issubclass(value.__class__, BaseOmni)
|
||||
except TypeError as e:
|
||||
logger.error(f"Couldn't check if {value.__class__} is subclass of {BaseOmni} due to {e}")
|
||||
check = False
|
||||
if check:
|
||||
logger.debug(f"Checking for subclass name.")
|
||||
# logger.debug(f"Checking for subclass name.")
|
||||
value = value.name
|
||||
self_value = self.list_searchables[key]
|
||||
if value != self_value:
|
||||
logger.debug(f"Value {key} is False, these are not the same object.")
|
||||
# logger.debug(f"Value {key} is False, these are not the same object.")
|
||||
return False
|
||||
logger.debug("Everything checks out, these are the same object.")
|
||||
# logger.debug("Everything checks out, these are the same object.")
|
||||
return True
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
@@ -51,24 +56,24 @@ class BaseOmni(BaseModel):
|
||||
new_key = class_value.impl.key
|
||||
except AttributeError:
|
||||
new_key = None
|
||||
logger.debug(f"Class value before new key: {class_value.property}")
|
||||
# logger.debug(f"Class value before new key: {class_value.property}")
|
||||
if new_key and new_key != key:
|
||||
class_value = getattr(self.class_object, new_key)
|
||||
logger.debug(f"Class value after new key: {class_value.property}")
|
||||
# logger.debug(f"Class value after new key: {class_value.property}")
|
||||
if isinstance(class_value, InstrumentedAttribute):
|
||||
logger.debug(f"{key} is an InstrumentedAttribute with class_value.property: {class_value.property}.")
|
||||
# logger.debug(f"{key} is an InstrumentedAttribute with class_value.property: {class_value.property}.")
|
||||
match class_value.property:
|
||||
case ColumnProperty():
|
||||
logger.debug(f"Setting ColumnProperty to {value}")
|
||||
# logger.debug(f"Setting ColumnProperty to {value}")
|
||||
return super().__setattr__(key, value)
|
||||
case _RelationshipDeclared():
|
||||
logger.debug(f" {self.__class__.__name__} Setting _RelationshipDeclared for {key} to {value}")
|
||||
# logger.debug(f" {self.__class__.__name__} Setting _RelationshipDeclared for {key} to {value}")
|
||||
if class_value.property.uselist:
|
||||
logger.debug(f"Setting {key} with uselist")
|
||||
# logger.debug(f"Setting {key} with uselist")
|
||||
existing = self.__getattribute__(key)
|
||||
if existing is not None:
|
||||
# NOTE: Getting some really weird duplicates for OmniSubmissionTypeKitTypeAssociation here.
|
||||
logger.debug(f"Existing: {existing}, incoming: {value}")
|
||||
# logger.debug(f"Existing: {existing}, incoming: {value}")
|
||||
if isinstance(value, list):
|
||||
if value != existing:
|
||||
value = existing + value
|
||||
@@ -82,7 +87,7 @@ class BaseOmni(BaseModel):
|
||||
if issubclass(value.__class__, self.__class__):
|
||||
value = value.to_sql()
|
||||
value = [value]
|
||||
logger.debug(f"Final value for {key}: {value}")
|
||||
# logger.debug(f"Final value for {key}: {value}")
|
||||
return super().__setattr__(key, value)
|
||||
else:
|
||||
if isinstance(value, list):
|
||||
@@ -98,6 +103,7 @@ class BaseOmni(BaseModel):
|
||||
|
||||
|
||||
class OmniSubmissionType(BaseOmni):
|
||||
|
||||
class_object: ClassVar[Any] = SubmissionType
|
||||
|
||||
name: str = Field(default="", description="property")
|
||||
@@ -161,6 +167,7 @@ class OmniSubmissionType(BaseOmni):
|
||||
|
||||
|
||||
class OmniReagentRole(BaseOmni):
|
||||
|
||||
class_object: ClassVar[Any] = ReagentRole
|
||||
|
||||
name: str = Field(default="", description="property")
|
||||
@@ -197,6 +204,7 @@ class OmniReagentRole(BaseOmni):
|
||||
|
||||
|
||||
class OmniSubmissionTypeKitTypeAssociation(BaseOmni):
|
||||
|
||||
class_object: ClassVar[Any] = SubmissionTypeKitTypeAssociation
|
||||
|
||||
submissiontype: str | OmniSubmissionType = Field(default="", description="relationship", title="SubmissionType")
|
||||
@@ -262,7 +270,7 @@ class OmniSubmissionTypeKitTypeAssociation(BaseOmni):
|
||||
)
|
||||
|
||||
def to_sql(self):
|
||||
logger.debug(f"Self kittype: {self.submissiontype}")
|
||||
# logger.debug(f"Self kittype: {self.submissiontype}")
|
||||
if issubclass(self.submissiontype.__class__, BaseOmni):
|
||||
submissiontype = SubmissionType.query(name=self.submissiontype.name)
|
||||
else:
|
||||
@@ -272,7 +280,7 @@ class OmniSubmissionTypeKitTypeAssociation(BaseOmni):
|
||||
else:
|
||||
kittype = KitType.query(name=self.kittype)
|
||||
# logger.debug(f"Self kittype: {self.kittype}")
|
||||
logger.debug(f"Query or create with {kittype}, {submissiontype}")
|
||||
# logger.debug(f"Query or create with {kittype}, {submissiontype}")
|
||||
instance, is_new = self.class_object.query_or_create(kittype=kittype, submissiontype=submissiontype)
|
||||
instance.mutable_cost_column = self.mutable_cost_column
|
||||
instance.mutable_cost_sample = self.mutable_cost_sample
|
||||
@@ -293,6 +301,7 @@ class OmniSubmissionTypeKitTypeAssociation(BaseOmni):
|
||||
|
||||
|
||||
class OmniKitTypeReagentRoleAssociation(BaseOmni):
|
||||
|
||||
class_object: ClassVar[Any] = KitTypeReagentRoleAssociation
|
||||
|
||||
reagent_role: str | OmniReagentRole = Field(default="", description="relationship", title="ReagentRole")
|
||||
@@ -363,7 +372,7 @@ class OmniKitTypeReagentRoleAssociation(BaseOmni):
|
||||
kittype=kittype,
|
||||
submissiontype=submissiontype
|
||||
)
|
||||
logger.debug(f"KitTypeReagentRoleAssociation coming out of query_or_create: {instance.__dict__}\nnew: {new}")
|
||||
# logger.debug(f"KitTypeReagentRoleAssociation coming out of query_or_create: {instance.__dict__}\nnew: {new}")
|
||||
if new:
|
||||
logger.warning(f"This is a new instance: {instance.__dict__}")
|
||||
try:
|
||||
@@ -371,10 +380,10 @@ class OmniKitTypeReagentRoleAssociation(BaseOmni):
|
||||
except AttributeError:
|
||||
reagent_role = ReagentRole.query(name=self.reagent_role)
|
||||
instance.reagent_role = reagent_role
|
||||
logger.debug(f"KTRRAssoc uses: {self.uses}")
|
||||
# logger.debug(f"KTRRAssoc uses: {self.uses}")
|
||||
instance.uses = self.uses
|
||||
instance.required = int(self.required)
|
||||
logger.debug(f"KitTypeReagentRoleAssociation: {pformat(instance.__dict__)}")
|
||||
# logger.debug(f"KitTypeReagentRoleAssociation: {pformat(instance.__dict__)}")
|
||||
return instance
|
||||
|
||||
@property
|
||||
@@ -395,6 +404,7 @@ class OmniKitTypeReagentRoleAssociation(BaseOmni):
|
||||
|
||||
|
||||
class OmniEquipmentRole(BaseOmni):
|
||||
|
||||
class_object: ClassVar[Any] = EquipmentRole
|
||||
|
||||
name: str = Field(default="", description="property")
|
||||
@@ -421,6 +431,7 @@ class OmniEquipmentRole(BaseOmni):
|
||||
|
||||
|
||||
class OmniTips(BaseOmni):
|
||||
|
||||
class_object: ClassVar[Any] = Tips
|
||||
|
||||
name: str = Field(default="", description="property")
|
||||
@@ -447,6 +458,7 @@ class OmniTips(BaseOmni):
|
||||
|
||||
|
||||
class OmniTipRole(BaseOmni):
|
||||
|
||||
class_object: ClassVar[Any] = TipRole
|
||||
|
||||
name: str = Field(default="", description="property")
|
||||
@@ -477,6 +489,7 @@ class OmniTipRole(BaseOmni):
|
||||
|
||||
|
||||
class OmniProcess(BaseOmni):
|
||||
|
||||
class_object: ClassVar[Any] = Process
|
||||
|
||||
# NOTE: How am I going to figure out relatioinships without getting into recursion issues?
|
||||
@@ -540,6 +553,7 @@ class OmniProcess(BaseOmni):
|
||||
|
||||
|
||||
class OmniKitType(BaseOmni):
|
||||
|
||||
class_object: ClassVar[Any] = KitType
|
||||
|
||||
name: str = Field(default="", description="property")
|
||||
@@ -565,17 +579,17 @@ class OmniKitType(BaseOmni):
|
||||
|
||||
def to_sql(self) -> KitType:
|
||||
kit, is_new = KitType.query_or_create(name=self.name)
|
||||
if is_new:
|
||||
logger.debug(f"New kit made: {kit}")
|
||||
else:
|
||||
logger.debug(f"Kit retrieved: {kit}")
|
||||
# if is_new:
|
||||
# logger.debug(f"New kit made: {kit}")
|
||||
# else:
|
||||
# logger.debug(f"Kit retrieved: {kit}")
|
||||
new_rr = []
|
||||
for rr_assoc in self.kit_reagentrole_associations:
|
||||
new_assoc = rr_assoc.to_sql()
|
||||
if new_assoc not in new_rr:
|
||||
logger.debug(f"Adding {new_assoc} to kit_reagentrole_associations")
|
||||
# logger.debug(f"Adding {new_assoc} to kit_reagentrole_associations")
|
||||
new_rr.append(new_assoc)
|
||||
logger.debug(f"Setting kit_reagentrole_associations to {pformat([item.__dict__ for item in new_rr])}")
|
||||
# logger.debug(f"Setting kit_reagentrole_associations to {pformat([item.__dict__ for item in new_rr])}")
|
||||
kit.kit_reagentrole_associations = new_rr
|
||||
new_st = []
|
||||
for st_assoc in self.kit_submissiontype_associations:
|
||||
@@ -589,9 +603,9 @@ class OmniKitType(BaseOmni):
|
||||
if new_process not in new_processes:
|
||||
new_processes.append(new_process)
|
||||
kit.processes = new_processes
|
||||
logger.debug(f"Kit: {pformat(kit.__dict__)}")
|
||||
for item in kit.kit_reagentrole_associations:
|
||||
logger.debug(f"KTRRassoc: {item.__dict__}")
|
||||
# logger.debug(f"Kit: {pformat(kit.__dict__)}")
|
||||
# for item in kit.kit_reagentrole_associations:
|
||||
# logger.debug(f"KTRRassoc: {item.__dict__}")
|
||||
return kit
|
||||
|
||||
|
||||
@@ -601,11 +615,10 @@ class OmniOrganization(BaseOmni):
|
||||
|
||||
name: str = Field(default="", description="property")
|
||||
cost_centre: str = Field(default="", description="property")
|
||||
# TODO: add in List[OmniContacts]
|
||||
contact: List[str] | List[OmniContact] = Field(default=[], description="relationship", title="Contact")
|
||||
|
||||
def __init__(self, instance_object: Any, **data):
|
||||
logger.debug(f"Incoming data: {data}")
|
||||
# logger.debug(f"Incoming data: {data}")
|
||||
super().__init__(**data)
|
||||
self.instance_object = instance_object
|
||||
|
||||
@@ -642,8 +655,8 @@ class OmniContact(BaseOmni):
|
||||
|
||||
def to_sql(self):
|
||||
contact, is_new = Contact.query_or_create(name=self.name, email=self.email, phone=self.phone)
|
||||
if is_new:
|
||||
logger.debug(f"New contact made: {contact}")
|
||||
else:
|
||||
logger.debug(f"Contact retrieved: {contact}")
|
||||
# if is_new:
|
||||
# logger.debug(f"New contact made: {contact}")
|
||||
# else:
|
||||
# logger.debug(f"Contact retrieved: {contact}")
|
||||
return contact
|
||||
|
||||
@@ -22,6 +22,7 @@ logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
|
||||
class PydReagent(BaseModel):
|
||||
|
||||
lot: str | None
|
||||
role: str | None
|
||||
expiry: date | datetime | Literal['NA'] | None = Field(default=None, validate_default=True)
|
||||
@@ -131,7 +132,7 @@ class PydReagent(BaseModel):
|
||||
if self.model_extra is not None:
|
||||
self.__dict__.update(self.model_extra)
|
||||
reagent = Reagent.query(lot=self.lot, name=self.name)
|
||||
logger.debug(f"Reagent: {reagent}")
|
||||
# logger.debug(f"Reagent: {reagent}")
|
||||
if reagent is None:
|
||||
reagent = Reagent()
|
||||
for key, value in self.__dict__.items():
|
||||
@@ -151,6 +152,7 @@ class PydReagent(BaseModel):
|
||||
|
||||
|
||||
class PydSample(BaseModel, extra='allow'):
|
||||
|
||||
submitter_id: str
|
||||
sample_type: str
|
||||
row: int | List[int] | None
|
||||
@@ -252,6 +254,7 @@ class PydSample(BaseModel, extra='allow'):
|
||||
|
||||
|
||||
class PydTips(BaseModel):
|
||||
|
||||
name: str
|
||||
lot: str | None = Field(default=None)
|
||||
role: str
|
||||
@@ -282,6 +285,7 @@ class PydTips(BaseModel):
|
||||
|
||||
|
||||
class PydEquipment(BaseModel, extra='ignore'):
|
||||
|
||||
asset_number: str
|
||||
name: str
|
||||
nickname: str | None
|
||||
@@ -376,6 +380,7 @@ class PydEquipment(BaseModel, extra='ignore'):
|
||||
|
||||
|
||||
class PydSubmission(BaseModel, extra='allow'):
|
||||
|
||||
filepath: Path
|
||||
submission_type: dict | None
|
||||
submitter_plate_num: dict | None = Field(default=dict(value=None, missing=True), validate_default=True)
|
||||
@@ -948,7 +953,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
self.extraction_kit['value'] = extraction_kit['value']
|
||||
ext_kit = KitType.query(name=self.extraction_kit['value'])
|
||||
ext_kit_rtypes = [item.to_pydantic() for item in
|
||||
ext_kit.get_reagents(required=True, submission_type=self.submission_type['value'])]
|
||||
ext_kit.get_reagents(required_only=True, submission_type=self.submission_type['value'])]
|
||||
# NOTE: Exclude any reagenttype found in this pyd not expected in kit.
|
||||
expected_check = [item.role for item in ext_kit_rtypes]
|
||||
output_reagents = [rt for rt in self.reagents if rt.role in expected_check]
|
||||
@@ -1014,6 +1019,7 @@ class PydSubmission(BaseModel, extra='allow'):
|
||||
|
||||
|
||||
class PydContact(BaseModel):
|
||||
|
||||
name: str
|
||||
phone: str | None
|
||||
email: str | None
|
||||
@@ -1061,6 +1067,7 @@ class PydContact(BaseModel):
|
||||
|
||||
|
||||
class PydOrganization(BaseModel):
|
||||
|
||||
name: str
|
||||
cost_centre: str
|
||||
contacts: List[PydContact] | None
|
||||
@@ -1101,6 +1108,7 @@ class PydOrganization(BaseModel):
|
||||
|
||||
|
||||
class PydReagentRole(BaseModel):
|
||||
|
||||
name: str
|
||||
eol_ext: timedelta | int | None
|
||||
uses: dict | None
|
||||
@@ -1139,6 +1147,7 @@ class PydReagentRole(BaseModel):
|
||||
|
||||
|
||||
class PydKitType(BaseModel):
|
||||
|
||||
name: str
|
||||
reagent_roles: List[PydReagent] = []
|
||||
|
||||
@@ -1160,6 +1169,7 @@ class PydKitType(BaseModel):
|
||||
|
||||
|
||||
class PydEquipmentRole(BaseModel):
|
||||
|
||||
name: str
|
||||
equipment: List[PydEquipment]
|
||||
processes: List[str] | None
|
||||
@@ -1187,6 +1197,7 @@ class PydEquipmentRole(BaseModel):
|
||||
|
||||
|
||||
class PydPCRControl(BaseModel):
|
||||
|
||||
name: str
|
||||
subtype: str
|
||||
target: str
|
||||
@@ -1210,6 +1221,7 @@ class PydPCRControl(BaseModel):
|
||||
|
||||
|
||||
class PydIridaControl(BaseModel, extra='ignore'):
|
||||
|
||||
name: str
|
||||
contains: list | dict #: unstructured hashes in contains.tsv for each organism
|
||||
matches: list | dict #: unstructured hashes in matches.tsv for each organism
|
||||
@@ -1244,6 +1256,7 @@ class PydIridaControl(BaseModel, extra='ignore'):
|
||||
|
||||
|
||||
class PydProcess(BaseModel, extra="allow"):
|
||||
|
||||
name: str
|
||||
version: str = Field(default="1")
|
||||
submission_types: List[str]
|
||||
@@ -1297,7 +1310,7 @@ class PydElastic(BaseModel, extra="allow", arbitrary_types_allowed=True):
|
||||
|
||||
@report_result
|
||||
def to_sql(self):
|
||||
print(self.instance)
|
||||
# print(self.instance)
|
||||
fields = [item for item in self.model_extra]
|
||||
for field in fields:
|
||||
try:
|
||||
@@ -1307,11 +1320,11 @@ class PydElastic(BaseModel, extra="allow", arbitrary_types_allowed=True):
|
||||
continue
|
||||
match field_type:
|
||||
case _RelationshipDeclared():
|
||||
logger.debug(f"{field} is a relationship with {field_type.entity.class_}")
|
||||
# logger.debug(f"{field} is a relationship with {field_type.entity.class_}")
|
||||
field_value = field_type.entity.class_.argument.query(name=getattr(self, field))
|
||||
logger.debug(f"{field} query result: {field_value}")
|
||||
# logger.debug(f"{field} query result: {field_value}")
|
||||
case ColumnProperty():
|
||||
logger.debug(f"{field} is a property.")
|
||||
# logger.debug(f"{field} is a property.")
|
||||
field_value = getattr(self, field)
|
||||
self.instance.__setattr__(field, field_value)
|
||||
return self.instance
|
||||
|
||||
Reference in New Issue
Block a user