prior to db rebuild

This commit is contained in:
Landon Wark
2023-07-26 14:05:52 -05:00
parent 82dffe3af2
commit f22e697815
11 changed files with 76 additions and 53 deletions

View File

@@ -18,7 +18,7 @@ from getpass import getuser
import numpy as np
import yaml
from pathlib import Path
from tools import Settings
from tools import Settings, check_regex_match, RSLNamer
@@ -43,7 +43,6 @@ def store_submission(ctx:Settings, base_submission:models.BasicSubmission) -> No
Returns:
None|dict : object that indicates issue raised for reporting in gui
"""
from tools import RSLNamer
logger.debug(f"Hello from store_submission")
# Add all samples to sample table
typer = RSLNamer(ctx=ctx, instr=base_submission.rsl_plate_num)
@@ -52,7 +51,7 @@ def store_submission(ctx:Settings, base_submission:models.BasicSubmission) -> No
logger.debug(f"Typer: {typer.submission_type}")
# Suuuuuper hacky way to be sure that the artic doesn't overwrite the ww plate in a ww sample
# need something more elegant
if "_artic" not in typer.submission_type:
if "_artic" not in typer.submission_type.lower():
sample.rsl_plate = base_submission
else:
sample.artic_rsl_plate = base_submission
@@ -114,7 +113,7 @@ def construct_submission_info(ctx:Settings, info_dict:dict) -> models.BasicSubmi
Returns:
models.BasicSubmission: Constructed submission object
"""
from tools import check_regex_match, RSLNamer
# from tools import check_regex_match, RSLNamer
# convert submission type into model name
query = info_dict['submission_type'].replace(" ", "")
# Ensure an rsl plate number exists for the plate
@@ -127,7 +126,8 @@ def construct_submission_info(ctx:Settings, info_dict:dict) -> models.BasicSubmi
info_dict['rsl_plate_num'] = RSLNamer(ctx=ctx, instr=info_dict["rsl_plate_num"]).parsed_name
# check database for existing object
# instance = ctx['database_session'].query(models.BasicSubmission).filter(models.BasicSubmission.rsl_plate_num==info_dict['rsl_plate_num']).first()
instance = ctx.database_session.query(models.BasicSubmission).filter(models.BasicSubmission.rsl_plate_num==info_dict['rsl_plate_num']).first()
# instance = ctx.database_session.query(models.BasicSubmission).filter(models.BasicSubmission.rsl_plate_num==info_dict['rsl_plate_num']).first()
instance = lookup_submission_by_rsl_num(ctx=ctx, rsl_num=info_dict['rsl_plate_num'])
# get model based on submission type converted above
logger.debug(f"Looking at models for submission type: {query}")
model = getattr(models, query)
@@ -866,8 +866,6 @@ def hitpick_plate(submission:models.BasicSubmission, plate_number:int=0) -> list
plate_dicto = []
for sample in submission.samples:
# have sample report back its info if it's positive, otherwise, None
method_list = [func for func in dir(sample) if callable(getattr(sample, func))]
logger.debug(f"Method list of sample: {method_list}")
samp = sample.to_hitpick()
if samp == None:
continue
@@ -963,7 +961,6 @@ def lookup_last_used_reagenttype_lot(ctx:Settings, type_name:str) -> models.Reag
except AttributeError:
return None
def check_kit_integrity(sub:BasicSubmission|KitType, reagenttypes:list|None=None) -> dict|None:
"""
Ensures all reagents expected in kit are listed in Submission

View File

@@ -18,7 +18,7 @@ class WWSample(Base):
id = Column(INTEGER, primary_key=True) #: primary key
ww_processing_num = Column(String(64)) #: wastewater processing number
ww_sample_full_id = Column(String(64), nullable=False)
ww_sample_full_id = Column(String(64), nullable=False, unique=True)
rsl_number = Column(String(64)) #: rsl plate identification number
rsl_plate = relationship("Wastewater", back_populates="samples") #: relationship to parent plate
rsl_plate_id = Column(INTEGER, ForeignKey("_submissions.id", ondelete="SET NULL", name="fk_WWS_submission_id"))
@@ -111,7 +111,7 @@ class BCSample(Base):
id = Column(INTEGER, primary_key=True) #: primary key
well_number = Column(String(8)) #: location on parent plate
sample_id = Column(String(64), nullable=False) #: identification from submitter
sample_id = Column(String(64), nullable=False, unique=True) #: identification from submitter
organism = Column(String(64)) #: bacterial specimen
concentration = Column(String(16)) #:
rsl_plate_id = Column(INTEGER, ForeignKey("_submissions.id", ondelete="SET NULL", name="fk_BCS_sample_id")) #: id of parent plate

View File

@@ -314,23 +314,29 @@ class SheetParser(object):
continue
logger.debug(f"massaged sample list for {self.sub['rsl_plate_num']}: {pprint.pprint(return_list)}")
return return_list
submission_info = self.xl.parse("cDNA", dtype=object)
biomek_info = self.xl.parse("ArticV4_1 Biomek", dtype=object)
# Reminder that the iloc uses row, column ordering
# sub_reagent_range = submission_info.iloc[56:, 1:4].dropna(how='all')
sub_reagent_range = submission_info.iloc[7:15, 5:9].dropna(how='all')
biomek_reagent_range = biomek_info.iloc[62:, 0:3].dropna(how='all')
submission_info = self.xl.parse("First Strand", dtype=object)
biomek_info = self.xl.parse("ArticV4 Biomek", dtype=object)
sub_reagent_range = submission_info.iloc[56:, 1:4].dropna(how='all')
biomek_reagent_range = biomek_info.iloc[60:, 0:3].dropna(how='all')
# submission_info = self.xl.parse("cDNA", dtype=object)
# biomek_info = self.xl.parse("ArticV4_1 Biomek", dtype=object)
# # Reminder that the iloc uses row, column ordering
# # sub_reagent_range = submission_info.iloc[56:, 1:4].dropna(how='all')
# sub_reagent_range = submission_info.iloc[7:15, 5:9].dropna(how='all')
# biomek_reagent_range = biomek_info.iloc[62:, 0:3].dropna(how='all')
self.sub['submitter_plate_num'] = ""
self.sub['rsl_plate_num'] = RSLNamer(ctx=self.ctx, instr=self.filepath.__str__()).parsed_name
self.sub['submitted_date'] = biomek_info.iloc[1][1]
self.sub['submitting_lab'] = "Enterics Wastewater Genomics"
self.sub['sample_count'] = submission_info.iloc[34][6]
self.sub['sample_count'] = submission_info.iloc[4][6]
# self.sub['sample_count'] = submission_info.iloc[34][6]
self.sub['extraction_kit'] = "ArticV4.1"
self.sub['technician'] = f"MM: {biomek_info.iloc[2][1]}, Bio: {biomek_info.iloc[3][1]}"
self.sub['reagents'] = []
parse_reagents(sub_reagent_range)
parse_reagents(biomek_reagent_range)
samples = massage_samples(biomek_info.iloc[25:33, 0:])
samples = massage_samples(biomek_info.iloc[22:31, 0:])
# samples = massage_samples(biomek_info.iloc[25:33, 0:])
sample_parser = SampleParser(self.ctx, pd.DataFrame.from_records(samples))
sample_parse = getattr(sample_parser, f"parse_{self.sub['submission_type']['value'].lower()}_samples")
self.sample_result, self.sub['samples'] = sample_parse()

View File

@@ -93,7 +93,6 @@ class PydSubmission(BaseModel, extra=Extra.allow):
else:
return value
else:
# logger.debug(f"Pydant values:{type(values)}\n{values}")
return dict(value=RSLNamer(ctx=values.data['ctx'], instr=values.data['filepath'].__str__()).parsed_name, parsed=False)
@field_validator("technician", mode="before")
@@ -115,11 +114,6 @@ class PydSubmission(BaseModel, extra=Extra.allow):
return_val = []
for reagent in value:
logger.debug(f"Pydantic reagent: {reagent}")
# match reagent.type.lower():
# case 'atcc':
# continue
# case _:
# return_val.append(reagent)
if reagent.type == None:
continue
else:
@@ -132,7 +126,6 @@ class PydSubmission(BaseModel, extra=Extra.allow):
if check_not_nan(value):
return int(value)
else:
# raise ValueError(f"{value} could not be used to create an integer.")
return convert_nans_to_nones(value)
@field_validator("extraction_kit", mode='before')
@@ -142,13 +135,11 @@ class PydSubmission(BaseModel, extra=Extra.allow):
if check_not_nan(value):
return dict(value=value, parsed=True)
else:
# logger.debug(values.data)
dlg = KitSelector(ctx=values.data['ctx'], title="Kit Needed", message="At minimum a kit is needed. Please select one.")
if dlg.exec():
return dict(value=dlg.getValues(), parsed=False)
else:
raise ValueError("Extraction kit needed.")
@field_validator("submission_type", mode='before')
@classmethod
@@ -161,14 +152,3 @@ class PydSubmission(BaseModel, extra=Extra.allow):
return dict(value=value.title(), parsed=False)
else:
return dict(value=RSLNamer(ctx=values.data['ctx'], instr=values.data['filepath'].__str__()).submission_type.title(), parsed=False)
# @model_validator(mode="after")
# def ensure_kit(cls, values):
# logger.debug(f"Model values: {values}")
# missing_fields = [k for k,v in values if v == None]
# if len(missing_fields) > 0:
# logger.debug(f"Missing fields: {missing_fields}")
# values['missing_fields'] = missing_fields
# return values

View File

@@ -1,5 +1,5 @@
'''
Operations for all user interactions.
Constructs main application.
'''
import sys
from PyQt6.QtWidgets import (
@@ -31,7 +31,6 @@ class App(QMainWindow):
self.ctx = ctx
# indicate version and connected database in title bar
try:
# self.title = f"Submissions App (v{ctx['package'].__version__}) - {ctx['database']}"
self.title = f"Submissions App (v{ctx.package.__version__}) - {ctx.database_path}"
except (AttributeError, KeyError):
self.title = f"Submissions App"

View File

@@ -23,7 +23,10 @@ def select_open_file(obj:QMainWindow, file_extension:str) -> Path:
Path: Path of file to be opened
"""
# home_dir = str(Path(obj.ctx["directory_path"]))
home_dir = str(Path(obj.ctx.directory_path))
try:
home_dir = Path(obj.ctx.directory_path).resolve().__str__()
except FileNotFoundError:
home_dir = Path.home().resolve().__str__()
fname = Path(QFileDialog.getOpenFileName(obj, 'Open file', home_dir, filter = f"{file_extension}(*.{file_extension})")[0])
return fname
@@ -43,7 +46,7 @@ def select_save_file(obj:QMainWindow, default_name:str, extension:str) -> Path:
# home_dir = Path(obj.ctx["directory_path"]).joinpath(default_name).resolve().__str__()
home_dir = Path(obj.ctx.directory_path).joinpath(default_name).resolve().__str__()
except FileNotFoundError:
home_dir = Path.home().resolve().__str__()
home_dir = Path.home().joinpath(default_name).resolve().__str__()
fname = Path(QFileDialog.getSaveFileName(obj, "Save File", home_dir, filter = f"{extension}(*.{extension})")[0])
return fname

