Moved import PCR results to context menu.

This commit is contained in:
Landon Wark
2024-04-11 09:33:16 -05:00
parent dc5549486f
commit f994f81d11
5 changed files with 59 additions and 89 deletions

View File

@@ -1,6 +1,7 @@
## 202404.02
- Various bug fixes.
- Move import PCR results to context menu.
- Added ability to sign off on submission in submission details.
## 202403.03

View File

@@ -3,7 +3,7 @@ Models for the main submission types.
'''
from __future__ import annotations
from getpass import getuser
import json, logging, uuid, tempfile, re, yaml, base64
import logging, uuid, tempfile, re, yaml, base64
from zipfile import ZipFile
from tempfile import TemporaryDirectory
from reportlab.graphics.barcode import createBarcodeImageInMemory
@@ -14,7 +14,6 @@ from pprint import pformat
from . import Reagent, SubmissionType, KitType, Organization
from sqlalchemy import Column, String, TIMESTAMP, INTEGER, ForeignKey, JSON, FLOAT, case
from sqlalchemy.orm import relationship, validates, Query
from json.decoder import JSONDecodeError
from sqlalchemy.ext.associationproxy import association_proxy
import pandas as pd
from openpyxl import Workbook
@@ -252,7 +251,7 @@ class BasicSubmission(BaseClass):
sample_list = self.hitpick_plate()
# logger.debug("Setting background colours")
for sample in sample_list:
if sample['Positive']:
if sample['positive']:
sample['background_color'] = "#f10f07"
else:
if "colour" in sample.keys():
@@ -1268,6 +1267,54 @@ class Wastewater(BasicSubmission):
row = idx.index.to_list()[0]
return row + 1
def custom_context_events(self) -> dict:
events = super().custom_context_events()
events['Link PCR'] = self.link_pcr
return events
def link_pcr(self, obj):
from backend.excel import PCRParser
from frontend.widgets import select_open_file
fname = select_open_file(obj=obj, file_extension="xlsx")
parser = PCRParser(filepath=fname)
# Check if PCR info already exists
if hasattr(self, 'pcr_info') and self.pcr_info != None:
# existing = json.loads(sub.pcr_info)
existing = self.pcr_info
else:
existing = None
if existing != None:
# update pcr_info
try:
logger.debug(f"Updating {type(existing)}: {existing} with {type(parser.pcr)}: {parser.pcr}")
# if json.dumps(parser.pcr) not in sub.pcr_info:
if parser.pcr not in self.pcr_info:
existing.append(parser.pcr)
logger.debug(f"Setting: {existing}")
# sub.pcr_info = json.dumps(existing)
self.pcr_info = existing
except TypeError:
logger.error(f"Error updating!")
# sub.pcr_info = json.dumps([parser.pcr])
self.pcr_info = [parser.pcr]
logger.debug(f"Final pcr info for {self.rsl_plate_num}: {self.pcr_info}")
else:
# sub.pcr_info = json.dumps([parser.pcr])
self.pcr_info = [parser.pcr]
logger.debug(f"Existing {type(self.pcr_info)}: {self.pcr_info}")
logger.debug(f"Inserting {type(parser.pcr)}: {parser.pcr}")
self.save(original=False)
logger.debug(f"Got {len(parser.samples)} samples to update!")
logger.debug(f"Parser samples: {parser.samples}")
for sample in self.samples:
logger.debug(f"Running update on: {sample}")
try:
sample_dict = [item for item in parser.samples if item['sample']==sample.rsl_number][0]
except IndexError:
continue
self.update_subsampassoc(sample=sample, input_dict=sample_dict)
# self.report.add_result(Result(msg=f"We added PCR info to {sub.rsl_plate_num}.", status='Information'))
class WastewaterArtic(BasicSubmission):
"""
derivative submission type for artic wastewater
@@ -2094,7 +2141,7 @@ class SubmissionSampleAssociation(BaseClass):
logger.error(f"Unable to find row {self.row} in row_map.")
sample['Well'] = None
sample['Plate Name'] = self.submission.rsl_plate_num
sample['Positive'] = False
sample['positive'] = False
sample['submitted_date'] = self.submission.submitted_date
return sample

View File

@@ -8,19 +8,16 @@ from PyQt6.QtWidgets import (
)
from PyQt6.QtGui import QAction
from pathlib import Path
from backend.validators import PydReagent
from tools import check_if_app, Settings, Report
from .pop_ups import AlertPop
from .misc import AddReagentForm, LogParser
from .misc import LogParser
import logging, webbrowser, sys
from datetime import date
from .submission_table import SubmissionsSheet
from .submission_widget import SubmissionFormContainer
from .controls_chart import ControlsViewer
from .kit_creator import KitAdder
from .submission_type_creator import SubmissionTypeAdder
logger = logging.getLogger(f'submissions.{__name__}')
logger.info("Hello, I am a logger")
@@ -70,7 +67,7 @@ class App(QMainWindow):
helpMenu.addAction(self.helpAction)
helpMenu.addAction(self.docsAction)
fileMenu.addAction(self.importAction)
fileMenu.addAction(self.importPCRAction)
# fileMenu.addAction(self.importPCRAction)
methodsMenu.addAction(self.searchLog)
reportMenu.addAction(self.generateReportAction)
maintenanceMenu.addAction(self.joinExtractionAction)
@@ -93,7 +90,7 @@ class App(QMainWindow):
"""
logger.debug(f"Creating actions...")
self.importAction = QAction("&Import Submission", self)
self.importPCRAction = QAction("&Import PCR Results", self)
# self.importPCRAction = QAction("&Import PCR Results", self)
self.addReagentAction = QAction("Add Reagent", self)
self.generateReportAction = QAction("Make Report", self)
self.addKitAction = QAction("Import Kit", self)
@@ -110,7 +107,7 @@ class App(QMainWindow):
"""
logger.debug(f"Connecting actions...")
self.importAction.triggered.connect(self.table_widget.formwidget.importSubmission)
self.importPCRAction.triggered.connect(self.table_widget.formwidget.import_pcr_results)
# self.importPCRAction.triggered.connect(self.table_widget.formwidget.import_pcr_results)
self.addReagentAction.triggered.connect(self.table_widget.formwidget.add_reagent)
self.generateReportAction.triggered.connect(self.table_widget.sub_wid.generate_report)
self.joinExtractionAction.triggered.connect(self.table_widget.sub_wid.link_extractions)
@@ -157,8 +154,6 @@ class App(QMainWindow):
self.report = Report()
else:
self.statusBar().showMessage("Action completed sucessfully.", 5000)
def runSearch(self):
dlg = LogParser(self)

View File

@@ -95,10 +95,12 @@ class SubmissionDetails(QDialog):
self.html = self.template.render(sub=self.base_dict, signing_permission=is_power_user())
self.webview.setHtml(self.html)
self.setWindowTitle(f"Submission Details - {submission.rsl_plate_num}")
with open("details.html", "w") as f:
f.write(self.html)
@pyqtSlot(str)
def sign_off(self, submission:str|BasicSubmission):
logger.debug(f"Signing off on {submission}")
logger.debug(f"Signing off on {submission} - ({getuser()})")
if isinstance(submission, str):
submission = BasicSubmission.query(rsl_number=submission)
submission.uploaded_by = getuser()

View File

@@ -112,81 +112,6 @@ class SubmissionFormContainer(QWidget):
logger.debug(f"Outgoing report: {self.report.results}")
logger.debug(f"All attributes of submission container:\n{pformat(self.__dict__)}")
def import_pcr_results(self):
"""
Pull QuantStudio results into db
"""
self.import_pcr_results_function()
self.app.report.add_result(self.report)
self.report = Report()
self.app.result_reporter()
def import_pcr_results_function(self):
"""
Import Quant-studio PCR data to an imported submission
Args:
obj (QMainWindow): original app window
Returns:
Tuple[QMainWindow, dict]: Collection of new main app window and result dict
"""
report = Report()
fname = select_open_file(self, file_extension="xlsx")
parser = PCRParser(filepath=fname)
logger.debug(f"Attempting lookup for {parser.plate_num}")
sub = BasicSubmission.query(rsl_number=parser.plate_num)
try:
logger.debug(f"Found submission: {sub.rsl_plate_num}")
except AttributeError:
# If no plate is found, may be because this is a repeat. Lop off the '-1' or '-2' and repeat
logger.error(f"Submission of number {parser.plate_num} not found. Attempting rescue of plate repeat.")
parser.plate_num = "-".join(parser.plate_num.split("-")[:-1])
sub = BasicSubmission.query(rsl_number=parser.plate_num)
try:
logger.debug(f"Found submission: {sub.rsl_plate_num}")
except AttributeError:
logger.error(f"Rescue of {parser.plate_num} failed.")
self.report.add_result(Result(msg="Couldn't find a submission with that RSL number.", status="Warning"))
return
# Check if PCR info already exists
if hasattr(sub, 'pcr_info') and sub.pcr_info != None:
# existing = json.loads(sub.pcr_info)
existing = sub.pcr_info
else:
existing = None
if existing != None:
# update pcr_info
try:
logger.debug(f"Updating {type(existing)}: {existing} with {type(parser.pcr)}: {parser.pcr}")
# if json.dumps(parser.pcr) not in sub.pcr_info:
if parser.pcr not in sub.pcr_info:
existing.append(parser.pcr)
logger.debug(f"Setting: {existing}")
# sub.pcr_info = json.dumps(existing)
sub.pcr_info = existing
except TypeError:
logger.error(f"Error updating!")
# sub.pcr_info = json.dumps([parser.pcr])
sub.pcr_info = [parser.pcr]
logger.debug(f"Final pcr info for {sub.rsl_plate_num}: {sub.pcr_info}")
else:
# sub.pcr_info = json.dumps([parser.pcr])
sub.pcr_info = [parser.pcr]
logger.debug(f"Existing {type(sub.pcr_info)}: {sub.pcr_info}")
logger.debug(f"Inserting {type(json.dumps(parser.pcr))}: {json.dumps(parser.pcr)}")
sub.save(original=False)
logger.debug(f"Got {len(parser.samples)} samples to update!")
logger.debug(f"Parser samples: {parser.samples}")
for sample in sub.samples:
logger.debug(f"Running update on: {sample}")
try:
sample_dict = [item for item in parser.samples if item['sample']==sample.rsl_number][0]
except IndexError:
continue
sub.update_subsampassoc(sample=sample, input_dict=sample_dict)
self.report.add_result(Result(msg=f"We added PCR info to {sub.rsl_plate_num}.", status='Information'))
def add_reagent(self, reagent_lot:str|None=None, reagent_type:str|None=None, expiry:date|None=None, name:str|None=None):
"""
Action to create new reagent in DB.