Removed logger.debugs for proven functions.

This commit is contained in:
lwark
2024-12-12 12:17:21 -06:00
parent b174eb1221
commit 67520cb784
32 changed files with 80 additions and 758 deletions

View File

@@ -41,7 +41,6 @@ class CustomFigure(Figure):
"""
if modes:
ytitle = modes[0]
# logger.debug("Creating visibles list for each mode.")
self.update_layout(
xaxis_title="Submitted Date (* - Date parsed from fastq file creation date)",
yaxis_title=ytitle,
@@ -79,7 +78,6 @@ class CustomFigure(Figure):
rng = [1]
if months > 2:
rng += [iii for iii in range(3, months, 3)]
# logger.debug(f"Making buttons for months: {rng}")
buttons = [dict(count=iii, label=f"{iii}m", step="month", stepmode="backward") for iii in rng]
if months > date.today().month:
buttons += [dict(count=1, label="YTD", step="year", stepmode="todate")]
@@ -117,24 +115,6 @@ class CustomFigure(Figure):
{"yaxis.title.text": mode},
])
# def save_figure(self, group_name: str = "plotly_output", parent: QWidget | None = None):
# """
# Writes plotly figure to html file.
#
# Args:
# figs ():
# settings (dict): settings passed down from click
# fig (Figure): input figure object
# group_name (str): controltype
# """
#
# output = select_save_file(obj=parent, default_name=group_name, extension="png")
# self.write_image(output.absolute().__str__(), engine="kaleido")
#
# def save_data(self, group_name: str = "plotly_export", parent:QWidget|None=None):
# output = select_save_file(obj=parent, default_name=group_name, extension="xlsx")
# self.df.to_excel(output.absolute().__str__(), engine="openpyxl", index=False)
def to_html(self) -> str:
"""
Creates final html code from plotly

View File

@@ -3,13 +3,12 @@ Functions for constructing irida controls graphs using plotly.
"""
from datetime import date
from pprint import pformat
from typing import Generator
import plotly.express as px
import pandas as pd
from PyQt6.QtWidgets import QWidget
from . import CustomFigure
import logging
from tools import get_unique_values_in_df_column, divide_chunks
from tools import get_unique_values_in_df_column
logger = logging.getLogger(f"submissions.{__name__}")

View File