View File

@@ -230,10 +230,9 @@ class ControlsDatePicker(QWidget):
super().__init__()
self.start_date = QDateEdit(calendarPopup=True)
# start date is three month prior to end date by default
# NOTE: 2 month, but the variable name is the same cause I'm lazy
threemonthsago = QDate.currentDate().addDays(-60)
self.start_date.setDate(threemonthsago)
# start date is two months prior to end date by default
twomonthsago = QDate.currentDate().addDays(-60)
self.start_date.setDate(twomonthsago)
self.end_date = QDateEdit(calendarPopup=True)
self.end_date.setDate(QDate.currentDate())
self.layout = QHBoxLayout()
@@ -299,4 +298,3 @@ class ImportReagent(QComboBox):
logger.debug(f"New relevant reagents: {relevant_reagents}")
self.setObjectName(f"lot_{reagent.type}")
self.addItems(relevant_reagents)

View File

@@ -338,7 +338,8 @@ class SubmissionDetails(QDialog):
# with open("test.html", "w") as f:
# f.write(html)
try:
home_dir = Path(self.ctx["directory_path"]).joinpath(f"Submission_Details_{self.base_dict['Plate Number']}.pdf").resolve().__str__()
# home_dir = Path(self.ctx["directory_path"]).joinpath(f"Submission_Details_{self.base_dict['Plate Number']}.pdf").resolve().__str__()
home_dir = Path(self.ctx.directory_path).joinpath(f"Submission_Details_{self.base_dict['Plate Number']}.pdf").resolve().__str__()
except FileNotFoundError:
home_dir = Path.home().resolve().__str__()
fname = Path(QFileDialog.getSaveFileName(self, "Save File", home_dir, filter=".pdf")[0])

View File

@@ -136,7 +136,8 @@ def check_if_app(ctx:dict=None) -> bool:
def retrieve_rsl_number(in_str:str) -> Tuple[str, str]:
"""
Uses regex to retrieve the plate number and submission type from an input string
DEPRECIATED. REPLACED BY RSLNamer.parsed_name
Args:
in_str (str): string to be parsed
@@ -354,7 +355,7 @@ class Settings(BaseSettings):
super_users: list
power_users: list
rerun_regex: str
submission_types: dict
submission_types: dict|None = None
database_session: Session|None = None
package: Any|None = None
@@ -609,4 +610,4 @@ def jinja_template_loading():
# jinja template loading
loader = FileSystemLoader(loader_path)
env = Environment(loader=loader)
return env
return env