From 3b9dc6961849e8e4124b07b83fdfc9b78bd5910a Mon Sep 17 00:00:00 2001 From: lwark Date: Mon, 10 Jun 2024 14:18:11 -0500 Subject: [PATCH] Before addition of tips. --- src/submissions/backend/db/models/kits.py | 1 - src/submissions/backend/excel/parser.py | 6 +- src/submissions/backend/excel/writer.py | 6 +- src/submissions/backend/validators/pydant.py | 1 - src/submissions/frontend/widgets/functions.py | 2 + .../frontend/widgets/gel_checker.py | 7 +- .../frontend/widgets/kit_creator.py | 3 +- src/submissions/frontend/widgets/misc.py | 6 +- src/submissions/frontend/widgets/pop_ups.py | 70 +------------------ .../frontend/widgets/sample_search.py | 5 +- .../frontend/widgets/submission_details.py | 11 ++- .../frontend/widgets/submission_table.py | 5 +- .../widgets/submission_type_creator.py | 2 + src/submissions/tools.py | 3 +- 14 files changed, 31 insertions(+), 97 deletions(-) diff --git a/src/submissions/backend/db/models/kits.py b/src/submissions/backend/db/models/kits.py index 0b08803..d352482 100644 --- a/src/submissions/backend/db/models/kits.py +++ b/src/submissions/backend/db/models/kits.py @@ -2,7 +2,6 @@ All kit and reagent related models """ from __future__ import annotations -from copy import copy from sqlalchemy import Column, String, TIMESTAMP, JSON, INTEGER, ForeignKey, Interval, Table, FLOAT, BLOB from sqlalchemy.orm import relationship, validates, Query from sqlalchemy.ext.associationproxy import association_proxy diff --git a/src/submissions/backend/excel/parser.py b/src/submissions/backend/excel/parser.py index c9b8429..b347543 100644 --- a/src/submissions/backend/excel/parser.py +++ b/src/submissions/backend/excel/parser.py @@ -8,8 +8,6 @@ from pprint import pformat from typing import List import pandas as pd from openpyxl import load_workbook, Workbook -from openpyxl.worksheet.protection import SheetProtection -import numpy as np from pathlib import Path from backend.db.models import * from backend.validators import PydSubmission, PydReagent, RSLNamer, PydSample, PydEquipment @@ -17,14 +15,12 @@ import logging, re from collections import OrderedDict from datetime import date from dateutil.parser import parse, ParserError -from tools import check_not_nan, convert_nans_to_nones, row_map, row_keys, is_missing, remove_key_from_list_of_dicts +from tools import check_not_nan, convert_nans_to_nones, is_missing, remove_key_from_list_of_dicts logger = logging.getLogger(f"submissions.{__name__}") -# row_keys = {v:k for k,v in row_map.items()} - class SheetParser(object): """ object to pull and contain data from excel file diff --git a/src/submissions/backend/excel/writer.py b/src/submissions/backend/excel/writer.py index 30c86d1..ca8ef1d 100644 --- a/src/submissions/backend/excel/writer.py +++ b/src/submissions/backend/excel/writer.py @@ -1,12 +1,10 @@ import logging from copy import copy -from pathlib import Path +# from pathlib import Path from pprint import pformat from typing import List - from openpyxl import load_workbook, Workbook -from tools import row_keys -from backend.db.models import SubmissionType, KitType, BasicSample, BasicSubmission +from backend.db.models import SubmissionType, KitType, BasicSubmission from backend.validators.pydant import PydSubmission from io import BytesIO from collections import OrderedDict diff --git a/src/submissions/backend/validators/pydant.py b/src/submissions/backend/validators/pydant.py index 11b6e61..394b786 100644 --- a/src/submissions/backend/validators/pydant.py +++ b/src/submissions/backend/validators/pydant.py @@ -2,7 +2,6 @@ Contains pydantic models and accompanying validators ''' from __future__ import annotations - import sys from operator import attrgetter import uuid, re, logging diff --git a/src/submissions/frontend/widgets/functions.py b/src/submissions/frontend/widgets/functions.py index 62bc412..bfdb1d5 100644 --- a/src/submissions/frontend/widgets/functions.py +++ b/src/submissions/frontend/widgets/functions.py @@ -8,6 +8,7 @@ from PyQt6.QtWidgets import QMainWindow, QFileDialog logger = logging.getLogger(f"submissions.{__name__}") + def select_open_file(obj:QMainWindow, file_extension:str) -> Path: """ File dialog to select a file to read from @@ -29,6 +30,7 @@ def select_open_file(obj:QMainWindow, file_extension:str) -> Path: obj.last_dir = fname.parent return fname + def select_save_file(obj:QMainWindow, default_name:str, extension:str) -> Path: """ File dialog to select a file to write to diff --git a/src/submissions/frontend/widgets/gel_checker.py b/src/submissions/frontend/widgets/gel_checker.py index c5e62a6..a217a53 100644 --- a/src/submissions/frontend/widgets/gel_checker.py +++ b/src/submissions/frontend/widgets/gel_checker.py @@ -5,9 +5,8 @@ from PyQt6.QtWidgets import (QWidget, QDialog, QGridLayout, QLabel, QLineEdit, QDialogButtonBox, QTextEdit ) -import numpy as np import pyqtgraph as pg -from PyQt6.QtGui import QIcon, QFont +from PyQt6.QtGui import QIcon from PIL import Image import numpy as np import logging @@ -18,6 +17,7 @@ from backend.db.models import WastewaterArtic logger = logging.getLogger(f"submissions.{__name__}") + # Main window class class GelBox(QDialog): @@ -86,7 +86,8 @@ class GelBox(QDialog): gel_barcode = self.gel_barcode.text() values, comment = self.form.parse_form() return dna_core_submission_number, gel_barcode, self.img_path, values, comment - + + class ControlsForm(QWidget): def __init__(self, parent, control_info:List=None) -> None: diff --git a/src/submissions/frontend/widgets/kit_creator.py b/src/submissions/frontend/widgets/kit_creator.py index 4e23455..dc38e0d 100644 --- a/src/submissions/frontend/widgets/kit_creator.py +++ b/src/submissions/frontend/widgets/kit_creator.py @@ -138,7 +138,8 @@ class KitAdder(QWidget): case QDateEdit(): info[widget.objectName()] = widget.date().toPyDate() return info, reagents - + + class ReagentRoleForm(QWidget): """ custom widget to add information about a new reagenttype diff --git a/src/submissions/frontend/widgets/misc.py b/src/submissions/frontend/widgets/misc.py index e0e84b2..57382a8 100644 --- a/src/submissions/frontend/widgets/misc.py +++ b/src/submissions/frontend/widgets/misc.py @@ -13,12 +13,12 @@ from backend.db.models import * import logging from .pop_ups import AlertPop from .functions import select_open_file -from tools import Settings logger = logging.getLogger(f"submissions.{__name__}") env = jinja_template_loading() + class AddReagentForm(QDialog): """ dialog to add gather info about new reagent @@ -102,6 +102,7 @@ class AddReagentForm(QDialog): lookup = Reagent.query(reagent_role=self.type_input.currentText()) self.name_input.addItems(list(set([item.name for item in lookup]))) + class ReportDatePicker(QDialog): """ custom dialog to ask for report start/stop dates @@ -138,6 +139,7 @@ class ReportDatePicker(QDialog): """ return dict(start_date=self.start_date.date().toPyDate(), end_date = self.end_date.date().toPyDate()) + class FirstStrandSalvage(QDialog): def __init__(self, ctx:Settings, submitter_id:str, rsl_plate_num:str|None=None) -> None: @@ -178,6 +180,7 @@ class FirstStrandSalvage(QDialog): """ return dict(plate=self.rsl_plate_num.text(), submitter_id=self.submitter_id_input.text(), well=f"{self.row_letter.currentText()}{self.column_number.currentText()}") + class LogParser(QDialog): def __init__(self, parent): @@ -197,7 +200,6 @@ class LogParser(QDialog): self.btn.clicked.connect(self.runsearch) self.setMinimumWidth(400) - def filelookup(self): """ Select file to search diff --git a/src/submissions/frontend/widgets/pop_ups.py b/src/submissions/frontend/widgets/pop_ups.py index a901182..11abb20 100644 --- a/src/submissions/frontend/widgets/pop_ups.py +++ b/src/submissions/frontend/widgets/pop_ups.py @@ -14,6 +14,7 @@ logger = logging.getLogger(f"submissions.{__name__}") env = jinja_template_loading() + class QuestionAsker(QDialog): """ dialog to ask yes/no questions @@ -33,6 +34,7 @@ class QuestionAsker(QDialog): self.layout.addWidget(self.buttonBox) self.setLayout(self.layout) + class AlertPop(QMessageBox): """ Dialog to show an alert. @@ -45,6 +47,7 @@ class AlertPop(QMessageBox): self.setInformativeText(message) self.setWindowTitle(f"{owner} - {status.title()}") + class ObjectSelector(QDialog): """ dialog to input BaseClass type manually @@ -79,70 +82,3 @@ class ObjectSelector(QDialog): str: KitType as str """ return self.widget.currentText() - -# class KitSelector(QDialog): -# """ -# dialog to input KitType manually -# """ -# def __init__(self, title:str, message:str) -> QDialog: -# super().__init__() -# self.setWindowTitle(title) -# self.widget = QComboBox() -# kits = [item.name for item in KitType.query()] -# self.widget.addItems(kits) -# self.widget.setEditable(False) -# # set yes/no buttons -# QBtn = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel -# self.buttonBox = QDialogButtonBox(QBtn) -# self.buttonBox.accepted.connect(self.accept) -# self.buttonBox.rejected.connect(self.reject) -# self.layout = QVBoxLayout() -# # Text for the yes/no question -# message = QLabel(message) -# self.layout.addWidget(message) -# self.layout.addWidget(self.widget) -# self.layout.addWidget(self.buttonBox) -# self.setLayout(self.layout) - -# def getValues(self) -> str: -# """ -# Get KitType(str) from widget - -# Returns: -# str: KitType as str -# """ -# return self.widget.currentText() - -# class SubmissionTypeSelector(QDialog): -# """ -# dialog to input SubmissionType manually -# """ -# def __init__(self, title:str, message:str) -> QDialog: -# super().__init__() -# self.setWindowTitle(title) -# self.widget = QComboBox() -# # sub_type = [item.name for item in lookup_submission_type(ctx=ctx)] -# sub_type = [item.name for item in SubmissionType.query()] -# self.widget.addItems(sub_type) -# self.widget.setEditable(False) -# # set yes/no buttons -# QBtn = QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel -# self.buttonBox = QDialogButtonBox(QBtn) -# self.buttonBox.accepted.connect(self.accept) -# self.buttonBox.rejected.connect(self.reject) -# self.layout = QVBoxLayout() -# # Text for the yes/no question -# message = QLabel(message) -# self.layout.addWidget(message) -# self.layout.addWidget(self.widget) -# self.layout.addWidget(self.buttonBox) -# self.setLayout(self.layout) - -# def parse_form(self) -> str: -# """ -# Pulls SubmissionType(str) from widget - -# Returns: -# str: SubmissionType as str -# """ -# return self.widget.currentText() diff --git a/src/submissions/frontend/widgets/sample_search.py b/src/submissions/frontend/widgets/sample_search.py index 234712f..7005aad 100644 --- a/src/submissions/frontend/widgets/sample_search.py +++ b/src/submissions/frontend/widgets/sample_search.py @@ -1,14 +1,13 @@ from pprint import pformat from typing import Tuple from pandas import DataFrame -from PyQt6.QtCore import QAbstractTableModel, Qt, QEvent, QSortFilterProxyModel +from PyQt6.QtCore import QSortFilterProxyModel from PyQt6.QtWidgets import ( QLabel, QVBoxLayout, QDialog, - QDialogButtonBox, QMessageBox, QComboBox, QTableView, QWidget, QLineEdit, QGridLayout + QComboBox, QTableView, QWidget, QLineEdit, QGridLayout ) from backend.db.models import BasicSample from .submission_table import pandasModel -from .submission_details import SubmissionDetails import logging logger = logging.getLogger(f"submissions.{__name__}") diff --git a/src/submissions/frontend/widgets/submission_details.py b/src/submissions/frontend/widgets/submission_details.py index 0d39dbc..8518f9f 100644 --- a/src/submissions/frontend/widgets/submission_details.py +++ b/src/submissions/frontend/widgets/submission_details.py @@ -21,6 +21,7 @@ from typing import List logger = logging.getLogger(f"submissions.{__name__}") + class SubmissionDetails(QDialog): """ a window showing text details of submission @@ -92,8 +93,8 @@ class SubmissionDetails(QDialog): self.base_dict, self.template = submission.get_details_template(base_dict=self.base_dict) self.html = self.template.render(sub=self.base_dict, signing_permission=is_power_user()) self.webview.setHtml(self.html) - with open("test.html", "w") as f: - f.write(self.html) + # with open("test.html", "w") as f: + # f.write(self.html) self.setWindowTitle(f"Submission Details - {submission.rsl_plate_num}") @pyqtSlot(str) @@ -125,8 +126,6 @@ class SubmissionDetails(QDialog): del self.base_dict['platemap'] self.html2 = self.template.render(sub=self.base_dict) try: - # with open(fname, "w+b") as f: - # pisa.CreatePDF(self.html2, dest=f) html_to_pdf(html=self.html2, output_file=fname) except PermissionError as e: logger.error(f"Error saving pdf: {e}") @@ -135,7 +134,8 @@ class SubmissionDetails(QDialog): msg.setInformativeText(f"Looks like {fname.__str__()} is open.\nPlease close it and try again.") msg.setWindowTitle("Permission Error") msg.exec() - + + class SubmissionComment(QDialog): """ a window for adding comment text to a submission @@ -174,4 +174,3 @@ class SubmissionComment(QDialog): full_comment = {"name":commenter, "time": dt, "text": comment} # logger.debug(f"Full comment: {full_comment}") return full_comment - diff --git a/src/submissions/frontend/widgets/submission_table.py b/src/submissions/frontend/widgets/submission_table.py index 22189a6..0a8d55f 100644 --- a/src/submissions/frontend/widgets/submission_table.py +++ b/src/submissions/frontend/widgets/submission_table.py @@ -9,7 +9,6 @@ from PyQt6.QtGui import QAction, QCursor from backend.db.models import BasicSubmission from backend.excel import make_report_html, make_report_xlsx from tools import Report, Result, row_map, get_first_blank_df_row, html_to_pdf -# from xhtml2pdf import pisa from .functions import select_save_file, select_open_file from .misc import ReportDatePicker import pandas as pd @@ -17,6 +16,7 @@ from openpyxl.worksheet.worksheet import Worksheet logger = logging.getLogger(f"submissions.{__name__}") + class pandasModel(QAbstractTableModel): """ pandas model for inserting summary sheet into gui @@ -60,7 +60,8 @@ class pandasModel(QAbstractTableModel): if orientation == Qt.Orientation.Horizontal and role == Qt.ItemDataRole.DisplayRole: return self._data.columns[col] return None - + + class SubmissionsSheet(QTableView): """ presents submission summary to user in tab1 diff --git a/src/submissions/frontend/widgets/submission_type_creator.py b/src/submissions/frontend/widgets/submission_type_creator.py index 4c10b18..d77022c 100644 --- a/src/submissions/frontend/widgets/submission_type_creator.py +++ b/src/submissions/frontend/widgets/submission_type_creator.py @@ -12,6 +12,7 @@ from .functions import select_open_file logger = logging.getLogger(f"submissions.{__name__}") + class SubmissionTypeAdder(QWidget): def __init__(self, parent) -> None: @@ -80,6 +81,7 @@ class SubmissionTypeAdder(QWidget): self.template_path = select_open_file(obj=self, file_extension="xlsx") self.template_label.setText(self.template_path.__str__()) + class InfoWidget(QWidget): def __init__(self, parent: QWidget, key) -> None: diff --git a/src/submissions/tools.py b/src/submissions/tools.py index 7df34df..0d023ac 100644 --- a/src/submissions/tools.py +++ b/src/submissions/tools.py @@ -4,7 +4,6 @@ Contains miscellaenous functions used by both frontend and backend. from __future__ import annotations import json -from pathlib import Path import numpy as np import logging, re, yaml, sys, os, stat, platform, getpass, inspect, csv import pandas as pd @@ -16,7 +15,7 @@ from sqlalchemy import create_engine, text from pydantic import field_validator, BaseModel, Field from pydantic_settings import BaseSettings, SettingsConfigDict from typing import Any, Tuple, Literal, List -from PyQt6.QtGui import QTextDocument, QPageSize +from PyQt6.QtGui import QPageSize from PyQt6.QtWebEngineWidgets import QWebEngineView from openpyxl.worksheet.worksheet import Worksheet