Addition of turnaround time tracking.
This commit is contained in:
@@ -279,7 +279,7 @@ class Control(BaseClass):
|
||||
@classmethod
|
||||
def make_parent_buttons(cls, parent: QWidget) -> None:
|
||||
"""
|
||||
Super that will make buttons in a CustomFigure. Made to be overrided.
|
||||
Super that will make buttons in a CustomFigure. Made to be overridden.
|
||||
|
||||
Args:
|
||||
parent (QWidget): chart holding widget to add buttons to.
|
||||
@@ -299,6 +299,10 @@ class Control(BaseClass):
|
||||
|
||||
|
||||
class PCRControl(Control):
|
||||
"""
|
||||
Class made to hold info from Design & Analysis software.
|
||||
"""
|
||||
|
||||
id = Column(INTEGER, ForeignKey('_control.id'), primary_key=True)
|
||||
subtype = Column(String(16)) #: PC or NC
|
||||
target = Column(String(16)) #: N1, N2, etc.
|
||||
@@ -348,7 +352,7 @@ class PCRControl(Control):
|
||||
df = df[df.ct > 0.0]
|
||||
except AttributeError:
|
||||
df = df
|
||||
fig = PCRFigure(df=df, modes=[])
|
||||
fig = PCRFigure(df=df, modes=[], settings=chart_settings)
|
||||
return report, fig
|
||||
|
||||
def to_pydantic(self):
|
||||
@@ -433,12 +437,12 @@ class IridaControl(Control):
|
||||
def convert_by_mode(self, control_sub_type: str, mode: Literal['kraken', 'matches', 'contains'],
|
||||
consolidate: bool = False) -> Generator[dict, None, None]:
|
||||
"""
|
||||
split this instance into analysis types for controls graphs
|
||||
split this instance into analysis types ('kraken', 'matches', 'contains') for controls graphs
|
||||
|
||||
Args:
|
||||
consolidate (bool): whether to merge all off-target genera. Defaults to False
|
||||
control_sub_type (str): control subtype, 'MCS-NOS', etc.
|
||||
mode (str): analysis type, 'contains', etc.
|
||||
mode (Literal['kraken', 'matches', 'contains']): analysis type, 'contains', etc.
|
||||
|
||||
Returns:
|
||||
List[dict]: list of records
|
||||
@@ -562,7 +566,7 @@ class IridaControl(Control):
|
||||
df, modes = cls.prep_df(ctx=ctx, df=df)
|
||||
# logger.debug(f"prepped df: \n {df}")
|
||||
fig = IridaFigure(df=df, ytitle=title, modes=modes, parent=parent,
|
||||
months=chart_settings['months'])
|
||||
settings=chart_settings)
|
||||
return report, fig
|
||||
|
||||
@classmethod
|
||||
@@ -571,9 +575,8 @@ class IridaControl(Control):
|
||||
Convert list of control records to dataframe
|
||||
|
||||
Args:
|
||||
ctx (dict): settings passed from gui
|
||||
input_df (list[dict]): list of dictionaries containing records
|
||||
sub_type (str | None, optional): sub_type of submission type. Defaults to None.
|
||||
sub_mode (str | None, optional): sub_type of submission type. Defaults to None.
|
||||
|
||||
Returns:
|
||||
DataFrame: dataframe of controls
|
||||
|
||||
@@ -168,7 +168,6 @@ class KitType(BaseClass):
|
||||
else:
|
||||
return (item.reagent_role for item in relevant_associations)
|
||||
|
||||
# TODO: Move to BasicSubmission?
|
||||
def construct_xl_map_for_use(self, submission_type: str | SubmissionType) -> Generator[(str, str), None, None]:
|
||||
"""
|
||||
Creates map of locations in Excel workbook for a SubmissionType
|
||||
@@ -274,8 +273,7 @@ class KitType(BaseClass):
|
||||
for kk, vv in assoc.to_export_dict().items():
|
||||
v[kk] = vv
|
||||
base_dict['reagent roles'].append(v)
|
||||
# for k, v in submission_type.construct_equipment_map():
|
||||
for k, v in submission_type.contstruct_field_map("equipment"):
|
||||
for k, v in submission_type.construct_field_map("equipment"):
|
||||
try:
|
||||
assoc = next(item for item in submission_type.submissiontype_equipmentrole_associations if
|
||||
item.equipment_role.name == k)
|
||||
@@ -428,7 +426,7 @@ class Reagent(BaseClass, LogMixin):
|
||||
submission=sub)) #: Association proxy to SubmissionSampleAssociation.samples
|
||||
|
||||
def __repr__(self):
|
||||
if self.name is not None:
|
||||
if self.name:
|
||||
return f"<Reagent({self.name}-{self.lot})>"
|
||||
else:
|
||||
return f"<Reagent({self.role.name}-{self.lot})>"
|
||||
@@ -447,11 +445,12 @@ class Reagent(BaseClass, LogMixin):
|
||||
|
||||
if extraction_kit is not None:
|
||||
# NOTE: Get the intersection of this reagent's ReagentType and all ReagentTypes in KitType
|
||||
try:
|
||||
reagent_role = list(set(self.role).intersection(extraction_kit.reagent_roles))[0]
|
||||
# NOTE: Most will be able to fall back to first ReagentType in itself because most will only have 1.
|
||||
except:
|
||||
reagent_role = self.role[0]
|
||||
reagent_role = next((item for item in set(self.role).intersection(extraction_kit.reagent_roles)), self.role[0])
|
||||
# try:
|
||||
# reagent_role = list(set(self.role).intersection(extraction_kit.reagent_roles))[0]
|
||||
# # NOTE: Most will be able to fall back to first ReagentType in itself because most will only have 1.
|
||||
# except:
|
||||
# reagent_role = self.role[0]
|
||||
else:
|
||||
try:
|
||||
reagent_role = self.role[0]
|
||||
|
||||
@@ -24,7 +24,7 @@ from sqlite3 import OperationalError as SQLOperationalError, IntegrityError as S
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.drawing.image import Image as OpenpyxlImage
|
||||
from tools import row_map, setup_lookup, jinja_template_loading, rreplace, row_keys, check_key_or_attr, Result, Report, \
|
||||
report_result, create_holidays_for_year
|
||||
report_result, create_holidays_for_year, ctx
|
||||
from datetime import datetime, date, timedelta
|
||||
from typing import List, Any, Tuple, Literal, Generator
|
||||
from dateutil.parser import parse
|
||||
@@ -127,7 +127,7 @@ class BasicSubmission(BaseClass, LogMixin):
|
||||
|
||||
def __repr__(self) -> str:
|
||||
submission_type = self.submission_type or "Basic"
|
||||
return f"<{submission_type}Submission({self.rsl_plate_num})>"
|
||||
return f"<Submission({self.rsl_plate_num})>"
|
||||
|
||||
@classmethod
|
||||
def jsons(cls) -> List[str]:
|
||||
@@ -1380,17 +1380,22 @@ class BasicSubmission(BaseClass, LogMixin):
|
||||
writer = pyd.to_writer()
|
||||
writer.xl.save(filename=fname.with_suffix(".xlsx"))
|
||||
|
||||
def get_turnaround_time(self):
|
||||
completed = self.completed_date or datetime.now()
|
||||
return self.calculate_turnaround(start_date=self.submitted_date.date(), end_date=completed.date())
|
||||
def get_turnaround_time(self) -> Tuple[int|None, bool|None]:
|
||||
try:
|
||||
completed = self.completed_date.date()
|
||||
except AttributeError:
|
||||
completed = None
|
||||
return self.calculate_turnaround(start_date=self.submitted_date.date(), end_date=completed)
|
||||
|
||||
@classmethod
|
||||
def calculate_turnaround(cls, start_date:date|None=None, end_date:date|None=None) -> int|None:
|
||||
def calculate_turnaround(cls, start_date:date|None=None, end_date:date|None=None) -> Tuple[int|None, bool|None]:
|
||||
if not end_date:
|
||||
return None, None
|
||||
try:
|
||||
delta = np.busday_count(start_date, end_date, holidays=create_holidays_for_year(start_date.year))
|
||||
delta = np.busday_count(start_date, end_date, holidays=create_holidays_for_year(start_date.year)) + 1
|
||||
except ValueError:
|
||||
return None
|
||||
return delta + 1
|
||||
return None, None
|
||||
return delta, delta <= ctx.TaT_threshold
|
||||
|
||||
|
||||
# Below are the custom submission types
|
||||
|
||||
Reference in New Issue
Block a user