Various bug fixes and streamlining.
This commit is contained in:
@@ -189,8 +189,8 @@ class App(QMainWindow):
|
||||
"""
|
||||
month = date.today().strftime("%Y-%m")
|
||||
current_month_bak = Path(self.ctx.backup_path).joinpath(f"submissions_backup-{month}").resolve()
|
||||
logger.debug(f"Here is the db directory: {self.ctx.database_path}")
|
||||
logger.debug(f"Here is the backup directory: {self.ctx.backup_path}")
|
||||
logger.info(f"Here is the db directory: {self.ctx.database_path}")
|
||||
logger.info(f"Here is the backup directory: {self.ctx.backup_path}")
|
||||
match self.ctx.database_schema:
|
||||
case "sqlite":
|
||||
db_path = self.ctx.database_path.joinpath(self.ctx.database_name).with_suffix(".db")
|
||||
@@ -206,15 +206,17 @@ class App(QMainWindow):
|
||||
current_month_bak = current_month_bak.with_suffix(".psql")
|
||||
|
||||
def export_ST_yaml(self):
|
||||
"""
|
||||
Copies submission type yaml to file system for editing and remport
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
if check_if_app():
|
||||
yaml_path = Path(sys._MEIPASS).joinpath("resources", "viral_culture.yml")
|
||||
else:
|
||||
yaml_path = project_path.joinpath("src", "submissions", "resources", "viral_culture.yml")
|
||||
# with open(yaml_path, "r") as f:
|
||||
# data = yaml.safe_load(f)
|
||||
fname = select_save_file(obj=self, default_name="Submission Type Template.yml", extension="yml")
|
||||
# with open(fname, "w") as f:
|
||||
# yaml.safe_dump(data=data, stream=f)
|
||||
shutil.copyfile(yaml_path, fname)
|
||||
|
||||
@check_authorization
|
||||
@@ -230,7 +232,6 @@ class App(QMainWindow):
|
||||
print(pformat(st.to_export_dict()))
|
||||
choice = input("Save the above submission type? [y/N]: ")
|
||||
if choice.lower() == "y":
|
||||
# st.save()
|
||||
pass
|
||||
else:
|
||||
logger.warning("Save of submission type cancelled.")
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
Handles display of control charts
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
from datetime import timedelta
|
||||
from typing import Tuple
|
||||
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||
from PyQt6.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QComboBox, QHBoxLayout,
|
||||
QDateEdit, QLabel, QSizePolicy
|
||||
QDateEdit, QLabel, QSizePolicy, QPushButton
|
||||
)
|
||||
from PyQt6.QtCore import QSignalBlocker
|
||||
from backend.db import ControlType, Control
|
||||
@@ -15,11 +16,11 @@ from PyQt6.QtCore import QDate, QSize
|
||||
import logging
|
||||
from pandas import DataFrame
|
||||
from tools import Report, Result, get_unique_values_in_df_column, Settings, report_result
|
||||
# from backend.excel.reports import convert_data_list_to_df
|
||||
from frontend.visualizations.control_charts import CustomFigure
|
||||
|
||||
logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
|
||||
class ControlsViewer(QWidget):
|
||||
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
@@ -29,7 +30,7 @@ class ControlsViewer(QWidget):
|
||||
self.report = Report()
|
||||
self.datepicker = ControlsDatePicker()
|
||||
self.webengineview = QWebEngineView()
|
||||
# set tab2 layout
|
||||
# NOTE: set tab2 layout
|
||||
self.layout = QVBoxLayout(self)
|
||||
self.control_typer = QComboBox()
|
||||
# NOTE: fetch types of controls
|
||||
@@ -54,18 +55,22 @@ class ControlsViewer(QWidget):
|
||||
self.mode_typer.currentIndexChanged.connect(self.controls_getter)
|
||||
self.datepicker.start_date.dateChanged.connect(self.controls_getter)
|
||||
self.datepicker.end_date.dateChanged.connect(self.controls_getter)
|
||||
self.datepicker.save_button.pressed.connect(self.save_chart_function)
|
||||
|
||||
def save_chart_function(self):
|
||||
self.fig.save_figure(parent=self)
|
||||
|
||||
def controls_getter(self):
|
||||
"""
|
||||
Lookup controls from database and send to chartmaker
|
||||
"""
|
||||
"""
|
||||
self.controls_getter_function()
|
||||
|
||||
@report_result
|
||||
def controls_getter_function(self):
|
||||
"""
|
||||
Get controls based on start/end dates
|
||||
"""
|
||||
"""
|
||||
report = Report()
|
||||
# NOTE: subtype defaults to disabled
|
||||
try:
|
||||
@@ -96,7 +101,7 @@ class ControlsViewer(QWidget):
|
||||
sub_types = []
|
||||
if sub_types != []:
|
||||
# NOTE: block signal that will rerun controls getter and update sub_typer
|
||||
with QSignalBlocker(self.sub_typer) as blocker:
|
||||
with QSignalBlocker(self.sub_typer) as blocker:
|
||||
self.sub_typer.addItems(sub_types)
|
||||
self.sub_typer.setEnabled(True)
|
||||
self.sub_typer.currentTextChanged.connect(self.chart_maker)
|
||||
@@ -109,8 +114,8 @@ class ControlsViewer(QWidget):
|
||||
def chart_maker(self):
|
||||
"""
|
||||
Creates plotly charts for webview
|
||||
"""
|
||||
self.chart_maker_function()
|
||||
"""
|
||||
self.chart_maker_function()
|
||||
|
||||
@report_result
|
||||
def chart_maker_function(self):
|
||||
@@ -122,7 +127,7 @@ class ControlsViewer(QWidget):
|
||||
|
||||
Returns:
|
||||
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_type}\n\tMode: {self.mode}\n\tStart
|
||||
# Date: {self.start_date}\n\tEnd Date: {self.end_date}") NOTE: set the subtype for kraken
|
||||
@@ -136,6 +141,7 @@ class ControlsViewer(QWidget):
|
||||
# NOTE: if no data found from query set fig to none for reporting in webview
|
||||
if controls is None:
|
||||
fig = None
|
||||
self.datepicker.save_button.setEnabled(False)
|
||||
else:
|
||||
# NOTE: change each control to list of dictionaries
|
||||
data = [control.convert_by_mode(mode=self.mode) for control in controls]
|
||||
@@ -153,8 +159,10 @@ class ControlsViewer(QWidget):
|
||||
title = f"{self.mode} - {self.subtype}"
|
||||
# NOTE: send dataframe to chart maker
|
||||
df, modes = self.prep_df(ctx=self.app.ctx, df=df)
|
||||
fig = CustomFigure(df=df, ytitle=title, modes=modes)
|
||||
fig = CustomFigure(df=df, ytitle=title, modes=modes, parent=self)
|
||||
self.datepicker.save_button.setEnabled(True)
|
||||
# logger.debug(f"Updating figure...")
|
||||
self.fig = fig
|
||||
# NOTE: construct html for webview
|
||||
html = fig.to_html()
|
||||
# logger.debug(f"The length of html code is: {len(html)}")
|
||||
@@ -179,6 +187,11 @@ class ControlsViewer(QWidget):
|
||||
df = DataFrame.from_records(input_df)
|
||||
safe = ['name', 'submitted_date', 'genus', 'target']
|
||||
for column in df.columns:
|
||||
if column not in safe:
|
||||
if self.subtype is not None and column != self.subtype:
|
||||
continue
|
||||
else:
|
||||
safe.append(column)
|
||||
if "percent" in column:
|
||||
# count_col = [item for item in df.columns if "count" in item][0]
|
||||
try:
|
||||
@@ -187,9 +200,9 @@ class ControlsViewer(QWidget):
|
||||
continue
|
||||
# NOTE: The actual percentage from kraken was off due to exclusion of NaN, recalculating.
|
||||
df[column] = 100 * df[count_col] / df.groupby('name')[count_col].transform('sum')
|
||||
if column not in safe:
|
||||
if self.subtype is not None and column != self.subtype:
|
||||
del df[column]
|
||||
logger.debug(df)
|
||||
logger.debug(safe)
|
||||
df = df[[c for c in df.columns if c in safe]]
|
||||
# NOTE: move date of sample submitted on same date as previous ahead one.
|
||||
df = self.displace_date(df=df)
|
||||
# NOTE: ad hoc method to make data labels more accurate.
|
||||
@@ -229,12 +242,13 @@ class ControlsViewer(QWidget):
|
||||
# NOTE: get submitted dates for each control
|
||||
dict_list = [dict(name=item, date=df[df.name == item].iloc[0]['submitted_date']) for item in
|
||||
sorted(df['name'].unique())]
|
||||
previous_dates = []
|
||||
for _, item in enumerate(dict_list):
|
||||
previous_dates = set()
|
||||
# for _, item in enumerate(dict_list):
|
||||
for item in dict_list:
|
||||
df, previous_dates = self.check_date(df=df, item=item, previous_dates=previous_dates)
|
||||
return df
|
||||
|
||||
def check_date(self, df: DataFrame, item: dict, previous_dates: list) -> Tuple[DataFrame, list]:
|
||||
def check_date(self, df: DataFrame, item: dict, previous_dates: set) -> Tuple[DataFrame, list]:
|
||||
"""
|
||||
Checks if an items date is already present in df and adjusts df accordingly
|
||||
|
||||
@@ -250,7 +264,7 @@ class ControlsViewer(QWidget):
|
||||
check = item['date'] in previous_dates
|
||||
except IndexError:
|
||||
check = False
|
||||
previous_dates.append(item['date'])
|
||||
previous_dates.add(item['date'])
|
||||
if check:
|
||||
# logger.debug(f"We found one! Increment date!\n\t{item['date']} to {item['date'] + timedelta(days=1)}")
|
||||
# NOTE: get df locations where name == item name
|
||||
@@ -273,7 +287,7 @@ class ControlsViewer(QWidget):
|
||||
df, previous_dates = self.check_date(df, item, previous_dates)
|
||||
return df, previous_dates
|
||||
|
||||
def prep_df(self, ctx: Settings, df: DataFrame) -> DataFrame:
|
||||
def prep_df(self, ctx: Settings, df: DataFrame) -> Tuple[DataFrame, list]:
|
||||
"""
|
||||
Constructs figures based on parsed pandas dataframe.
|
||||
|
||||
@@ -285,27 +299,17 @@ class ControlsViewer(QWidget):
|
||||
Returns:
|
||||
Figure: Plotly figure
|
||||
"""
|
||||
# from backend.excel import drop_reruns_from_df
|
||||
# converts starred genera to normal and splits off list of starred
|
||||
genera = []
|
||||
# NOTE: converts starred genera to normal and splits off list of starred
|
||||
if df.empty:
|
||||
return None
|
||||
for item in df['genus'].to_list():
|
||||
try:
|
||||
if item[-1] == "*":
|
||||
genera.append(item[-1])
|
||||
else:
|
||||
genera.append("")
|
||||
except IndexError:
|
||||
genera.append("")
|
||||
df['genus'] = df['genus'].replace({'\*': ''}, regex=True).replace({"NaN": "Unknown"})
|
||||
df['genera'] = genera
|
||||
df['genera'] = [item[-1] if item and item[-1] == "*" else "" for item in df['genus'].to_list()]
|
||||
# NOTE: remove original runs, using reruns if applicable
|
||||
df = self.drop_reruns_from_df(ctx=ctx, df=df)
|
||||
# NOTE: sort by and exclude from
|
||||
sorts = ['submitted_date', "target", "genus"]
|
||||
exclude = ['name', 'genera']
|
||||
modes = [item for item in df.columns if item not in sorts and item not in exclude] # and "_hashes" not in item]
|
||||
modes = [item for item in df.columns if item not in sorts and item not in exclude]
|
||||
# NOTE: Set descending for any columns that have "{mode}" in the header.
|
||||
ascending = [False if item == "target" else True for item in sorts]
|
||||
df = df.sort_values(by=sorts, ascending=ascending)
|
||||
@@ -327,23 +331,26 @@ class ControlsViewer(QWidget):
|
||||
if 'rerun_regex' in ctx:
|
||||
sample_names = get_unique_values_in_df_column(df, column_name="name")
|
||||
rerun_regex = re.compile(fr"{ctx.rerun_regex}")
|
||||
for sample in sample_names:
|
||||
if rerun_regex.search(sample):
|
||||
first_run = re.sub(rerun_regex, "", sample)
|
||||
df = df.drop(df[df.name == first_run].index)
|
||||
exclude = [re.sub(rerun_regex, "", sample) for sample in sample_names if rerun_regex.search(sample)]
|
||||
df = df[df.name not in exclude]
|
||||
# for sample in sample_names:
|
||||
# if rerun_regex.search(sample):
|
||||
# first_run = re.sub(rerun_regex, "", sample)
|
||||
# df = df.drop(df[df.name == first_run].index)
|
||||
return df
|
||||
|
||||
|
||||
class ControlsDatePicker(QWidget):
|
||||
"""
|
||||
custom widget to pick start and end dates for controls graphs
|
||||
"""
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.start_date = QDateEdit(calendarPopup=True)
|
||||
# NOTE: start date is two months prior to end date by default
|
||||
twomonthsago = QDate.currentDate().addDays(-60)
|
||||
self.start_date.setDate(twomonthsago)
|
||||
sixmonthsago = QDate.currentDate().addDays(-180)
|
||||
self.start_date.setDate(sixmonthsago)
|
||||
self.end_date = QDateEdit(calendarPopup=True)
|
||||
self.end_date.setDate(QDate.currentDate())
|
||||
self.layout = QHBoxLayout()
|
||||
@@ -353,6 +360,8 @@ class ControlsDatePicker(QWidget):
|
||||
self.layout.addWidget(self.end_date)
|
||||
self.setLayout(self.layout)
|
||||
self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
|
||||
self.save_button = QPushButton("Save Chart", parent=self)
|
||||
self.layout.addWidget(self.save_button)
|
||||
|
||||
def sizeHint(self) -> QSize:
|
||||
return QSize(80,20)
|
||||
return QSize(80, 20)
|
||||
|
||||
@@ -8,7 +8,7 @@ from PyQt6.QtWidgets import (QDialog, QComboBox, QCheckBox,
|
||||
from backend.db.models import Equipment, BasicSubmission, Process
|
||||
from backend.validators.pydant import PydEquipment, PydEquipmentRole, PydTips
|
||||
import logging
|
||||
from typing import List
|
||||
from typing import List, Generator
|
||||
|
||||
logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
@@ -45,26 +45,26 @@ class EquipmentUsage(QDialog):
|
||||
widg.update_processes()
|
||||
self.layout.addWidget(self.buttonBox)
|
||||
|
||||
def parse_form(self) -> List[PydEquipment]:
|
||||
def parse_form(self) -> Generator[PydEquipment, None, None]:
|
||||
"""
|
||||
Pull info from all RoleComboBox widgets
|
||||
|
||||
Returns:
|
||||
List[PydEquipment]: All equipment pulled from widgets
|
||||
"""
|
||||
output = []
|
||||
for widget in self.findChildren(QWidget):
|
||||
match widget:
|
||||
case RoleComboBox():
|
||||
if widget.check.isChecked():
|
||||
output.append(widget.parse_form())
|
||||
item = widget.parse_form()
|
||||
if item:
|
||||
yield item
|
||||
else:
|
||||
continue
|
||||
else:
|
||||
continue
|
||||
case _:
|
||||
pass
|
||||
# logger.debug(f"parsed output of Equsage form: {pformat(output)}")
|
||||
try:
|
||||
return [item.strip() for item in output if item is not None]
|
||||
except AttributeError:
|
||||
return [item for item in output if item is not None]
|
||||
continue
|
||||
|
||||
class LabelRow(QWidget):
|
||||
|
||||
@@ -93,14 +93,10 @@ class RoleComboBox(QWidget):
|
||||
|
||||
def __init__(self, parent, role: PydEquipmentRole, used: list) -> None:
|
||||
super().__init__(parent)
|
||||
# self.layout = QHBoxLayout()
|
||||
self.layout = QGridLayout()
|
||||
self.role = role
|
||||
self.check = QCheckBox()
|
||||
# if role.name in used:
|
||||
self.check.setChecked(False)
|
||||
# else:
|
||||
# self.check.setChecked(True)
|
||||
self.check.stateChanged.connect(self.toggle_checked)
|
||||
self.box = QComboBox()
|
||||
self.box.setMaximumWidth(200)
|
||||
@@ -129,7 +125,6 @@ class RoleComboBox(QWidget):
|
||||
"""
|
||||
equip = self.box.currentText()
|
||||
# logger.debug(f"Updating equipment: {equip}")
|
||||
# equip2 = [item for item in self.role.equipment if item.name == equip][0]
|
||||
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()
|
||||
@@ -158,7 +153,10 @@ class RoleComboBox(QWidget):
|
||||
widget.setMinimumWidth(200)
|
||||
widget.setMaximumWidth(200)
|
||||
self.layout.addWidget(widget, 0, 4)
|
||||
widget.setEnabled(self.check.isChecked())
|
||||
try:
|
||||
widget.setEnabled(self.check.isChecked())
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
def parse_form(self) -> PydEquipment | None:
|
||||
"""
|
||||
|
||||
@@ -74,7 +74,7 @@ class GelBox(QDialog):
|
||||
self.buttonBox = QDialogButtonBox(QBtn)
|
||||
self.buttonBox.accepted.connect(self.accept)
|
||||
self.buttonBox.rejected.connect(self.reject)
|
||||
layout.addWidget(self.buttonBox, 23, 1, 1, 1) #, alignment=Qt.AlignmentFlag.AlignTop)
|
||||
layout.addWidget(self.buttonBox, 23, 1, 1, 1)
|
||||
self.setLayout(layout)
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ class ControlsForm(QWidget):
|
||||
self.layout.addWidget(self.comment_field, 1, 5, 4, 1)
|
||||
self.setLayout(self.layout)
|
||||
|
||||
def parse_form(self) -> List[dict]:
|
||||
def parse_form(self) -> Tuple[List[dict], str]:
|
||||
"""
|
||||
Pulls the controls statuses from the form.
|
||||
|
||||
@@ -145,11 +145,7 @@ class ControlsForm(QWidget):
|
||||
output = []
|
||||
for le in self.findChildren(QComboBox):
|
||||
label = [item.strip() for item in le.objectName().split(" : ")]
|
||||
try:
|
||||
# dicto = [item for item in output if item['name'] == label[0]][0]
|
||||
dicto = next(item for item in output if item['name'] == label[0])
|
||||
except StopIteration:
|
||||
dicto = dict(name=label[0], values=[])
|
||||
dicto = next((item for item in output if item['name'] == label[0]), dict(name=label[0], values=[]))
|
||||
dicto['values'].append(dict(name=label[1], value=le.currentText()))
|
||||
if label[0] not in [item['name'] for item in output]:
|
||||
output.append(dicto)
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
Contains dialogs for notification and prompting.
|
||||
'''
|
||||
from PyQt6.QtWidgets import (
|
||||
QLabel, QVBoxLayout, QDialog,
|
||||
QLabel, QVBoxLayout, QDialog,
|
||||
QDialogButtonBox, QMessageBox, QComboBox
|
||||
)
|
||||
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||
from PyQt6.QtCore import Qt
|
||||
from tools import jinja_template_loading
|
||||
import logging
|
||||
from backend.db import models
|
||||
@@ -20,8 +19,9 @@ env = jinja_template_loading()
|
||||
class QuestionAsker(QDialog):
|
||||
"""
|
||||
dialog to ask yes/no questions
|
||||
"""
|
||||
def __init__(self, title:str, message:str):
|
||||
"""
|
||||
|
||||
def __init__(self, title: str, message: str):
|
||||
super().__init__()
|
||||
self.setWindowTitle(title)
|
||||
# NOTE: set yes/no buttons
|
||||
@@ -40,8 +40,10 @@ class QuestionAsker(QDialog):
|
||||
class AlertPop(QMessageBox):
|
||||
"""
|
||||
Dialog to show an alert.
|
||||
"""
|
||||
def __init__(self, message:str, status:Literal['Information', 'Question', 'Warning', 'Critical'], owner:str|None=None):
|
||||
"""
|
||||
|
||||
def __init__(self, message: str, status: Literal['Information', 'Question', 'Warning', 'Critical'],
|
||||
owner: str | None = None):
|
||||
super().__init__()
|
||||
# NOTE: select icon by string
|
||||
icon = getattr(QMessageBox.Icon, status)
|
||||
@@ -49,9 +51,10 @@ class AlertPop(QMessageBox):
|
||||
self.setInformativeText(message)
|
||||
self.setWindowTitle(f"{owner} - {status.title()}")
|
||||
|
||||
|
||||
class HTMLPop(QDialog):
|
||||
|
||||
def __init__(self, html:str, owner:str|None=None, title:str="python"):
|
||||
def __init__(self, html: str, owner: str | None = None, title: str = "python"):
|
||||
super().__init__()
|
||||
|
||||
self.webview = QWebEngineView(parent=self)
|
||||
@@ -66,14 +69,18 @@ class HTMLPop(QDialog):
|
||||
class ObjectSelector(QDialog):
|
||||
"""
|
||||
dialog to input BaseClass type manually
|
||||
"""
|
||||
def __init__(self, title:str, message:str, obj_type:str|type[models.BaseClass]):
|
||||
"""
|
||||
|
||||
def __init__(self, title: str, message: str, obj_type: str | type[models.BaseClass], values: list | None = None):
|
||||
super().__init__()
|
||||
self.setWindowTitle(title)
|
||||
self.widget = QComboBox()
|
||||
if isinstance(obj_type, str):
|
||||
obj_type: models.BaseClass = getattr(models, obj_type)
|
||||
items = [item.name for item in obj_type.query()]
|
||||
if values:
|
||||
items = values
|
||||
else:
|
||||
if isinstance(obj_type, str):
|
||||
obj_type: models.BaseClass = getattr(models, obj_type)
|
||||
items = [item.name for item in obj_type.query()]
|
||||
self.widget.addItems(items)
|
||||
self.widget.setEditable(False)
|
||||
# NOTE: set yes/no buttons
|
||||
@@ -95,5 +102,5 @@ class ObjectSelector(QDialog):
|
||||
|
||||
Returns:
|
||||
str: KitType as str
|
||||
"""
|
||||
"""
|
||||
return self.widget.currentText()
|
||||
|
||||
@@ -55,6 +55,7 @@ class SearchBox(QDialog):
|
||||
widget = FieldSearch(parent=self, label=item['label'], field_name=item['field'])
|
||||
self.layout.addWidget(widget, start_row+iii, 0)
|
||||
widget.search_widget.textChanged.connect(self.update_data)
|
||||
self.update_data()
|
||||
|
||||
def parse_form(self) -> dict:
|
||||
"""
|
||||
@@ -73,7 +74,8 @@ class SearchBox(QDialog):
|
||||
# logger.debug(f"Running update_data with sample type: {self.type}")
|
||||
fields = self.parse_form()
|
||||
# logger.debug(f"Got fields: {fields}")
|
||||
sample_list_creator = self.type.fuzzy_search(sample_type=self.type, **fields)
|
||||
# sample_list_creator = self.type.fuzzy_search(sample_type=self.type, **fields)
|
||||
sample_list_creator = self.type.fuzzy_search(**fields)
|
||||
data = self.type.samples_to_df(sample_list=sample_list_creator)
|
||||
# logger.debug(f"Data: {data}")
|
||||
self.results.setData(df=data)
|
||||
|
||||
@@ -9,7 +9,6 @@ from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||
from PyQt6.QtWebChannel import QWebChannel
|
||||
from PyQt6.QtCore import Qt, pyqtSlot, QMarginsF
|
||||
from jinja2 import TemplateNotFound
|
||||
|
||||
from backend.db.models import BasicSubmission, BasicSample, Reagent, KitType
|
||||
from tools import is_power_user, html_to_pdf, jinja_template_loading
|
||||
from .functions import select_save_file
|
||||
@@ -18,9 +17,8 @@ import logging
|
||||
from getpass import getuser
|
||||
from datetime import datetime
|
||||
from pprint import pformat
|
||||
|
||||
from typing import List
|
||||
from backend.excel.writer import DocxWriter
|
||||
|
||||
|
||||
logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@ from backend.excel import ReportMaker
|
||||
from tools import Report, Result, report_result
|
||||
from .functions import select_save_file, select_open_file
|
||||
from .misc import ReportDatePicker
|
||||
import pandas as pd
|
||||
from openpyxl.worksheet.worksheet import Worksheet
|
||||
|
||||
logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
@@ -222,10 +220,6 @@ class SubmissionsSheet(QTableView):
|
||||
# NOTE: if imported submission doesn't exist move on to next run
|
||||
if sub is None:
|
||||
continue
|
||||
# try:
|
||||
# logger.debug(f"Found submission: {sub.rsl_plate_num}")
|
||||
# except AttributeError:
|
||||
# continue
|
||||
sub.set_attribute('pcr_info', new_run)
|
||||
# NOTE: check if pcr_info already exists
|
||||
sub.save()
|
||||
|
||||
@@ -9,7 +9,7 @@ from PyQt6.QtWidgets import (
|
||||
)
|
||||
from PyQt6.QtCore import pyqtSignal, Qt
|
||||
from . import select_open_file, select_save_file
|
||||
import logging, difflib, inspect
|
||||
import logging, difflib
|
||||
from pathlib import Path
|
||||
from tools import Report, Result, check_not_nan, main_form_style, report_result, check_regex_match
|
||||
from backend.excel.parser import SheetParser
|
||||
@@ -163,7 +163,7 @@ class SubmissionFormContainer(QWidget):
|
||||
# NOTE: create form
|
||||
dlg = AddReagentForm(reagent_lot=reagent_lot, reagent_role=reagent_role, expiry=expiry, reagent_name=name)
|
||||
if dlg.exec():
|
||||
# extract form info
|
||||
# NOTE: extract form info
|
||||
info = dlg.parse_form()
|
||||
# logger.debug(f"Reagent info: {info}")
|
||||
# NOTE: create reagent object
|
||||
@@ -180,7 +180,6 @@ class SubmissionFormWidget(QWidget):
|
||||
|
||||
def __init__(self, parent: QWidget, submission: PydSubmission, disable: list | None = None) -> None:
|
||||
super().__init__(parent)
|
||||
# self.report = Report()
|
||||
# logger.debug(f"Disable: {disable}")
|
||||
if disable is None:
|
||||
disable = []
|
||||
@@ -268,7 +267,6 @@ class SubmissionFormWidget(QWidget):
|
||||
Tuple[QMainWindow, dict]: Updated application and result
|
||||
"""
|
||||
extraction_kit = args[0]
|
||||
# caller = inspect.stack()[1].function.__repr__().replace("'", "")
|
||||
report = Report()
|
||||
# logger.debug(f"Extraction kit: {extraction_kit}")
|
||||
# NOTE: Remove previous reagent widgets
|
||||
|
||||
Reference in New Issue
Block a user