Moments before disaster.
This commit is contained in:
@@ -40,7 +40,6 @@ class IridaFigure(CustomFigure):
|
||||
Returns:
|
||||
Figure: output stacked bar chart.
|
||||
"""
|
||||
# fig = Figure()
|
||||
for ii, mode in enumerate(modes):
|
||||
if "count" in mode:
|
||||
df[mode] = pd.to_numeric(df[mode], errors='coerce')
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
"""
|
||||
Construct turnaround time charts
|
||||
"""
|
||||
from pprint import pformat
|
||||
from . import CustomFigure
|
||||
import plotly.express as px
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from PyQt6.QtWidgets import QWidget
|
||||
import logging
|
||||
|
||||
@@ -25,7 +27,6 @@ class TurnaroundChart(CustomFigure):
|
||||
self.construct_chart()
|
||||
if threshold:
|
||||
self.add_hline(y=threshold)
|
||||
# self.update_xaxes()
|
||||
self.update_layout(showlegend=False)
|
||||
|
||||
def construct_chart(self, df: pd.DataFrame | None = None):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"""
|
||||
Constructs main application.
|
||||
"""
|
||||
import os
|
||||
from pprint import pformat
|
||||
from PyQt6.QtCore import qInstallMessageHandler
|
||||
from PyQt6.QtWidgets import (
|
||||
@@ -18,12 +17,11 @@ from tools import check_if_app, Settings, Report, jinja_template_loading, check_
|
||||
from .functions import select_save_file, select_open_file
|
||||
from datetime import date
|
||||
from .pop_ups import HTMLPop, AlertPop
|
||||
from .misc import LogParser, Pagifier
|
||||
from .misc import Pagifier
|
||||
import logging, webbrowser, sys, shutil
|
||||
from .submission_table import SubmissionsSheet
|
||||
from .submission_widget import SubmissionFormContainer
|
||||
from .controls_chart import ControlsViewer
|
||||
# from .sample_search import SampleSearchBox
|
||||
from .summary import Summary
|
||||
from .turnaround import TurnaroundTime
|
||||
from .omni_search import SearchBox
|
||||
@@ -84,7 +82,7 @@ class App(QMainWindow):
|
||||
fileMenu.addAction(self.importAction)
|
||||
fileMenu.addAction(self.yamlExportAction)
|
||||
fileMenu.addAction(self.yamlImportAction)
|
||||
methodsMenu.addAction(self.searchLog)
|
||||
# methodsMenu.addAction(self.searchLog)
|
||||
methodsMenu.addAction(self.searchSample)
|
||||
maintenanceMenu.addAction(self.joinExtractionAction)
|
||||
maintenanceMenu.addAction(self.joinPCRAction)
|
||||
@@ -98,8 +96,8 @@ class App(QMainWindow):
|
||||
toolbar = QToolBar("My main toolbar")
|
||||
self.addToolBar(toolbar)
|
||||
toolbar.addAction(self.addReagentAction)
|
||||
toolbar.addAction(self.addKitAction)
|
||||
toolbar.addAction(self.addOrgAction)
|
||||
# toolbar.addAction(self.addKitAction)
|
||||
# toolbar.addAction(self.addOrgAction)
|
||||
|
||||
def _createActions(self):
|
||||
"""
|
||||
@@ -108,13 +106,13 @@ class App(QMainWindow):
|
||||
# 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.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.searchLog = QAction("Search Log", self)
|
||||
self.searchSample = QAction("Search Sample", self)
|
||||
self.githubAction = QAction("Github", self)
|
||||
self.yamlExportAction = QAction("Export Type Example", self)
|
||||
@@ -132,14 +130,13 @@ class App(QMainWindow):
|
||||
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.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)
|
||||
self.yamlImportAction.triggered.connect(self.import_ST_yaml)
|
||||
self.table_widget.pager.current_page.textChanged.connect(self.update_data)
|
||||
self.editReagentAction.triggered.connect(self.edit_reagent)
|
||||
self.destroyed.connect(self.final_commit)
|
||||
|
||||
def showAbout(self):
|
||||
"""
|
||||
@@ -180,15 +177,14 @@ class App(QMainWindow):
|
||||
instr = HTMLPop(html=html, title="Instructions")
|
||||
instr.exec()
|
||||
|
||||
def runSearch(self):
|
||||
dlg = LogParser(self)
|
||||
dlg.exec()
|
||||
# def runSearch(self):
|
||||
# dlg = LogParser(self)
|
||||
# dlg.exec()
|
||||
|
||||
def runSampleSearch(self):
|
||||
"""
|
||||
Create a search for samples.
|
||||
"""
|
||||
# dlg = SampleSearchBox(self)
|
||||
dlg = SearchBox(self, object_type=BasicSample, extras=[])
|
||||
dlg.exec()
|
||||
|
||||
@@ -244,7 +240,6 @@ class App(QMainWindow):
|
||||
st = SubmissionType.import_from_json(filepath=fname)
|
||||
if st:
|
||||
# NOTE: Do not delete the print statement below.
|
||||
# print(pformat(st.to_export_dict()))
|
||||
choice = input("Save the above submission type? [y/N]: ")
|
||||
if choice.lower() == "y":
|
||||
pass
|
||||
@@ -254,9 +249,6 @@ class App(QMainWindow):
|
||||
def update_data(self):
|
||||
self.table_widget.sub_wid.setData(page=self.table_widget.pager.page_anchor, page_size=page_size)
|
||||
|
||||
def final_commit(self):
|
||||
logger.debug("Running final commit")
|
||||
self.ctx.database_session.commit()
|
||||
|
||||
class AddSubForm(QWidget):
|
||||
|
||||
|
||||
@@ -10,9 +10,10 @@ from PyQt6.QtWidgets import (
|
||||
from PyQt6.QtCore import QSignalBlocker
|
||||
from backend.db import ControlType, IridaControl
|
||||
import logging
|
||||
from tools import Report, report_result
|
||||
from tools import Report, report_result, Result
|
||||
from frontend.visualizations import CustomFigure
|
||||
from .misc import StartEndDatePicker
|
||||
from .info_tab import InfoPane
|
||||
|
||||
logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
@@ -37,11 +38,11 @@ class ControlsViewer(QWidget):
|
||||
# NOTE: fetch types of controls
|
||||
con_sub_types = [item for item in self.archetype.targets.keys()]
|
||||
self.control_sub_typer.addItems(con_sub_types)
|
||||
# NOTE: create custom widget to get types of analysis
|
||||
# NOTE: create custom widget to get types of analysis -- disabled by PCR control
|
||||
self.mode_typer = QComboBox()
|
||||
mode_types = IridaControl.get_modes()
|
||||
self.mode_typer.addItems(mode_types)
|
||||
# NOTE: create custom widget to get subtypes of analysis
|
||||
# NOTE: create custom widget to get subtypes of analysis -- disabled by PCR control
|
||||
self.mode_sub_typer = QComboBox()
|
||||
self.mode_sub_typer.setEnabled(False)
|
||||
# NOTE: add widgets to tab2 layout
|
||||
@@ -83,15 +84,15 @@ class ControlsViewer(QWidget):
|
||||
pass
|
||||
# NOTE: correct start date being more recent than end date and rerun
|
||||
if self.datepicker.start_date.date() > self.datepicker.end_date.date():
|
||||
logger.warning("Start date after end date is not allowed!")
|
||||
threemonthsago = self.datepicker.end_date.date().addDays(-60)
|
||||
# NOTE: block signal that will rerun controls getter and set start date
|
||||
# Without triggering this function again
|
||||
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.controls_getter()
|
||||
self.report.add_result(report)
|
||||
return
|
||||
self.controls_getter_function()
|
||||
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()
|
||||
@@ -167,4 +168,3 @@ class ControlsViewer(QWidget):
|
||||
self.webengineview.update()
|
||||
# logger.debug("Figure updated... I hope.")
|
||||
return report
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
'''
|
||||
Creates forms that the user can enter equipment info into.
|
||||
'''
|
||||
import time
|
||||
from pprint import pformat
|
||||
from PyQt6.QtCore import Qt, QSignalBlocker
|
||||
from PyQt6.QtWidgets import (QDialog, QComboBox, QCheckBox,
|
||||
|
||||
@@ -66,7 +66,6 @@ class GelBox(QDialog):
|
||||
layout.addWidget(self.imv, 0, 1, 20, 20)
|
||||
# NOTE: setting this widget as central widget of the main window
|
||||
try:
|
||||
# control_info = sorted(self.submission.gel_controls, key=lambda d: d['location'])
|
||||
control_info = sorted(self.submission.gel_controls, key=itemgetter('location'))
|
||||
except KeyError:
|
||||
control_info = None
|
||||
@@ -79,7 +78,6 @@ class GelBox(QDialog):
|
||||
layout.addWidget(self.buttonBox, 23, 1, 1, 1)
|
||||
self.setLayout(layout)
|
||||
|
||||
|
||||
def parse_form(self) -> Tuple[str, str | Path, list]:
|
||||
"""
|
||||
Get relevant values from self/form
|
||||
@@ -124,7 +122,6 @@ class ControlsForm(QWidget):
|
||||
self.layout.addWidget(label, iii, 1, 1, 1)
|
||||
for iii in range(3):
|
||||
for jjj in range(3):
|
||||
# widge = QLineEdit()
|
||||
widge = QComboBox()
|
||||
widge.addItems(['Neg', 'Pos'])
|
||||
widge.setCurrentIndex(0)
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
"""
|
||||
A pane to show info e.g. cost reports and turnaround times.
|
||||
TODO: Can I merge this with the controls chart pane?
|
||||
"""
|
||||
from PyQt6.QtCore import QSignalBlocker
|
||||
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||
from PyQt6.QtWidgets import QWidget, QGridLayout, QPushButton
|
||||
from tools import Report
|
||||
from PyQt6.QtWidgets import QWidget, QGridLayout
|
||||
from tools import Report, report_result, Result
|
||||
from .misc import StartEndDatePicker, save_pdf
|
||||
from .functions import select_save_file
|
||||
import logging
|
||||
@@ -17,22 +22,29 @@ class InfoPane(QWidget):
|
||||
self.report = Report()
|
||||
self.datepicker = StartEndDatePicker(default_start=-31)
|
||||
self.webview = QWebEngineView()
|
||||
self.datepicker.start_date.dateChanged.connect(self.date_changed)
|
||||
self.datepicker.end_date.dateChanged.connect(self.date_changed)
|
||||
self.datepicker.start_date.dateChanged.connect(self.update_data)
|
||||
self.datepicker.end_date.dateChanged.connect(self.update_data)
|
||||
self.layout = QGridLayout(self)
|
||||
self.layout.addWidget(self.datepicker, 0, 0, 1, 2)
|
||||
self.save_excel_button = QPushButton("Save Excel", parent=self)
|
||||
self.save_excel_button.pressed.connect(self.save_excel)
|
||||
self.save_pdf_button = QPushButton("Save PDF", parent=self)
|
||||
self.save_pdf_button.pressed.connect(self.save_pdf)
|
||||
self.layout.addWidget(self.save_excel_button, 0, 2, 1, 1)
|
||||
self.layout.addWidget(self.save_pdf_button, 0, 3, 1, 1)
|
||||
self.layout.addWidget(self.webview, 2, 0, 1, 4)
|
||||
self.setLayout(self.layout)
|
||||
|
||||
def date_changed(self):
|
||||
@report_result
|
||||
def update_data(self, *args, **kwargs):
|
||||
report = Report()
|
||||
self.start_date = self.datepicker.start_date.date().toPyDate()
|
||||
self.end_date = self.datepicker.end_date.date().toPyDate()
|
||||
if self.datepicker.start_date.date() > self.datepicker.end_date.date():
|
||||
lastmonth = self.datepicker.end_date.date().addDays(-31)
|
||||
msg = f"Start date after end date is not allowed! Setting to {lastmonth.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(lastmonth)
|
||||
self.update_data()
|
||||
report.add_result(Result(owner=self.__str__(), msg=msg, status="Warning"))
|
||||
return report
|
||||
|
||||
def save_excel(self):
|
||||
fname = select_save_file(self, default_name=f"Report {self.start_date.strftime('%Y%m%d')} - {self.end_date.strftime('%Y%m%d')}", extension="xlsx")
|
||||
@@ -42,4 +54,10 @@ class InfoPane(QWidget):
|
||||
fname = select_save_file(obj=self,
|
||||
default_name=f"Report {self.start_date.strftime('%Y%m%d')} - {self.end_date.strftime('%Y%m%d')}",
|
||||
extension="pdf")
|
||||
save_pdf(obj=self.webview, filename=fname)
|
||||
save_pdf(obj=self.webview, filename=fname)
|
||||
|
||||
def save_png(self):
|
||||
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")
|
||||
@@ -14,8 +14,6 @@ from PyQt6.QtCore import Qt, QDate, QSize, QMarginsF
|
||||
from tools import jinja_template_loading
|
||||
from backend.db.models import *
|
||||
import logging
|
||||
from .pop_ups import AlertPop
|
||||
from .functions import select_open_file
|
||||
|
||||
logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
@@ -114,55 +112,6 @@ class AddReagentForm(QDialog):
|
||||
self.name_input.addItems(list(set([item.name for item in lookup])))
|
||||
|
||||
|
||||
class LogParser(QDialog):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
self.app = self.parent()
|
||||
self.filebutton = QPushButton(self)
|
||||
self.filebutton.setText("Import File")
|
||||
self.phrase_looker = QComboBox(self)
|
||||
self.phrase_looker.setEditable(True)
|
||||
self.btn = QPushButton(self)
|
||||
self.btn.setText("Search")
|
||||
self.layout = QFormLayout(self)
|
||||
self.layout.addRow(self.tr("&File:"), self.filebutton)
|
||||
self.layout.addRow(self.tr("&Search Term:"), self.phrase_looker)
|
||||
self.layout.addRow(self.btn)
|
||||
self.filebutton.clicked.connect(self.filelookup)
|
||||
self.btn.clicked.connect(self.runsearch)
|
||||
self.setMinimumWidth(400)
|
||||
|
||||
def filelookup(self):
|
||||
"""
|
||||
Select file to search
|
||||
"""
|
||||
self.fname = select_open_file(self, "tabular")
|
||||
|
||||
def runsearch(self):
|
||||
"""
|
||||
Gets total/percent occurences of string in tabular file.
|
||||
"""
|
||||
count: int = 0
|
||||
total: int = 0
|
||||
# logger.debug(f"Current search term: {self.phrase_looker.currentText()}")
|
||||
try:
|
||||
with open(self.fname, "r") as f:
|
||||
for chunk in readInChunks(fileObj=f):
|
||||
total += len(chunk)
|
||||
for line in chunk:
|
||||
if self.phrase_looker.currentText().lower() in line.lower():
|
||||
count += 1
|
||||
percent = (count / total) * 100
|
||||
msg = f"I found {count} instances of the search phrase out of {total} = {percent:.2f}%."
|
||||
status = "Information"
|
||||
except AttributeError:
|
||||
msg = f"No file was selected."
|
||||
status = "Error"
|
||||
dlg = AlertPop(message=msg, status=status)
|
||||
dlg.exec()
|
||||
|
||||
|
||||
class StartEndDatePicker(QWidget):
|
||||
"""
|
||||
custom widget to pick start and end dates for controls graphs
|
||||
|
||||
@@ -16,6 +16,9 @@ logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
|
||||
class SearchBox(QDialog):
|
||||
"""
|
||||
The full search widget.
|
||||
"""
|
||||
|
||||
def __init__(self, parent, object_type: Any, extras: List[str], **kwargs):
|
||||
super().__init__(parent)
|
||||
@@ -36,7 +39,7 @@ 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}")
|
||||
# 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,6 +54,7 @@ class SearchBox(QDialog):
|
||||
# logger.debug(deletes)
|
||||
for item in deletes:
|
||||
item.setParent(None)
|
||||
# NOTE: Handle any subclasses
|
||||
if not self.sub_class:
|
||||
self.update_data()
|
||||
else:
|
||||
@@ -89,6 +93,9 @@ class SearchBox(QDialog):
|
||||
|
||||
|
||||
class FieldSearch(QWidget):
|
||||
"""
|
||||
Search bar.
|
||||
"""
|
||||
|
||||
def __init__(self, parent, label, field_name):
|
||||
super().__init__(parent)
|
||||
@@ -115,6 +122,9 @@ class FieldSearch(QWidget):
|
||||
|
||||
|
||||
class SearchResults(QTableView):
|
||||
"""
|
||||
Results table.
|
||||
"""
|
||||
|
||||
def __init__(self, parent: SearchBox, object_type: Any, extras: List[str], **kwargs):
|
||||
super().__init__()
|
||||
@@ -146,7 +156,6 @@ class SearchResults(QTableView):
|
||||
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(**{self.object_type.searchables: context[self.object_type.searchables]})
|
||||
object = self.object_type.query(**context)
|
||||
except KeyError:
|
||||
object = None
|
||||
|
||||
@@ -42,7 +42,7 @@ class SubmissionDetails(QDialog):
|
||||
# NOTE: button to export a pdf version
|
||||
self.btn = QPushButton("Export PDF")
|
||||
self.btn.setFixedWidth(775)
|
||||
self.btn.clicked.connect(self.export)
|
||||
self.btn.clicked.connect(self.save_pdf)
|
||||
self.back = QPushButton("Back")
|
||||
self.back.setFixedWidth(100)
|
||||
# self.back.clicked.connect(self.back_function)
|
||||
@@ -181,7 +181,7 @@ class SubmissionDetails(QDialog):
|
||||
submission.save()
|
||||
self.submission_details(submission=self.rsl_plate_num)
|
||||
|
||||
def export(self):
|
||||
def save_pdf(self):
|
||||
"""
|
||||
Renders submission to html, then creates and saves .pdf file to user selected file.
|
||||
"""
|
||||
|
||||
@@ -83,6 +83,7 @@ class SubmissionsSheet(QTableView):
|
||||
self.resizeRowsToContents()
|
||||
self.setSortingEnabled(True)
|
||||
self.doubleClicked.connect(lambda x: BasicSubmission.query(id=x.sibling(x.row(), 0).data()).show_details(self))
|
||||
# NOTE: Have to run native query here because mine just returns results?
|
||||
self.total_count = BasicSubmission.__database_session__.query(BasicSubmission).count()
|
||||
|
||||
def setData(self, page: int = 1, page_size: int = 250) -> None:
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
'''
|
||||
Contains all submission related frontend functions
|
||||
'''
|
||||
import sys
|
||||
|
||||
from PyQt6.QtWidgets import (
|
||||
QWidget, QPushButton, QVBoxLayout,
|
||||
QComboBox, QDateEdit, QLineEdit, QLabel
|
||||
)
|
||||
from PyQt6.QtCore import pyqtSignal, Qt
|
||||
from . import select_open_file, select_save_file
|
||||
import logging, difflib
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from tools import Report, Result, check_not_nan, main_form_style, report_result
|
||||
from backend.excel.parser import SheetParser
|
||||
@@ -187,6 +185,8 @@ class SubmissionFormContainer(QWidget):
|
||||
|
||||
class SubmissionFormWidget(QWidget):
|
||||
|
||||
update_reagent_fields = ['extraction_kit']
|
||||
|
||||
def __init__(self, parent: QWidget, submission: PydSubmission, disable: list | None = None) -> None:
|
||||
super().__init__(parent)
|
||||
# logger.debug(f"Disable: {disable}")
|
||||
@@ -203,7 +203,7 @@ class SubmissionFormWidget(QWidget):
|
||||
# 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}")
|
||||
# logger.debug(f"Creating widget: {k}")
|
||||
if k in self.ignore:
|
||||
logger.warning(f"{k} in form_ignore {self.ignore}, not creating widget")
|
||||
continue
|
||||
@@ -225,10 +225,10 @@ 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 == "extraction_kit":
|
||||
if k in self.__class__.update_reagent_fields:
|
||||
add_widget.input.currentTextChanged.connect(self.scrape_reagents)
|
||||
self.setStyleSheet(main_form_style)
|
||||
# self.scrape_reagents(self.pyd.extraction_kit)
|
||||
self.scrape_reagents(self.extraction_kit)
|
||||
|
||||
def create_widget(self, key: str, value: dict | PydReagent, submission_type: str | SubmissionType | None = None,
|
||||
@@ -293,9 +293,8 @@ class SubmissionFormWidget(QWidget):
|
||||
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)}")
|
||||
# logger.debug(f"Got reagents: {pformat(reagents)}")
|
||||
for reagent in reagents:
|
||||
# add_widget = self.ReagentFormWidget(parent=self, reagent=reagent, extraction_kit=self.pyd.extraction_kit)
|
||||
add_widget = self.ReagentFormWidget(parent=self, reagent=reagent, extraction_kit=self.extraction_kit)
|
||||
self.layout.addWidget(add_widget)
|
||||
report.add_result(integrity_report)
|
||||
@@ -334,10 +333,6 @@ class SubmissionFormWidget(QWidget):
|
||||
query = [widget for widget in query if widget.objectName() == object_name]
|
||||
return query
|
||||
|
||||
# def update_pyd(self):
|
||||
# results = self.parse_form()
|
||||
# logger.debug(pformat(results))
|
||||
|
||||
@report_result
|
||||
def submit_new_sample_function(self, *args) -> Report:
|
||||
"""
|
||||
@@ -538,19 +533,14 @@ 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"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)
|
||||
# NOTE: lookup organizations suitable for submitting_lab (ctx: self.InfoItem.SubmissionFormWidget.SubmissionFormContainer.AddSubForm )
|
||||
labs = [item.name for item in Organization.query()]
|
||||
# NOTE: try to set closest match to top of list
|
||||
# try:
|
||||
# labs = difflib.get_close_matches(value, labs, len(labs), 0)
|
||||
# except (TypeError, ValueError):
|
||||
# pass
|
||||
if isinstance(value, dict):
|
||||
value = value['value']
|
||||
if isinstance(value, Organization):
|
||||
@@ -559,7 +549,7 @@ 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}")
|
||||
# logger.debug(f"\n\nLooked up lab: {looked_up_lab}")
|
||||
if looked_up_lab:
|
||||
try:
|
||||
labs.remove(str(looked_up_lab.name))
|
||||
@@ -579,7 +569,6 @@ class SubmissionFormWidget(QWidget):
|
||||
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 KitType.query(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}")
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
from PyQt6.QtCore import QSignalBlocker
|
||||
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||
"""
|
||||
Pane to hold information e.g. cost summary.
|
||||
"""
|
||||
from .info_tab import InfoPane
|
||||
from PyQt6.QtWidgets import QWidget, QGridLayout, QPushButton, QLabel
|
||||
from PyQt6.QtWidgets import QWidget, QLabel, QPushButton
|
||||
from backend.db import Organization
|
||||
from backend.excel import ReportMaker
|
||||
from tools import Report
|
||||
from .misc import StartEndDatePicker, save_pdf, CheckableComboBox
|
||||
from .functions import select_save_file
|
||||
from .misc import CheckableComboBox
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(f"submissions.{__name__}")
|
||||
@@ -16,32 +15,27 @@ class Summary(InfoPane):
|
||||
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent)
|
||||
self.save_excel_button = QPushButton("Save Excel", parent=self)
|
||||
self.save_excel_button.pressed.connect(self.save_excel)
|
||||
self.save_pdf_button = QPushButton("Save PDF", parent=self)
|
||||
self.save_pdf_button.pressed.connect(self.save_pdf)
|
||||
self.layout.addWidget(self.save_excel_button, 0, 2, 1, 1)
|
||||
self.layout.addWidget(self.save_pdf_button, 0, 3, 1, 1)
|
||||
self.org_select = CheckableComboBox()
|
||||
self.org_select.setEditable(False)
|
||||
self.org_select.addItem("Select", header=True)
|
||||
for org in [org.name for org in Organization.query()]:
|
||||
self.org_select.addItem(org)
|
||||
self.org_select.model().itemChanged.connect(self.date_changed)
|
||||
self.org_select.model().itemChanged.connect(self.update_data)
|
||||
self.layout.addWidget(QLabel("Client"), 1, 0, 1, 1)
|
||||
self.layout.addWidget(self.org_select, 1, 1, 1, 3)
|
||||
self.date_changed()
|
||||
self.update_data()
|
||||
|
||||
def date_changed(self):
|
||||
|
||||
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)]
|
||||
if self.datepicker.start_date.date() > self.datepicker.end_date.date():
|
||||
logger.warning("Start date after end date is not allowed!")
|
||||
lastmonth = self.datepicker.end_date.date().addDays(-31)
|
||||
# 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(lastmonth)
|
||||
self.date_changed()
|
||||
return
|
||||
# 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()
|
||||
super().date_changed()
|
||||
logger.debug(f"Getting report from {self.start_date} to {self.end_date} using {orgs}")
|
||||
# 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:
|
||||
@@ -50,13 +44,3 @@ class Summary(InfoPane):
|
||||
else:
|
||||
self.save_pdf_button.setEnabled(False)
|
||||
self.save_excel_button.setEnabled(False)
|
||||
|
||||
# def save_excel(self):
|
||||
# fname = select_save_file(self, default_name=f"Report {self.start_date.strftime('%Y%m%d')} - {self.end_date.strftime('%Y%m%d')}", extension="xlsx")
|
||||
# self.report_obj.write_report(fname, obj=self)
|
||||
#
|
||||
# def save_pdf(self):
|
||||
# fname = select_save_file(obj=self,
|
||||
# default_name=f"Report {self.start_date.strftime('%Y%m%d')} - {self.end_date.strftime('%Y%m%d')}",
|
||||
# extension="pdf")
|
||||
# save_pdf(obj=self.webview, filename=fname)
|
||||
|
||||
@@ -15,28 +15,25 @@ class TurnaroundTime(InfoPane):
|
||||
|
||||
def __init__(self, parent: QWidget):
|
||||
super().__init__(parent)
|
||||
self.chart = None
|
||||
self.save_button = QPushButton("Save Chart", parent=self)
|
||||
self.save_button.pressed.connect(self.save_png)
|
||||
self.layout.addWidget(self.save_button, 0, 2, 1, 1)
|
||||
self.export_button = QPushButton("Save Data", parent=self)
|
||||
self.export_button.pressed.connect(self.save_excel)
|
||||
self.layout.addWidget(self.export_button, 0, 3, 1, 1)
|
||||
self.fig = None
|
||||
self.report_object = None
|
||||
self.submission_typer = QComboBox(self)
|
||||
subs = ["Any"] + [item.name for item in SubmissionType.query()]
|
||||
subs = ["All"] + [item.name for item in SubmissionType.query()]
|
||||
self.submission_typer.addItems(subs)
|
||||
self.layout.addWidget(self.submission_typer, 1, 1, 1, 3)
|
||||
self.submission_typer.currentTextChanged.connect(self.date_changed)
|
||||
self.date_changed()
|
||||
self.submission_typer.currentTextChanged.connect(self.update_data)
|
||||
self.update_data()
|
||||
|
||||
def date_changed(self):
|
||||
if self.datepicker.start_date.date() > self.datepicker.end_date.date():
|
||||
logger.warning("Start date after end date is not allowed!")
|
||||
lastmonth = self.datepicker.end_date.date().addDays(-31)
|
||||
# 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(lastmonth)
|
||||
self.date_changed()
|
||||
return
|
||||
super().date_changed()
|
||||
def update_data(self):
|
||||
super().update_data()
|
||||
chart_settings = dict(start_date=self.start_date, end_date=self.end_date)
|
||||
if self.submission_typer.currentText() == "Any":
|
||||
if self.submission_typer.currentText() == "All":
|
||||
submission_type = None
|
||||
subtype_obj = None
|
||||
else:
|
||||
@@ -47,5 +44,5 @@ class TurnaroundTime(InfoPane):
|
||||
threshold = subtype_obj.defaults['turnaround_time'] + 0.5
|
||||
else:
|
||||
threshold = None
|
||||
self.chart = TurnaroundChart(df=self.report_obj.df, settings=chart_settings, modes=[], threshold=threshold)
|
||||
self.webview.setHtml(self.chart.to_html())
|
||||
self.fig = TurnaroundChart(df=self.report_obj.df, settings=chart_settings, modes=[], threshold=threshold)
|
||||
self.webview.setHtml(self.fig.to_html())
|
||||
|
||||
Reference in New Issue
Block a user