@@ -21,11 +21,9 @@ class PCRFigure(CustomFigure):
months = int(settings['months'])
except KeyError:
months = 6
# logger.debug(f"DF: {self.df}")
self.construct_chart(df=df)
def construct_chart(self, df: pd.DataFrame):
# logger.debug(f"PCR df:\n {df}")
try:
scatter = px.scatter(data_frame=df, x='submitted_date', y="ct",
hover_data=["name", "target", "ct", "reagent_lot"],

View File

@@ -23,7 +23,6 @@ class TurnaroundChart(CustomFigure):
months = int(settings['months'])
except KeyError:
months = 6
# logger.debug(f"DF: {self.df}")
self.construct_chart()
if threshold:
self.add_hline(y=threshold)
@@ -32,11 +31,9 @@ class TurnaroundChart(CustomFigure):
def construct_chart(self, df: pd.DataFrame | None = None):
if df:
self.df = df
# logger.debug(f"PCR df:\n {df}")
self.df = self.df[self.df.days.notnull()]
self.df = self.df.sort_values(['submitted_date', 'name'], ascending=[True, True]).reset_index(drop=True)
self.df = self.df.reset_index().rename(columns={"index": "idx"})
# logger.debug(f"DF: {self.df}")
try:
scatter = px.scatter(data_frame=self.df, x='idx', y="days",
hover_data=["name", "submitted_date", "completed_date", "days"],

View File

@@ -27,13 +27,11 @@ from .turnaround import TurnaroundTime
from .omni_search import SearchBox
logger = logging.getLogger(f'submissions.{__name__}')
# logger.info("Hello, I am a logger")
class App(QMainWindow):
def __init__(self, ctx: Settings = None):
# logger.debug(f"Initializing main window...")
super().__init__()
qInstallMessageHandler(lambda x, y, z: None)
self.ctx = ctx
@@ -68,7 +66,6 @@ class App(QMainWindow):
"""
adds items to menu bar
"""
# logger.debug(f"Creating menu bar...")
menuBar = self.menuBar()
fileMenu = menuBar.addMenu("&File")
editMenu = menuBar.addMenu("&Edit")
@@ -82,7 +79,6 @@ class App(QMainWindow):
fileMenu.addAction(self.importAction)
fileMenu.addAction(self.yamlExportAction)
fileMenu.addAction(self.yamlImportAction)
# methodsMenu.addAction(self.searchLog)
methodsMenu.addAction(self.searchSample)
maintenanceMenu.addAction(self.joinExtractionAction)
maintenanceMenu.addAction(self.joinPCRAction)
@@ -92,27 +88,20 @@ class App(QMainWindow):
"""
adds items to toolbar
"""
# logger.debug(f"Creating toolbar...")
toolbar = QToolBar("My main toolbar")
self.addToolBar(toolbar)
toolbar.addAction(self.addReagentAction)
# toolbar.addAction(self.addKitAction)
# toolbar.addAction(self.addOrgAction)
def _createActions(self):
"""
creates actions
"""
# logger.debug(f"Creating actions...")
self.importAction = QAction("&Import Submission", self)
self.addReagentAction = QAction("Add Reagent", self)
# self.addKitAction = QAction("Import Kit", self)
# self.addOrgAction = QAction("Import Org", self)
self.joinExtractionAction = QAction("Link Extraction Logs")
self.joinPCRAction = QAction("Link PCR Logs")
self.helpAction = QAction("&About", self)
self.docsAction = QAction("&Docs", self)
# self.searchLog = QAction("Search Log", self)
self.searchSample = QAction("Search Sample", self)
self.githubAction = QAction("Github", self)
self.yamlExportAction = QAction("Export Type Example", self)
@@ -123,14 +112,12 @@ class App(QMainWindow):
"""
connect menu and tool bar item to functions
"""
# logger.debug(f"Connecting actions...")
self.importAction.triggered.connect(self.table_widget.formwidget.importSubmission)
self.addReagentAction.triggered.connect(self.table_widget.formwidget.add_reagent)
self.joinExtractionAction.triggered.connect(self.table_widget.sub_wid.link_extractions)
self.joinPCRAction.triggered.connect(self.table_widget.sub_wid.link_pcr)
self.helpAction.triggered.connect(self.showAbout)
self.docsAction.triggered.connect(self.openDocs)
# self.searchLog.triggered.connect(self.runSearch)
self.searchSample.triggered.connect(self.runSampleSearch)
self.githubAction.triggered.connect(self.openGithub)
self.yamlExportAction.triggered.connect(self.export_ST_yaml)
@@ -145,7 +132,6 @@ class App(QMainWindow):
j_env = jinja_template_loading()
template = j_env.get_template("project.html")
html = template.render(info=self.ctx.package.__dict__)
# logger.debug(html)
about = HTMLPop(html=html, title="About")
about.exec()
@@ -157,7 +143,6 @@ class App(QMainWindow):
url = Path(sys._MEIPASS).joinpath("files", "docs", "index.html")
else:
url = Path("docs\\build\\index.html").absolute()
# logger.debug(f"Attempting to open {url}")
webbrowser.get('windows-default').open(f"file://{url.__str__()}")
def openGithub(self):
@@ -177,10 +162,6 @@ class App(QMainWindow):
instr = HTMLPop(html=html, title="Instructions")
instr.exec()
# def runSearch(self):
# dlg = LogParser(self)
# dlg.exec()
def runSampleSearch(self):
"""
Create a search for samples.
@@ -253,7 +234,6 @@ class App(QMainWindow):
class AddSubForm(QWidget):
def __init__(self, parent: QWidget):
# logger.debug(f"Initializating subform...")
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)
# NOTE: Initialize tab screen

View File

@@ -6,7 +6,6 @@ from PyQt6.QtWidgets import (
QWidget, QComboBox, QPushButton
)
from PyQt6.QtCore import QSignalBlocker
from backend import ChartReportMaker
from backend.db import ControlType, IridaControl
import logging
@@ -21,12 +20,9 @@ class ControlsViewer(InfoPane):
def __init__(self, parent: QWidget, archetype: str) -> None:
super().__init__(parent)
logger.debug(f"Incoming Archetype: {archetype}")
self.archetype = ControlType.query(name=archetype)
if not self.archetype:
return
logger.debug(f"Archetype set as: {self.archetype}")
# logger.debug(f"\n\n{self.app}\n\n")
# NOTE: set tab2 layout
self.control_sub_typer = QComboBox()
# NOTE: fetch types of controls
@@ -54,12 +50,6 @@ class ControlsViewer(InfoPane):
self.save_button.pressed.connect(self.save_png)
self.export_button.pressed.connect(self.save_excel)
# def save_chart_function(self):
# self.fig.save_figure(parent=self)
#
# def save_data_function(self):
# self.fig.save_data(parent=self)
@report_result
def update_data(self, *args, **kwargs):
"""
@@ -71,20 +61,6 @@ class ControlsViewer(InfoPane):
self.mode_sub_typer.disconnect()
except TypeError:
pass
# NOTE: correct start date being more recent than end date and rerun
# if self.datepicker.start_date.date() > self.datepicker.end_date.date():
# threemonthsago = self.datepicker.end_date.date().addDays(-60)
# msg = f"Start date after end date is not allowed! Setting to {threemonthsago.toString()}."
# logger.warning(msg)
# # NOTE: block signal that will rerun controls getter and set start date Without triggering this function again
# with QSignalBlocker(self.datepicker.start_date) as blocker:
# self.datepicker.start_date.setDate(threemonthsago)
# self.update_data()
# report.add_result(Result(owner=self.__str__(), msg=msg, status="Warning"))
# return report
# # NOTE: convert to python useable date objects
# self.start_date = self.datepicker.start_date.date().toPyDate()
# self.end_date = self.datepicker.end_date.date().toPyDate()
self.con_sub_type = self.control_sub_typer.currentText()
self.mode = self.mode_typer.currentText()
self.mode_sub_typer.clear()
@@ -104,7 +80,6 @@ class ControlsViewer(InfoPane):
self.mode_sub_typer.clear()
self.mode_sub_typer.setEnabled(False)
self.chart_maker_function()
# return report
@report_result
def chart_maker_function(self, *args, **kwargs):
@@ -119,14 +94,11 @@ class ControlsViewer(InfoPane):
Tuple[QMainWindow, dict]: Collection of new main app window and result dict
"""
report = Report()
# logger.debug(f"Control getter context: \n\tControl type: {self.con_sub_type}\n\tMode: {self.mode}\n\tStart \
# Date: {self.start_date}\n\tEnd Date: {self.end_date}")
# NOTE: set the mode_sub_type for kraken
if self.mode_sub_typer.currentText() == "":
self.mode_sub_type = None
else:
self.mode_sub_type = self.mode_sub_typer.currentText()
logger.debug(f"Subtype: {self.mode_sub_type}")
months = self.diff_month(self.start_date, self.end_date)
# NOTE: query all controls using the type/start and end dates from the gui
chart_settings = dict(sub_type=self.con_sub_type, start_date=self.start_date, end_date=self.end_date,
@@ -136,14 +108,11 @@ class ControlsViewer(InfoPane):
self.report_obj = ChartReportMaker(df=self.fig.df, sheet_name=self.archetype.name)
if issubclass(self.fig.__class__, CustomFigure):
self.save_button.setEnabled(True)
# logger.debug(f"Updating figure...")
# NOTE: construct html for webview
try:
html = self.fig.to_html()
except AttributeError:
html = ""
# logger.debug(f"The length of html code is: {len(html)}")
self.webview.setHtml(html)
self.webview.update()
# logger.debug("Figure updated... I hope.")
return report

View File

@@ -21,9 +21,7 @@ class EquipmentUsage(QDialog):
self.setWindowTitle(f"Equipment Checklist - {submission.rsl_plate_num}")
self.used_equipment = self.submission.get_used_equipment()
self.kit = self.submission.extraction_kit
# logger.debug(f"Existing equipment: {self.used_equipment}")
self.opt_equipment = submission.submission_type.get_equipment()
# logger.debug(f"EquipmentRoles: {self.opt_equipment}")
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.populate_form()
@@ -38,7 +36,6 @@ class EquipmentUsage(QDialog):
self.buttonBox.rejected.connect(self.reject)
label = self.LabelRow(parent=self)
self.layout.addWidget(label)
# logger.debug("Creating widgets for equipment")
for eq in self.opt_equipment:
widg = eq.to_form(parent=self, used=self.used_equipment)
self.layout.addWidget(widg)
@@ -124,9 +121,7 @@ class RoleComboBox(QWidget):
Changes processes when equipment is changed
"""
equip = self.box.currentText()
# logger.debug(f"Updating equipment: {equip}")
equip2 = next((item for item in self.role.equipment if item.name == equip), self.role.equipment[0])
# logger.debug(f"Using: {equip2}")
with QSignalBlocker(self.process) as blocker:
self.process.clear()
self.process.addItems([item for item in equip2.processes if item in self.role.processes])
@@ -136,7 +131,6 @@ class RoleComboBox(QWidget):
Changes what tips are available when process is changed
"""
process = self.process.currentText().strip()
# logger.debug(f"Checking process: {process} for equipment {self.role.name}")
process = Process.query(name=process)
if process.tip_roles:
for iii, tip_role in enumerate(process.tip_roles):
@@ -144,7 +138,6 @@ class RoleComboBox(QWidget):
tip_choices = [item.name for item in tip_role.instances]
widget.setEditable(False)
widget.addItems(tip_choices)
# logger.debug(f"Tiprole: {tip_role.__dict__}")
widget.setObjectName(f"tips_{tip_role.name}")
widget.setMinimumWidth(200)
widget.setMaximumWidth(200)
@@ -169,7 +162,6 @@ class RoleComboBox(QWidget):
eq = Equipment.query(name=self.box.currentText())
tips = [PydTips(name=item.currentText(), role=item.objectName().lstrip("tips").lstrip("_")) for item in
self.findChildren(QComboBox) if item.objectName().startswith("tips")]
# logger.debug(tips)
try:
return PydEquipment(
name=eq.name,

View File

@@ -148,5 +148,4 @@ class ControlsForm(QWidget):
dicto['values'].append(dict(name=label[1], value=le.currentText()))
if label[0] not in [item['name'] for item in output]:
output.append(dicto)
# logger.debug(pformat(output))
return output, self.comment_field.toPlainText()

View File

@@ -18,7 +18,6 @@ class InfoPane(QWidget):
def __init__(self, parent: QWidget) -> None:
super().__init__(parent)
self.app = self.parent().parent()
# logger.debug(f"\n\n{self.app}\n\n")
self.report = Report()
self.datepicker = StartEndDatePicker(default_start=-180)
self.webview = QWebEngineView()
@@ -75,4 +74,4 @@ class InfoPane(QWidget):
fname = select_save_file(obj=self,
default_name=f"Plotly {self.start_date.strftime('%Y%m%d')} - {self.end_date.strftime('%Y%m%d')}",
extension="png")
self.fig.write_image(fname.absolute().__str__(), engine="kaleido")
self.fig.write_image(fname.absolute().__str__(), engine="kaleido")

View File

@@ -1,6 +1,6 @@
'''
"""
Contains miscellaneous widgets for frontend functions
'''
"""
import math
from datetime import date
from PyQt6.QtGui import QPageLayout, QPageSize, QStandardItem, QIcon
@@ -8,7 +8,7 @@ from PyQt6.QtWebEngineWidgets import QWebEngineView
from PyQt6.QtWidgets import (
QLabel, QVBoxLayout,
QLineEdit, QComboBox, QDialog,
QDialogButtonBox, QDateEdit, QPushButton, QFormLayout, QWidget, QHBoxLayout, QSizePolicy
QDialogButtonBox, QDateEdit, QPushButton, QWidget, QHBoxLayout, QSizePolicy
)
from PyQt6.QtCore import Qt, QDate, QSize, QMarginsF
from tools import jinja_template_loading
@@ -66,7 +66,6 @@ class AddReagentForm(QDialog):
self.type_input.addItems([item.name for item in ReagentRole.query() if kit in item.kit_types])
else:
self.type_input.addItems([item.name for item in ReagentRole.query()])
# logger.debug(f"Trying to find index of {reagent_type}")
# NOTE: convert input to user-friendly string?
try:
reagent_role = reagent_role.replace("_", " ").title()
@@ -106,7 +105,6 @@ class AddReagentForm(QDialog):
"""
Updates reagent names form field with examples from reagent type
"""
# logger.debug(self.type_input.currentText())
self.name_input.clear()
lookup = Reagent.query(role=self.type_input.currentText())
self.name_input.addItems(list(set([item.name for item in lookup])))
@@ -145,7 +143,8 @@ def save_pdf(obj: QWebEngineView, filename: Path):
obj.page().printToPdf(filename.absolute().__str__(), page_layout)
# subclass
# NOTE: subclass
class CheckableComboBox(QComboBox):
# once there is a checkState set, it is rendered
# here we assume default Unchecked
@@ -162,7 +161,6 @@ class CheckableComboBox(QComboBox):
return item.checkState() == Qt.CheckState.Checked
def changed(self):
logger.debug("emitting updated")
self.updated.emit()

View File

@@ -1,6 +1,6 @@
'''
"""
Search box that performs fuzzy search for samples
'''
"""
from pprint import pformat
from typing import Tuple, Any, List
from pandas import DataFrame
@@ -39,7 +39,6 @@ class SearchBox(QDialog):
else:
self.sub_class = None
self.results = SearchResults(parent=self, object_type=self.object_type, extras=self.extras, **kwargs)
# logger.debug(f"results: {self.results}")
self.layout.addWidget(self.results, 5, 0)
self.setLayout(self.layout)
self.setWindowTitle(f"Search {self.object_type.__name__}")
@@ -51,7 +50,6 @@ class SearchBox(QDialog):
Changes form inputs based on sample type
"""
deletes = [item for item in self.findChildren(FieldSearch)]
# logger.debug(deletes)
for item in deletes:
item.setParent(None)
# NOTE: Handle any subclasses
@@ -62,7 +60,6 @@ class SearchBox(QDialog):
self.object_type = self.original_type
else:
self.object_type = self.original_type.find_regular_subclass(self.sub_class.currentText())
logger.debug(f"{self.object_type} searchables: {self.object_type.searchables}")
for iii, searchable in enumerate(self.object_type.searchables):
widget = FieldSearch(parent=self, label=searchable, field_name=searchable)
widget.setObjectName(searchable)
@@ -85,10 +82,9 @@ class SearchBox(QDialog):
Shows dataframe of relevant samples.
"""
fields = self.parse_form()
# logger.debug(f"Got fields: {fields}")
sample_list_creator = self.object_type.fuzzy_search(**fields)
data = self.object_type.results_to_df(objects=sample_list_creator)
# Setting results moved to here from __init__ 202411118
# NOTE: Setting results moved to here from __init__ 202411118
self.results.setData(df=data)
@@ -154,7 +150,6 @@ class SearchResults(QTableView):
def parse_row(self, x):
context = {item['name']: x.sibling(x.row(), item['column']).data() for item in self.columns_of_interest}
logger.debug(f"Context: {context}")
try:
object = self.object_type.query(**context)
except KeyError:

View File

@@ -9,7 +9,7 @@ from PyQt6.QtWebEngineWidgets import QWebEngineView
from tools import jinja_template_loading
import logging
from backend.db import models
from typing import Any, Literal
from typing import Literal
logger = logging.getLogger(f"submissions.{__name__}")

View File

@@ -45,7 +45,6 @@ class SubmissionDetails(QDialog):
self.btn.clicked.connect(self.save_pdf)
self.back = QPushButton("Back")
self.back.setFixedWidth(100)
# self.back.clicked.connect(self.back_function)
self.back.clicked.connect(self.webview.back)
self.layout.addWidget(self.back, 0, 0, 1, 1)
self.layout.addWidget(self.btn, 0, 1, 1, 9)
@@ -70,7 +69,6 @@ class SubmissionDetails(QDialog):
if "Submission" in title:
self.btn.setEnabled(True)
self.export_plate = title.split(" ")[-1]
# logger.debug(f"Updating export plate to: {self.export_plate}")
else:
self.btn.setEnabled(False)
try:
@@ -78,7 +76,6 @@ class SubmissionDetails(QDialog):
except IndexError as e:
check = title
if title == check:
# logger.debug("Disabling back button")
self.back.setEnabled(False)
else:
self.back.setEnabled(True)
@@ -91,7 +88,6 @@ class SubmissionDetails(QDialog):
Args:
sample (str): Submitter Id of the sample.
"""
# logger.debug(f"Details: {sample}")
if isinstance(sample, str):
sample = BasicSample.query(submitter_id=sample)
base_dict = sample.to_sub_dict(full_data=True)
@@ -114,7 +110,6 @@ class SubmissionDetails(QDialog):
base_dict = reagent.to_sub_dict(extraction_kit=self.kit, full_data=True)
env = jinja_template_loading()
temp_name = "reagent_details.html"
# logger.debug(f"Returning template: {temp_name}")
try:
template = env.get_template(temp_name)
except TemplateNotFound as e:
@@ -147,29 +142,23 @@ class SubmissionDetails(QDialog):
Args:
submission (str | BasicSubmission): Submission of interest.
"""
# logger.debug(f"Details for: {submission}")
if isinstance(submission, str):
submission = BasicSubmission.query(rsl_plate_num=submission)
self.rsl_plate_num = submission.rsl_plate_num
self.base_dict = submission.to_dict(full_data=True)
# logger.debug(f"Submission details data:\n{pformat({k:v for k,v in self.base_dict.items() if k == 'reagents'})}")
# NOTE: don't want id
# logger.debug(f"Creating barcode.")
# logger.debug(f"Making platemap...")
self.base_dict['platemap'] = submission.make_plate_map(sample_list=submission.hitpick_plate())
self.base_dict['excluded'] = submission.get_default_info("details_ignore")
self.base_dict, self.template = submission.get_details_template(base_dict=self.base_dict)
template_path = Path(self.template.environment.loader.__getattribute__("searchpath")[0])
with open(template_path.joinpath("css", "styles.css"), "r") as f:
css = f.read()
# logger.debug(f"Submission_details: {pformat(self.base_dict)}")
# logger.debug(f"User is power user: {is_power_user()}")
self.html = self.template.render(sub=self.base_dict, permission=is_power_user(), css=css)
self.webview.setHtml(self.html)
@pyqtSlot(str)
def sign_off(self, submission: str | BasicSubmission):
logger.debug(f"Signing off on {submission} - ({getuser()})")
logger.info(f"Signing off on {submission} - ({getuser()})")
if isinstance(submission, str):
submission = BasicSubmission.query(rsl_plate_num=submission)
submission.signed_by = getuser()
@@ -195,7 +184,6 @@ class SubmissionComment(QDialog):
super().__init__(parent)
try:
self.app = parent.parent().parent().parent().parent().parent().parent
# logger.debug(f"App: {self.app}")
except AttributeError:
pass
self.submission = submission
@@ -225,5 +213,4 @@ class SubmissionComment(QDialog):
return None
dt = datetime.strftime(datetime.now(), "%Y-%m-%d %H:%M:%S")
full_comment = {"name": commenter, "time": dt, "text": comment}
# logger.debug(f"Full comment: {full_comment}")
return full_comment

View File

@@ -1,6 +1,6 @@
'''
"""
Contains widgets specific to the submission summary and submission details.
'''
"""
import logging
from pprint import pformat
from PyQt6.QtWidgets import QTableView, QMenu
@@ -107,20 +107,16 @@ class SubmissionsSheet(QTableView):
Args:
event (_type_): the item of interest
"""
# logger.debug(event.__dict__)
id = self.selectionModel().currentIndex()
id = id.sibling(id.row(), 0).data()
submission = BasicSubmission.query(id=id)
# logger.debug(f"Event submission: {submission}")
self.menu = QMenu(self)
self.con_actions = submission.custom_context_events()
# logger.debug(f"Menu options: {self.con_actions}")
for k in self.con_actions.keys():
# logger.debug(f"Adding {k}")
action = QAction(k, self)
action.triggered.connect(lambda _, action_name=k: self.triggered_action(action_name=action_name))
self.menu.addAction(action)
# add other required actions
# NOTE: add other required actions
self.menu.popup(QCursor.pos())
def triggered_action(self, action_name: str):
@@ -130,8 +126,6 @@ class SubmissionsSheet(QTableView):
Args:
action_name (str): name of the action from the menu
"""
# logger.debug(f"Action: {action_name}")
# logger.debug(f"Responding with {self.con_actions[action_name]}")
func = self.con_actions[action_name]
func(obj=self)
@@ -179,7 +173,6 @@ class SubmissionsSheet(QTableView):
if sub is None:
continue
try:
# logger.debug(f"Found submission: {sub.rsl_plate_num}")
count += 1
except AttributeError:
continue

View File

@@ -1,9 +1,9 @@
'''
"""
Contains all submission related frontend functions
'''
"""
from PyQt6.QtWidgets import (
QWidget, QPushButton, QVBoxLayout,
QComboBox, QDateEdit, QLineEdit, QLabel, QCheckBox, QBoxLayout, QHBoxLayout, QGridLayout
QComboBox, QDateEdit, QLineEdit, QLabel, QCheckBox, QHBoxLayout, QGridLayout
)
from PyQt6.QtCore import pyqtSignal, Qt, QSignalBlocker
from . import select_open_file, select_save_file
@@ -34,7 +34,6 @@ class MyQComboBox(QComboBox):
super(MyQComboBox, self).__init__(*args, **kwargs)
self.scrollWidget = scrollWidget
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
logger.debug(f"Scrollwidget: {scrollWidget}")
def wheelEvent(self, *args, **kwargs):
if self.hasFocus():
@@ -61,14 +60,12 @@ class MyQDateEdit(QDateEdit):
class SubmissionFormContainer(QWidget):
# A signal carrying a path
# NOTE: A signal carrying a path
import_drag = pyqtSignal(Path)
def __init__(self, parent: QWidget) -> None:
# logger.debug(f"Setting form widget...")
super().__init__(parent)
self.app = self.parent().parent()
# logger.debug(f"App: {self.app}")
self.report = Report()
self.setStyleSheet('background-color: light grey;')
self.setAcceptDrops(True)
@@ -89,7 +86,6 @@ class SubmissionFormContainer(QWidget):
Sets filename when file dropped
"""
fname = Path([u.toLocalFile() for u in event.mimeData().urls()][0])
# logger.debug(f"App: {self.app}")
self.app.last_dir = fname.parent
self.import_drag.emit(fname)
@@ -127,7 +123,6 @@ class SubmissionFormContainer(QWidget):
# NOTE: set file dialog
if isinstance(fname, bool) or fname is None:
fname = select_open_file(self, file_extension="xlsx")
# logger.debug(f"Attempting to parse file: {fname}")
if not fname:
report.add_result(Result(msg=f"File {fname.__str__()} not found.", status="critical"))
return report
@@ -139,14 +134,10 @@ class SubmissionFormContainer(QWidget):
return
except AttributeError:
self.prsr = SheetParser(filepath=fname)
# logger.debug(f"Submission dictionary:\n{pformat(self.prsr.sub)}")
self.pyd = self.prsr.to_pydantic()
# logger.debug(f"Pydantic result: \n\n{pformat(self.pyd)}\n\n")
self.form = self.pyd.to_form(parent=self)
self.layout().addWidget(self.form)
return report
# logger.debug(f"Outgoing report: {self.report.results}")
# logger.debug(f"All attributes of submission container:\n{pformat(self.__dict__)}")
@report_result
def add_reagent(self, reagent_lot: str | None = None, reagent_role: str | None = None, expiry: date | None = None,
@@ -172,14 +163,12 @@ class SubmissionFormContainer(QWidget):
if dlg.exec():
# NOTE: extract form info
info = dlg.parse_form()
# logger.debug(f"Reagent info: {info}")
# NOTE: create reagent object
reagent = PydReagent(ctx=self.app.ctx, **info, missing=False)
# NOTE: send reagent to db
sqlobj, result = reagent.toSQL()
sqlobj.save()
report.add_result(result)
# logger.debug(f"Reagent: {reagent}, Report: {report}")
return reagent, report
@@ -189,7 +178,6 @@ class SubmissionFormWidget(QWidget):
def __init__(self, parent: QWidget, submission: PydSubmission, disable: list | None = None) -> None:
super().__init__(parent)
# logger.debug(f"Disable: {disable}")
if disable is None:
disable = []
self.app = parent.app
@@ -200,17 +188,13 @@ class SubmissionFormWidget(QWidget):
defaults = st.get_default_info("form_recover", "form_ignore", submission_type=self.pyd.submission_type['value'])
self.recover = defaults['form_recover']
self.ignore = defaults['form_ignore']
# logger.debug(f"Attempting to extend ignore list with {self.pyd.submission_type['value']}")
self.layout = QVBoxLayout()
for k in list(self.pyd.model_fields.keys()) + list(self.pyd.model_extra.keys()):
# logger.debug(f"Creating widget: {k}")
if k in self.ignore:
logger.warning(f"{k} in form_ignore {self.ignore}, not creating widget")
continue
try:
# logger.debug(f"Key: {k}, Disable: {disable}")
check = k in disable
# logger.debug(f"Check: {check}")
except TypeError:
check = False
try:
@@ -225,7 +209,6 @@ class SubmissionFormWidget(QWidget):
sub_obj=st, disable=check)
if add_widget is not None:
self.layout.addWidget(add_widget)
# if k == "extraction_kit":
if k in self.__class__.update_reagent_fields:
add_widget.input.currentTextChanged.connect(self.scrape_reagents)
self.disabler = self.DisableReagents(self)
@@ -236,15 +219,10 @@ class SubmissionFormWidget(QWidget):
self.scrape_reagents(self.extraction_kit)
def disable_reagents(self):
"""
Disables all ReagentFormWidgets in this form/
"""
for reagent in self.findChildren(self.ReagentFormWidget):
# if self.disabler.checkbox.isChecked():
# # reagent.setVisible(True)
# # with QSignalBlocker(self.disabler.checkbox) as b:
# reagent.flip_check()
# else:
# # reagent.setVisible(False)
# # with QSignalBlocker(self.disabler.checkbox) as b:
# reagent.check.setChecked(False)
reagent.flip_check(self.disabler.checkbox.isChecked())
@@ -263,7 +241,6 @@ class SubmissionFormWidget(QWidget):
Returns:
self.InfoItem: Form widget to hold name:value
"""
# logger.debug(f"Key: {key}, Disable: {disable}")
if isinstance(submission_type, str):
submission_type = SubmissionType.query(name=submission_type)
if key not in self.ignore:
@@ -276,7 +253,6 @@ class SubmissionFormWidget(QWidget):
case _:
widget = self.InfoItem(parent=self, key=key, value=value, submission_type=submission_type,
sub_obj=sub_obj)
# logger.debug(f"Setting widget enabled to: {not disable}")
if disable:
widget.input.setEnabled(False)
widget.input.setToolTip("Widget disabled to protect database integrity.")
@@ -298,24 +274,20 @@ class SubmissionFormWidget(QWidget):
"""
self.extraction_kit = args[0]
report = Report()
logger.debug(f"Extraction kit: {self.extraction_kit}")
# NOTE: Remove previous reagent widgets
try:
old_reagents = self.find_widgets()
except AttributeError:
logger.error(f"Couldn't find old reagents.")
old_reagents = []
# logger.debug(f"\n\nAttempting to clear: {old_reagents}\n\n")
for reagent in old_reagents:
if isinstance(reagent, self.ReagentFormWidget) or isinstance(reagent, QPushButton):
reagent.setParent(None)
reagents, integrity_report = self.pyd.check_kit_integrity(extraction_kit=self.extraction_kit)
# logger.debug(f"Got reagents: {pformat(reagents)}")
for reagent in reagents:
add_widget = self.ReagentFormWidget(parent=self, reagent=reagent, extraction_kit=self.extraction_kit)
self.layout.addWidget(add_widget)
report.add_result(integrity_report)
# logger.debug(f"Outgoing report: {report.results}")
if hasattr(self.pyd, "csv"):
export_csv_btn = QPushButton("Export CSV")
export_csv_btn.setObjectName("export_csv_btn")
@@ -326,6 +298,7 @@ class SubmissionFormWidget(QWidget):
self.layout.addWidget(submit_btn)
submit_btn.clicked.connect(self.submit_new_sample_function)
self.setLayout(self.layout)
self.disabler.checkbox.setChecked(True)
return report
def clear_form(self):
@@ -365,23 +338,16 @@ class SubmissionFormWidget(QWidget):
report = Report()
result = self.parse_form()
report.add_result(result)
# logger.debug(f"Submission: {pformat(self.pyd)}")
# logger.debug("Checking kit integrity...")
if self.disabler.checkbox.isChecked():
_, result = self.pyd.check_kit_integrity()
report.add_result(result)
if len(result.results) > 0:
return
# logger.debug(f"PYD before transformation into SQL:\n\n{self.pyd}\n\n")
base_submission, result = self.pyd.to_sql()
# logger.debug(f"SQL object: {pformat(base_submission.__dict__)}")
# logger.debug(f"Base submission: {base_submission.to_dict()}")
# NOTE: check output message for issues
# logger.debug(f"Result of to_sql: {result}")
try:
trigger = result.results[-1]
code = trigger.code
# logger.debug(f"Code from return: {code}")
except IndexError as e:
logger.error(result.results)
logger.error(f"Problem getting error code: {e}")
@@ -408,11 +374,8 @@ class SubmissionFormWidget(QWidget):
pass
# NOTE: add reagents to submission object
for reagent in base_submission.reagents:
# logger.debug(f"Updating: {reagent} with {reagent.lot}")
reagent.update_last_used(kit=base_submission.extraction_kit)
# logger.debug(f"Final reagents: {pformat(base_submission.reagents)}")
save_output = base_submission.save()
# logger.debug(f"Save output: {save_output}")
# NOTE: update summary sheet
self.app.table_widget.sub_wid.setData()
# NOTE: reset form
@@ -423,7 +386,6 @@ class SubmissionFormWidget(QWidget):
check = True
if check:
self.setParent(None)
# logger.debug(f"All attributes of obj: {pformat(self.__dict__)}")
return report
def export_csv_function(self, fname: Path | None = None):
@@ -454,7 +416,6 @@ class SubmissionFormWidget(QWidget):
info = {}
reagents = []
for widget in self.findChildren(QWidget):
# logger.debug(f"Parsed widget of type {type(widget)}")
match widget:
case self.ReagentFormWidget():
reagent, _ = widget.parse_form()
@@ -464,16 +425,10 @@ class SubmissionFormWidget(QWidget):
field, value = widget.parse_form()
if field is not None:
info[field] = value
# logger.debug(f"Info: {pformat(info)}")
logger.debug(f"Reagents going into pyd: {pformat(reagents)}")
self.pyd.reagents = reagents
logger.debug(f"Reagents after insertion in pyd: {pformat(self.pyd.reagents)}")
# logger.debug(f"Attrs not in info: {[k for k, v in self.__dict__.items() if k not in info.keys()]}")
for item in self.recover:
# logger.debug(f"Attempting to recover: {item}")
if hasattr(self, item):
value = getattr(self, item)
# logger.debug(f"Setting {item}")
info[item] = value
for k, v in info.items():
self.pyd.set_attribute(key=k, value=v)
@@ -551,9 +506,6 @@ class SubmissionFormWidget(QWidget):
except (TypeError, KeyError):
pass
obj = parent.parent().parent()
# logger.debug(f"Object: {obj}")
# logger.debug(f"Parent: {parent.parent()}")
# logger.debug(f"Creating widget for: {key}")
match key:
case 'submitting_lab':
add_widget = MyQComboBox(scrollWidget=parent)
@@ -567,7 +519,6 @@ class SubmissionFormWidget(QWidget):
looked_up_lab = Organization.query(name=value, limit=1)
except AttributeError:
looked_up_lab = None
# logger.debug(f"\n\nLooked up lab: {looked_up_lab}")
if looked_up_lab:
try:
labs.remove(str(looked_up_lab.name))
@@ -586,12 +537,9 @@ class SubmissionFormWidget(QWidget):
# NOTE: create combobox to hold looked up kits
add_widget = MyQComboBox(scrollWidget=parent)
# NOTE: lookup existing kits by 'submission_type' decided on by sheetparser
# logger.debug(f"Looking up kits used for {submission_type}")
uses = [item.name for item in submission_type.kit_types]
obj.uses = uses
# logger.debug(f"Kits received for {submission_type}: {uses}")
if check_not_nan(value):
# logger.debug(f"The extraction kit in parser was: {value}")
try:
uses.insert(0, uses.pop(uses.index(value)))
except ValueError:
@@ -626,7 +574,6 @@ class SubmissionFormWidget(QWidget):
else:
# NOTE: anything else gets added in as a line edit
add_widget = QLineEdit()
# logger.debug(f"Setting widget text to {str(value).replace('_', ' ')}")
add_widget.setText(str(value).replace("_", " "))
add_widget.setToolTip(f"Enter value for {key}")
if add_widget is not None:
@@ -725,7 +672,6 @@ class SubmissionFormWidget(QWidget):
if not self.lot.isEnabled():
return None, report
lot = self.lot.currentText()
# logger.debug(f"Using this lot for the reagent {self.reagent}: {lot}")
wanted_reagent = Reagent.query(lot=lot, role=self.reagent.role)
# NOTE: if reagent doesn't exist in database, offer to add it (uses App.add_reagent)
if wanted_reagent is None:
@@ -741,7 +687,6 @@ class SubmissionFormWidget(QWidget):
return wanted_reagent, report
else:
# NOTE: In this case we will have an empty reagent and the submission will fail kit integrity check
# logger.debug("Will not add reagent.")
report.add_result(Result(msg="Failed integrity check", status="Critical"))
return None, report
else:
@@ -791,7 +736,6 @@ class SubmissionFormWidget(QWidget):
looked_up_rt = KitTypeReagentRoleAssociation.query(reagent_role=reagent.role,
kit_type=extraction_kit)
relevant_reagents = [str(item.lot) for item in looked_up_rt.get_all_relevant_reagents()]
logger.debug(f"Relevant reagents for {reagent}: {relevant_reagents}")
# NOTE: if reagent in sheet is not found insert it into the front of relevant reagents so it shows
if str(reagent.lot) not in relevant_reagents:
if check_not_nan(reagent.lot):
@@ -803,7 +747,6 @@ class SubmissionFormWidget(QWidget):
looked_up_reg = None
if isinstance(looked_up_reg, list):
looked_up_reg = None
# logger.debug(f"Because there was no reagent listed for {reagent.lot}, we will insert the last lot used: {looked_up_reg}")
if looked_up_reg:
try:
relevant_reagents.remove(str(looked_up_reg.lot))
@@ -812,15 +755,11 @@ class SubmissionFormWidget(QWidget):
relevant_reagents.insert(0, str(looked_up_reg.lot))
else:
if len(relevant_reagents) > 1:
# logger.debug(f"Found {reagent.lot} in relevant reagents: {relevant_reagents}. Moving to front of list.")
idx = relevant_reagents.index(str(reagent.lot))
# logger.debug(f"The index we got for {reagent.lot} in {relevant_reagents} was {idx}")
moved_reag = relevant_reagents.pop(idx)
relevant_reagents.insert(0, moved_reag)
else:
# logger.debug(f"Found {reagent.lot} in relevant reagents: {relevant_reagents}. But no need to move due to short list.")
pass
logger.debug(f"New relevant reagents: {relevant_reagents}")
self.setObjectName(f"lot_{reagent.role}")
self.addItems(relevant_reagents)
self.setToolTip(f"Enter lot number for the reagent used for {reagent.role}")

View File

@@ -35,7 +35,6 @@ class Summary(InfoPane):
def update_data(self):
super().update_data()
orgs = [self.org_select.itemText(i) for i in range(self.org_select.count()) if self.org_select.itemChecked(i)]
# logger.debug(f"Getting report from {self.start_date} to {self.end_date} using {orgs}")
self.report_obj = ReportMaker(start_date=self.start_date, end_date=self.end_date, organizations=orgs)
self.webview.setHtml(self.report_obj.html)
if self.report_obj.subs: