Second round of code cleanup.
This commit is contained in:
@@ -2,12 +2,13 @@
|
||||
Contains all operations for creating charts, graphs and visual effects.
|
||||
'''
|
||||
from PyQt6.QtWidgets import QWidget
|
||||
import plotly
|
||||
import plotly, logging
|
||||
from plotly.graph_objects import Figure
|
||||
from plotly.graph_objs import FigureWidget
|
||||
import pandas as pd
|
||||
from frontend.widgets.functions import select_save_file
|
||||
|
||||
logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
|
||||
class CustomFigure(Figure):
|
||||
|
||||
@@ -40,16 +41,12 @@ class CustomFigure(Figure):
|
||||
"""
|
||||
Creates final html code from plotly
|
||||
|
||||
Args:
|
||||
figure (Figure): input figure
|
||||
|
||||
Returns:
|
||||
str: html string
|
||||
"""
|
||||
html = '<html><body>'
|
||||
if self is not None:
|
||||
html += plotly.offline.plot(self, output_type='div',
|
||||
include_plotlyjs='cdn') #, image = 'png', auto_open=True, image_filename='plot_image')
|
||||
html += plotly.offline.plot(self, output_type='div', include_plotlyjs='cdn')
|
||||
else:
|
||||
html += "<h1>No data was retrieved for the given parameters.</h1>"
|
||||
html += '</body></html>'
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
Functions for constructing irida controls graphs using plotly.
|
||||
"""
|
||||
from pprint import pformat
|
||||
|
||||
from plotly.graph_objs import FigureWidget, Scatter
|
||||
|
||||
from . import CustomFigure
|
||||
import plotly.express as px
|
||||
import pandas as pd
|
||||
@@ -13,30 +10,23 @@ import logging
|
||||
|
||||
logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
# NOTE: For click events try (haven't got working yet) ipywidgets >=7.0.0 required for figurewidgets:
|
||||
# https://plotly.com/python/click-events/
|
||||
|
||||
|
||||
class PCRFigure(CustomFigure):
|
||||
|
||||
def __init__(self, df: pd.DataFrame, modes: list, ytitle: str | None = None, parent: QWidget | None = None,
|
||||
months: int = 6):
|
||||
super().__init__(df=df, modes=modes)
|
||||
logger.debug(f"DF: {self.df}")
|
||||
# logger.debug(f"DF: {self.df}")
|
||||
self.construct_chart(df=df)
|
||||
|
||||
def hello(self):
|
||||
print("hello")
|
||||
|
||||
def construct_chart(self, df: pd.DataFrame):
|
||||
logger.debug(f"PCR df:\n {df}")
|
||||
# logger.debug(f"PCR df:\n {df}")
|
||||
try:
|
||||
express = px.scatter(data_frame=df, x='submitted_date', y="ct",
|
||||
scatter = px.scatter(data_frame=df, x='submitted_date', y="ct",
|
||||
hover_data=["name", "target", "ct", "reagent_lot"],
|
||||
color="target")
|
||||
except ValueError:
|
||||
express = px.scatter()
|
||||
scatter = FigureWidget([datum for datum in express.data])
|
||||
scatter = px.scatter()
|
||||
self.add_traces(scatter.data)
|
||||
self.update_traces(marker={'size': 15})
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Constructs main application.
|
||||
"""
|
||||
from pprint import pformat
|
||||
from PyQt6.QtCore import qInstallMessageHandler
|
||||
from PyQt6.QtWidgets import (
|
||||
QTabWidget, QWidget, QVBoxLayout,
|
||||
QHBoxLayout, QScrollArea, QMainWindow,
|
||||
@@ -11,6 +12,7 @@ from PyQt6.QtGui import QAction
|
||||
from pathlib import Path
|
||||
from markdown import markdown
|
||||
from __init__ import project_path
|
||||
from backend import SubmissionType
|
||||
from tools import check_if_app, Settings, Report, jinja_template_loading, check_authorization, page_size
|
||||
from .functions import select_save_file, select_open_file
|
||||
from datetime import date
|
||||
@@ -32,12 +34,13 @@ 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
|
||||
self.last_dir = ctx.directory_path
|
||||
self.report = Report()
|
||||
# NOTE: indicate version and connected database in title bar
|
||||
try:
|
||||
self.title = f"Submissions App (v{ctx.package.__version__}) - {ctx.database_session.get_bind().url}"
|
||||
self.title = f"Submissions App (v{ctx.package.__version__}) - {ctx.database_path}/{ctx.database_name}"
|
||||
except (AttributeError, KeyError):
|
||||
self.title = f"Submissions App"
|
||||
# NOTE: set initial app position and size
|
||||
|
||||
@@ -155,7 +155,7 @@ class ControlsViewer(QWidget):
|
||||
chart_settings = dict(sub_type=self.con_sub_type, start_date=self.start_date, end_date=self.end_date,
|
||||
mode=self.mode,
|
||||
sub_mode=self.mode_sub_type, parent=self, months=months)
|
||||
_, self.fig = self.archetype.get_instance_class().make_chart(chart_settings=chart_settings, parent=self, ctx=self.app.ctx)
|
||||
self.fig = self.archetype.get_instance_class().make_chart(chart_settings=chart_settings, parent=self, ctx=self.app.ctx)
|
||||
if issubclass(self.fig.__class__, CustomFigure):
|
||||
self.save_button.setEnabled(True)
|
||||
# logger.debug(f"Updating figure...")
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
'''
|
||||
Creates forms that the user can enter equipment info into.
|
||||
'''
|
||||
import time
|
||||
from pprint import pformat
|
||||
from PyQt6.QtCore import Qt
|
||||
from PyQt6.QtCore import Qt, QSignalBlocker
|
||||
from PyQt6.QtWidgets import (QDialog, QComboBox, QCheckBox,
|
||||
QLabel, QWidget, QVBoxLayout, QDialogButtonBox, QGridLayout)
|
||||
from backend.db.models import Equipment, BasicSubmission, Process
|
||||
@@ -127,13 +128,14 @@ class RoleComboBox(QWidget):
|
||||
# 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}")
|
||||
self.process.clear()
|
||||
with QSignalBlocker(self.process) as blocker:
|
||||
self.process.clear()
|
||||
self.process.addItems([item for item in equip2.processes if item in self.role.processes])
|
||||
|
||||
def update_tips(self):
|
||||
"""
|
||||
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)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Gel box for artic quality control
|
||||
"""
|
||||
from operator import itemgetter
|
||||
from PyQt6.QtWidgets import (QWidget, QDialog, QGridLayout,
|
||||
QLabel, QLineEdit, QDialogButtonBox,
|
||||
QTextEdit, QComboBox
|
||||
@@ -65,7 +66,8 @@ 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=lambda d: d['location'])
|
||||
control_info = sorted(self.submission.gel_controls, key=itemgetter('location'))
|
||||
except KeyError:
|
||||
control_info = None
|
||||
self.form = ControlsForm(parent=self, control_info=control_info)
|
||||
|
||||
@@ -99,19 +99,21 @@ class SubmissionsSheet(QTableView):
|
||||
proxyModel.setSourceModel(pandasModel(self.data))
|
||||
self.setModel(proxyModel)
|
||||
|
||||
def contextMenuEvent(self):
|
||||
def contextMenuEvent(self, event):
|
||||
"""
|
||||
Creates actions for right click menu events.
|
||||
|
||||
Args:
|
||||
event (_type_): the item of interest
|
||||
"""
|
||||
# logger.debug(event().__dict__)
|
||||
# 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)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
'''
|
||||
Contains all submission related frontend functions
|
||||
'''
|
||||
import sys
|
||||
|
||||
from PyQt6.QtWidgets import (
|
||||
QWidget, QPushButton, QVBoxLayout,
|
||||
QComboBox, QDateEdit, QLineEdit, QLabel
|
||||
@@ -190,7 +192,8 @@ class SubmissionFormWidget(QWidget):
|
||||
self.app = parent.app
|
||||
self.pyd = submission
|
||||
self.missing_info = []
|
||||
st = SubmissionType.query(name=self.pyd.submission_type['value']).get_submission_class()
|
||||
self.submission_type = SubmissionType.query(name=self.pyd.submission_type['value'])
|
||||
st = self.submission_type.get_submission_class()
|
||||
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']
|
||||
@@ -215,7 +218,7 @@ class SubmissionFormWidget(QWidget):
|
||||
value = self.pyd.model_extra[k]
|
||||
except KeyError:
|
||||
value = dict(value=None, missing=True)
|
||||
add_widget = self.create_widget(key=k, value=value, submission_type=self.pyd.submission_type['value'],
|
||||
add_widget = self.create_widget(key=k, value=value, submission_type=self.submission_type,
|
||||
sub_obj=st, disable=check)
|
||||
if add_widget is not None:
|
||||
self.layout.addWidget(add_widget)
|
||||
@@ -224,7 +227,7 @@ class SubmissionFormWidget(QWidget):
|
||||
self.setStyleSheet(main_form_style)
|
||||
self.scrape_reagents(self.pyd.extraction_kit)
|
||||
|
||||
def create_widget(self, key: str, value: dict | PydReagent, submission_type: str | None = None,
|
||||
def create_widget(self, key: str, value: dict | PydReagent, submission_type: str | SubmissionType| None = None,
|
||||
extraction_kit: str | None = None, sub_obj: BasicSubmission | None = None,
|
||||
disable: bool = False) -> "self.InfoItem":
|
||||
"""
|
||||
@@ -240,6 +243,8 @@ class SubmissionFormWidget(QWidget):
|
||||
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:
|
||||
match value:
|
||||
case PydReagent():
|
||||
@@ -272,7 +277,7 @@ class SubmissionFormWidget(QWidget):
|
||||
"""
|
||||
extraction_kit = args[0]
|
||||
report = Report()
|
||||
# logger.debug(f"Extraction kit: {extraction_kit}")
|
||||
logger.debug(f"Extraction kit: {extraction_kit}")
|
||||
# NOTE: Remove previous reagent widgets
|
||||
try:
|
||||
old_reagents = self.find_widgets()
|
||||
@@ -284,7 +289,7 @@ 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=extraction_kit)
|
||||
# logger.debug(f"Missing reagents: {obj.missing_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)
|
||||
self.layout.addWidget(add_widget)
|
||||
@@ -454,9 +459,11 @@ class SubmissionFormWidget(QWidget):
|
||||
|
||||
class InfoItem(QWidget):
|
||||
|
||||
def __init__(self, parent: QWidget, key: str, value: dict, submission_type: str | None = None,
|
||||
def __init__(self, parent: QWidget, key: str, value: dict, submission_type: str | SubmissionType | None = None,
|
||||
sub_obj: BasicSubmission | None = None) -> None:
|
||||
super().__init__(parent)
|
||||
if isinstance(submission_type, str):
|
||||
submission_type = SubmissionType.query(name=submission_type)
|
||||
layout = QVBoxLayout()
|
||||
self.label = self.ParsedQLabel(key=key, value=value)
|
||||
self.input: QWidget = self.set_widget(parent=parent, key=key, value=value, submission_type=submission_type,
|
||||
@@ -497,7 +504,7 @@ class SubmissionFormWidget(QWidget):
|
||||
return None, None
|
||||
return self.input.objectName(), dict(value=value, missing=self.missing)
|
||||
|
||||
def set_widget(self, parent: QWidget, key: str, value: dict, submission_type: str | None = None,
|
||||
def set_widget(self, parent: QWidget, key: str, value: dict, submission_type: str | SubmissionType | None = None,
|
||||
sub_obj: BasicSubmission | None = None) -> QWidget:
|
||||
"""
|
||||
Creates form widget
|
||||
@@ -511,8 +518,10 @@ class SubmissionFormWidget(QWidget):
|
||||
Returns:
|
||||
QWidget: Form object
|
||||
"""
|
||||
if isinstance(submission_type, str):
|
||||
submission_type = SubmissionType.query(name=submission_type)
|
||||
if sub_obj is None:
|
||||
sub_obj = SubmissionType.query(name=submission_type).get_submission_class()
|
||||
sub_obj = submission_type.get_submission_class()
|
||||
try:
|
||||
value = value['value']
|
||||
except (TypeError, KeyError):
|
||||
@@ -544,7 +553,8 @@ 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 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}")
|
||||
if check_not_nan(value):
|
||||
@@ -668,7 +678,7 @@ class SubmissionFormWidget(QWidget):
|
||||
dlg = QuestionAsker(title=f"Add {lot}?",
|
||||
message=f"Couldn't find reagent type {self.reagent.role}: {lot} in the database.\n\nWould you like to add it?")
|
||||
if dlg.exec():
|
||||
wanted_reagent, _ = self.parent().parent().add_reagent(reagent_lot=lot,
|
||||
wanted_reagent = self.parent().parent().add_reagent(reagent_lot=lot,
|
||||
reagent_role=self.reagent.role,
|
||||
expiry=self.reagent.expiry,
|
||||
name=self.reagent.name)
|
||||
|
||||
@@ -42,7 +42,6 @@ class Summary(QWidget):
|
||||
self.setLayout(self.layout)
|
||||
self.get_report()
|
||||
|
||||
|
||||
def get_report(self):
|
||||
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():
|
||||
|
||||
Reference in New Issue
Block a user