Addition of procedure parser in import.

This commit is contained in:
lwark
2025-06-17 15:09:51 -05:00
parent 0233bc3ac2
commit d8c3f3bbb2
31 changed files with 688 additions and 304 deletions

View File

@@ -8,8 +8,8 @@ from PyQt6.QtWidgets import (
from PyQt6.QtWebEngineWidgets import QWebEngineView
from tools import jinja_template_loading
import logging
from backend.db import models
from typing import Literal
from typing import Literal, Any
logger = logging.getLogger(f"submissions.{__name__}")
@@ -70,7 +70,8 @@ class ObjectSelector(QDialog):
dialog to input BaseClass type manually
"""
def __init__(self, title: str, message: str, obj_type: str | type[models.BaseClass], values: list | None = None):
def __init__(self, title: str, message: str, obj_type: str | Any, values: list | None = None):
from backend.db import models
super().__init__()
self.setWindowTitle(title)
self.widget = QComboBox()

View File

@@ -29,7 +29,7 @@ class ProcedureCreation(QDialog):
super().__init__(parent)
self.run = run
self.proceduretype = proceduretype
self.setWindowTitle(f"New {proceduretype.name} for { run.rsl_plate_num }")
self.setWindowTitle(f"New {proceduretype.name} for { run.rsl_plate_number }")
self.created_procedure = self.proceduretype.construct_dummy_procedure(run=self.run)
self.created_procedure.update_kittype_reagentroles(kittype=self.created_procedure.possible_kits[0])
self.created_procedure.samples = self.run.constuct_sample_dicts_for_proceduretype(proceduretype=self.proceduretype)
@@ -65,8 +65,8 @@ class ProcedureCreation(QDialog):
template_name="procedure_creation",
# css_in=['new_context_menu'],
js_in=["procedure_form", "grid_drag", "context_menu"],
proceduretype=self.proceduretype.as_dict,
run=self.run.to_dict(),
proceduretype=self.proceduretype.details_dict(),
run=self.run.details_dict(),
procedure=self.created_procedure.__dict__,
plate_map=self.plate_map
)

View File

@@ -1,7 +0,0 @@
class DefaultResults(object):
pass
from .pcr import PCR

View File

@@ -1,39 +0,0 @@
"""
"""
import logging
from pathlib import Path
from backend.validators import PydResults
from backend.db.models import Procedure, Results
from backend.excel.parsers.pcr_parser import PCRSampleParser, PCRInfoParser
from frontend.widgets.functions import select_open_file
from tools import get_application_from_parent
from . import DefaultResults
logger = logging.getLogger(f"submissions.{__name__}")
class PCR(DefaultResults):
def __init__(self, procedure: Procedure, parent, fname:Path|str|None=None):
logger.debug(f"FName before correction: {fname}")
self.procedure = procedure
if not fname:
self.fname = select_open_file(file_extension="xlsx", obj=get_application_from_parent(parent))
elif isinstance(fname, str):
self.fname = Path(fname)
logger.debug(f"FName after correction: {fname}")
self.info_parser = PCRInfoParser(filepath=self.fname, procedure=self.procedure)
self.sample_parser = PCRSampleParser(filepath=self.fname, procedure=self.procedure)
self.build_procedure()
self.build_samples()
def build_procedure(self):
procedure_info = self.info_parser.to_pydantic()
procedure_sql = procedure_info.to_sql()
procedure_sql.save()
def build_samples(self):
samples = self.sample_parser.to_pydantic()
for sample in samples:
sql = sample.to_sql()
sql.save()

View File

@@ -21,9 +21,9 @@ class SampleChecker(QDialog):
def __init__(self, parent, title: str, samples: List[PydSample], clientsubmission: ClientSubmission|None=None):
super().__init__(parent)
if clientsubmission:
self.rsl_plate_num = RSLNamer.construct_new_plate_name(clientsubmission.to_dict())
self.rsl_plate_number = RSLNamer.construct_new_plate_name(clientsubmission.to_dict())
else:
self.rsl_plate_num = clientsubmission
self.rsl_plate_number = clientsubmission
self.samples = samples
self.setWindowTitle(title)
self.app = get_application_from_parent(parent)
@@ -45,7 +45,7 @@ class SampleChecker(QDialog):
except AttributeError as e:
logger.error(f"Problem getting sample list: {e}")
samples = []
html = template.render(samples=samples, css=css, rsl_plate_num=self.rsl_plate_num)
html = template.render(samples=samples, css=css, rsl_plate_number=self.rsl_plate_number)
self.webview.setHtml(html)
QBtn = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
self.buttonBox = QDialogButtonBox(QBtn)
@@ -76,9 +76,9 @@ class SampleChecker(QDialog):
item.__setattr__("enabled", enabled)
@pyqtSlot(str)
def set_rsl_plate_num(self, rsl_plate_num: str):
logger.debug(f"RSL plate num: {rsl_plate_num}")
self.rsl_plate_num = rsl_plate_num
def set_rsl_plate_number(self, rsl_plate_number: str):
logger.debug(f"RSL plate num: {rsl_plate_number}")
self.rsl_plate_number = rsl_plate_number
@property
def formatted_list(self) -> List[dict]:

View File

@@ -50,17 +50,33 @@ class SubmissionDetails(QDialog):
# NOTE: setup channel
self.channel = QWebChannel()
self.channel.registerObject('backend', self)
match sub:
case Run():
self.run_details(run=sub)
self.rsl_plate_num = sub.rsl_plate_num
case Sample():
self.sample_details(sample=sub)
case Reagent():
self.reagent_details(reagent=sub)
# match sub:
# case Run():
# self.run_details(run=sub)
# self.rsl_plate_number = sub.rsl_plate_number
# case Sample():
# self.sample_details(sample=sub)
# case Reagent():
# self.reagent_details(reagent=sub)
# NOTE: Used to maintain javascript functions.
self.object_details(object=sub)
self.webview.page().setWebChannel(self.channel)
def object_details(self, object):
details = object.details_dict()
template = object.details_template
template_path = Path(template.environment.loader.__getattribute__("searchpath")[0])
with open(template_path.joinpath("css", "styles.css"), "r") as f:
css = f.read()
key = object.__class__.__name__.lower()
d = {key: details}
logger.debug(f"Using details: {d}")
html = template.render(**d, css=css)
self.webview.setHtml(html)
self.setWindowTitle(f"{object.__class__.__name__} Details - {object.name}")
def activate_export(self) -> None:
"""
Determines if export pdf should be active.
@@ -213,7 +229,7 @@ class SubmissionDetails(QDialog):
logger.debug(f"Submission details.")
if isinstance(run, str):
run = Run.query(name=run)
self.rsl_plate_num = run.rsl_plate_num
self.rsl_plate_number = run.rsl_plate_number
self.base_dict = run.to_dict(full_data=True)
# NOTE: don't want id
self.base_dict['platemap'] = run.make_plate_map(sample_list=run.hitpicked)
@@ -244,7 +260,7 @@ class SubmissionDetails(QDialog):
run.completed_date = datetime.now()
run.completed_date.replace(tzinfo=timezone)
run.save()
self.run_details(run=self.rsl_plate_num)
self.run_details(run=self.rsl_plate_number)
def save_pdf(self):
"""
@@ -264,7 +280,7 @@ class SubmissionComment(QDialog):
super().__init__(parent)
self.app = get_application_from_parent(parent)
self.submission = submission
self.setWindowTitle(f"{self.submission.rsl_plate_num} Submission Comment")
self.setWindowTitle(f"{self.submission.rsl_plate_number} Submission Comment")
# NOTE: create text field
self.txt_editor = QTextEdit(self)
self.txt_editor.setReadOnly(False)

View File

@@ -161,7 +161,7 @@ class SubmissionsSheet(QTableView):
for run in runs:
new_run = dict(
start_time=run[0].strip(),
rsl_plate_num=run[1].strip(),
rsl_plate_number=run[1].strip(),
sample_count=run[2].strip(),
status=run[3].strip(),
experiment_name=run[4].strip(),
@@ -213,7 +213,7 @@ class SubmissionsSheet(QTableView):
for run in runs:
new_run = dict(
start_time=run[0].strip(),
rsl_plate_num=run[1].strip(),
rsl_plate_number=run[1].strip(),
biomek_status=run[2].strip(),
quant_status=run[3].strip(),
experiment_name=run[4].strip(),
@@ -379,7 +379,7 @@ class SubmissionsTree(QTreeView):
query_str=submission['submitter_plate_id'],
item_type=ClientSubmission
))
logger.debug(f"Added {submission_item}")
# logger.debug(f"Added {submission_item}")
for run in submission['run']:
# self.model.append_element_to_group(group_item=group_item, element=run)
run_item = self.model.add_child(parent=submission_item, child=dict(
@@ -387,14 +387,14 @@ class SubmissionsTree(QTreeView):
query_str=run['plate_number'],
item_type=Run
))
logger.debug(f"Added {run_item}")
# logger.debug(f"Added {run_item}")
for procedure in run['procedures']:
procedure_item = self.model.add_child(parent=run_item, child=dict(
name=procedure['name'],
query_str=procedure['name'],
item_type=Procedure
))
logger.debug(f"Added {procedure_item}")
# logger.debug(f"Added {procedure_item}")
def _populateTree(self, children, parent):
for child in children:
@@ -415,7 +415,6 @@ class SubmissionsTree(QTreeView):
# id = id.sibling(id.row(), 1)
indexes = self.selectedIndexes()
dicto = next((item.data(1) for item in indexes if item.data(1)))
logger.debug(dicto)
# try:
# id = int(id.data())
# except ValueError:
@@ -423,6 +422,7 @@ class SubmissionsTree(QTreeView):
# Run.query(id=id).show_details(self)
obj = dicto['item_type'].query(name=dicto['query_str'], limit=1)
logger.debug(obj)
obj.show_details(obj)
def link_extractions(self):
pass

View File

@@ -10,7 +10,7 @@ from .functions import select_open_file, select_save_file
import logging
from pathlib import Path
from tools import Report, Result, check_not_nan, main_form_style, report_result, get_application_from_parent
from backend.excel import ClientSubmissionParser, ClientSampleParser
from backend.excel.parsers.clientsubmission_parser import ClientSubmissionInfoParser, ClientSubmissionSampleParser
from backend.validators import PydSubmission, PydReagent, PydClientSubmission, PydSample
from backend.db import (
ClientLab, SubmissionType, Reagent,
@@ -121,20 +121,20 @@ class SubmissionFormContainer(QWidget):
return report
# NOTE: create sheetparser using excel sheet and context from gui
try:
self.clientsubmissionparser = ClientSubmissionParser(filepath=fname)
self.clientsubmissionparser = ClientSubmissionInfoParser(filepath=fname)
except PermissionError:
logger.error(f"Couldn't get permission to access file: {fname}")
return
except AttributeError:
self.clientsubmissionparser = ClientSubmissionParser(filepath=fname)
self.clientsubmissionparser = ClientSubmissionInfoParser(filepath=fname)
try:
# self.prsr = SheetParser(filepath=fname)
self.sampleparser = ClientSampleParser(filepath=fname)
self.sampleparser = ClientSubmissionSampleParser(filepath=fname)
except PermissionError:
logger.error(f"Couldn't get permission to access file: {fname}")
return
except AttributeError:
self.sampleparser = ClientSampleParser(filepath=fname)
self.sampleparser = ClientSubmissionSampleParser(filepath=fname)
self.pydclientsubmission = self.clientsubmissionparser.to_pydantic()
self.pydsamples = self.sampleparser.to_pydantic()
# logger.debug(f"Samples: {pformat(self.pydclientsubmission.sample)}")
@@ -368,7 +368,7 @@ class SubmissionFormWidget(QWidget):
pass
# NOTE: code 1: ask for overwrite
case 1:
dlg = QuestionAsker(title=f"Review {base_submission.rsl_plate_num}?", message=trigger.msg)
dlg = QuestionAsker(title=f"Review {base_submission.rsl_plate_number}?", message=trigger.msg)
if dlg.exec():
# NOTE: Do not add duplicate reagents.
pass