logging and scrollable form

This commit is contained in:
Landon Wark
2023-01-24 15:22:15 -06:00
parent 7a53cfd9a1
commit f53d420d56
9 changed files with 129 additions and 121 deletions

View File

@@ -6,12 +6,11 @@ if getattr(sys, 'frozen', False):
else :
pass
from configure import get_config, create_database_session, setup_logger
logger = setup_logger(verbosity=3)
ctx = get_config(None)
from PyQt6.QtWidgets import QApplication
from frontend import App
logger = setup_logger(verbose=True)
ctx["database_session"] = create_database_session(Path(ctx['database']))
if __name__ == '__main__':

View File

@@ -11,7 +11,7 @@ from sqlalchemy import JSON
import json
from dateutil.relativedelta import relativedelta
logger = logging.getLogger(__name__)
logger = logging.getLogger(f"submissions.{__name__}")
def get_kits_by_use( ctx:dict, kittype_str:str|None) -> list:
pass
@@ -35,7 +35,7 @@ def store_submission(ctx:dict, base_submission:models.BasicSubmission) -> None:
def store_reagent(ctx:dict, reagent:models.Reagent) -> None:
print(reagent.__dict__)
logger.debug(reagent.__dict__)
ctx['database_session'].add(reagent)
ctx['database_session'].commit()
@@ -46,18 +46,18 @@ def construct_submission_info(ctx:dict, info_dict:dict) -> models.BasicSubmissio
info_dict['submission_type'] = info_dict['submission_type'].replace(" ", "_").lower()
instance = model()
for item in info_dict:
print(f"Setting {item} to {info_dict[item]}")
logger.debug(f"Setting {item} to {info_dict[item]}")
match item:
case "extraction_kit":
q_str = info_dict[item]
print(f"Looking up kit {q_str}")
logger.debug(f"Looking up kit {q_str}")
field_value = lookup_kittype_by_name(ctx=ctx, name=q_str)
print(f"Got {field_value} for kit {q_str}")
logger.debug(f"Got {field_value} for kit {q_str}")
case "submitting_lab":
q_str = info_dict[item].replace(" ", "_").lower()
print(f"looking up organization: {q_str}")
logger.debug(f"looking up organization: {q_str}")
field_value = lookup_org_by_name(ctx=ctx, name=q_str)
print(f"Got {field_value} for organization {q_str}")
logger.debug(f"Got {field_value} for organization {q_str}")
case "submitter_plate_num":
# Because of unique constraint, the submitter plate number cannot be None, so...
if info_dict[item] == None:
@@ -72,16 +72,16 @@ def construct_submission_info(ctx:dict, info_dict:dict) -> models.BasicSubmissio
try:
setattr(instance, item, field_value)
except AttributeError:
print(f"Could not set attribute: {item} to {info_dict[item]}")
logger.debug(f"Could not set attribute: {item} to {info_dict[item]}")
continue
# print(instance.__dict__)
# logger.debug(instance.__dict__)
return instance
# looked_up = []
# for reagent in reagents:
# my_reagent = lookup_reagent(reagent)
# print(my_reagent)
# logger.debug(my_reagent)
# looked_up.append(my_reagent)
# print(looked_up)
# logger.debug(looked_up)
# instance.reagents = looked_up
# ctx['database_session'].add(instance)
# ctx['database_session'].commit()
@@ -89,7 +89,7 @@ def construct_submission_info(ctx:dict, info_dict:dict) -> models.BasicSubmissio
def construct_reagent(ctx:dict, info_dict:dict) -> models.Reagent:
reagent = models.Reagent()
for item in info_dict:
print(f"Reagent info item: {item}")
logger.debug(f"Reagent info item: {item}")
match item:
case "lot":
reagent.lot = info_dict[item].upper()
@@ -100,7 +100,7 @@ def construct_reagent(ctx:dict, info_dict:dict) -> models.Reagent:
try:
reagent.expiry = reagent.expiry + reagent.type.eol_ext
except TypeError as e:
print(f"WE got a type error: {e}.")
logger.debug(f"WE got a type error: {e}.")
except AttributeError:
pass
return reagent
@@ -116,9 +116,9 @@ def get_all_reagenttype_names(ctx:dict) -> list[str]:
return lookedup
def lookup_reagenttype_by_name(ctx:dict, rt_name:str) -> models.ReagentType:
print(f"Looking up ReagentType by name: {rt_name}")
logger.debug(f"Looking up ReagentType by name: {rt_name}")
lookedup = ctx['database_session'].query(models.ReagentType).filter(models.ReagentType.name==rt_name).first()
print(f"Found ReagentType: {lookedup}")
logger.debug(f"Found ReagentType: {lookedup}")
return lookedup
@@ -127,7 +127,7 @@ def lookup_kittype_by_use(ctx:dict, used_by:str) -> list[models.KitType]:
return ctx['database_session'].query(models.KitType).filter(models.KitType.used_for.contains(used_by))
def lookup_kittype_by_name(ctx:dict, name:str) -> models.KitType:
print(f"Querying kittype: {name}")
logger.debug(f"Querying kittype: {name}")
return ctx['database_session'].query(models.KitType).filter(models.KitType.name==name).first()
@@ -154,11 +154,11 @@ def lookup_all_orgs(ctx:dict) -> list[models.Organization]:
return ctx['database_session'].query(models.Organization).all()
def lookup_org_by_name(ctx:dict, name:str|None) -> models.Organization:
print(f"Querying organization: {name}")
logger.debug(f"Querying organization: {name}")
return ctx['database_session'].query(models.Organization).filter(models.Organization.name==name).first()
def submissions_to_df(ctx:dict, type:str|None=None):
print(f"Type: {type}")
logger.debug(f"Type: {type}")
subs = [item.to_dict() for item in lookup_all_submissions_by_type(ctx=ctx, type=type)]
df = pd.DataFrame.from_records(subs)
return df
@@ -205,7 +205,7 @@ def create_kit_from_yaml(ctx:dict, exp:dict) -> None:
except (UnicodeDecodeError, AttributeError):
exp['password'] = exp['password'].encode()
if base64.b64encode(exp['password']) != b'cnNsX3N1Ym1pNTVpb25z':
print(f"Not the correct password.")
logger.debug(f"Not the correct password.")
return
for type in exp:
if type == "password":
@@ -220,8 +220,8 @@ def create_kit_from_yaml(ctx:dict, exp:dict) -> None:
rt = look_up
rt.kits.append(kit)
ctx['database_session'].add(rt)
print(rt.__dict__)
print(kit.__dict__)
logger.debug(rt.__dict__)
logger.debug(kit.__dict__)
ctx['database_session'].add(kit)
ctx['database_session'].commit()
@@ -252,7 +252,7 @@ def get_all_controls_by_type(ctx:dict, con_type:str, start_date:date|None=None,
list: Control instances.
"""
# print(f"Using dates: {start_date} to {end_date}")
# logger.debug(f"Using dates: {start_date} to {end_date}")
query = ctx['database_session'].query(models.ControlType).filter_by(name=con_type)
try:
output = query.first().instances
@@ -261,7 +261,7 @@ def get_all_controls_by_type(ctx:dict, con_type:str, start_date:date|None=None,
# Hacky solution to my not being able to get the sql query to work.
if start_date != None and end_date != None:
output = [item for item in output if item.submitted_date.date() > start_date and item.submitted_date.date() < end_date]
# print(f"Type {con_type}: {query.first()}")
# logger.debug(f"Type {con_type}: {query.first()}")
return output
@@ -271,7 +271,7 @@ def get_control_subtypes(ctx:dict, type:str, mode:str):
except TypeError:
return []
jsoner = json.loads(getattr(outs, mode))
print(f"JSON out: {jsoner}")
logger.debug(f"JSON out: {jsoner}")
try:
genera = list(jsoner.keys())[0]
except IndexError:

View File

@@ -1,13 +1,12 @@
from . import Base
from sqlalchemy import Column, String, TIMESTAMP, text, JSON, INTEGER, ForeignKey, UniqueConstraint, Table
from sqlalchemy.orm import relationship, relationships
from sqlalchemy import Column, String, TIMESTAMP, INTEGER, ForeignKey, Table
from sqlalchemy.orm import relationship
from datetime import datetime as dt
reagents_submissions = Table("_reagents_submissions", Base.metadata, Column("reagent_id", INTEGER, ForeignKey("_reagents.id")), Column("submission_id", INTEGER, ForeignKey("_submissions.id")))
class BasicSubmission(Base):
# TODO: Figure out if I want seperate tables for different sample types.
__tablename__ = "_submissions"
id = Column(INTEGER, primary_key=True) #: primary key
@@ -32,7 +31,6 @@ class BasicSubmission(Base):
}
def to_dict(self):
print(self.submitting_lab)
try:
sub_lab = self.submitting_lab.name
except AttributeError:

View File

@@ -13,11 +13,14 @@ logger = logging.getLogger(f"submissions.{__name__}")
class SheetParser(object):
def __init__(self, filepath:Path|None = None, **kwargs):
logger.debug(f"Parsing {filepath.__str__()}")
for kwarg in kwargs:
setattr(self, f"_{kwarg}", kwargs[kwarg])
if filepath == None:
logger.debug(f"No filepath.")
self.xl = None
else:
try:
self.xl = pd.ExcelFile(filepath.__str__())
except ValueError:
@@ -76,6 +79,7 @@ class SheetParser(object):
self.sub['lot_plate'] = submission_info.iloc[12][6]
sample_parser = SampleParser(submission_info.iloc[15:111])
sample_parse = getattr(sample_parser, f"parse_{self.sub['submission_type'].lower()}_samples")
logger.debug(f"Parser result: {self.sub}")
self.sub['samples'] = sample_parse()
@@ -121,9 +125,10 @@ class SampleParser(object):
new.sample_id = sample['Unnamed: 1']
new.organism = sample['Unnamed: 2']
new.concentration = sample['Unnamed: 3']
# print(f"Sample object: {new.sample_id} = {type(new.sample_id)}")
# logger.debug(f"Sample object: {new.sample_id} = {type(new.sample_id)}")
logger.debug(f"Got sample_id: {new.sample_id}")
try:
not_a_nan = not np.isnan(new.sample_id) and new.sample_id.lower() != 'blank'
not_a_nan = not np.isnan(new.sample_id) and str(new.sample_id).lower() != 'blank'
except TypeError:
not_a_nan = True
if not_a_nan:

View File

@@ -3,6 +3,9 @@ from pandas import DataFrame
import numpy as np
from backend.db import models
import json
import logging
logger = logging.getLogger(f"submissions.{__name__}")
def make_report_xlsx(records:list[dict]) -> DataFrame:
df = DataFrame.from_records(records)
@@ -10,7 +13,7 @@ def make_report_xlsx(records:list[dict]) -> DataFrame:
# table = df.pivot_table(values="Cost", index=["Submitting Lab", "Extraction Kit"], columns=["Cost", "Sample Count"], aggfunc={'Cost':np.sum,'Sample Count':np.sum})
df2 = df.groupby(["Submitting Lab", "Extraction Kit"]).agg({'Cost': ['sum', 'count'], 'Sample Count':['sum']})
# df2['Cost'] = df2['Cost'].map('${:,.2f}'.format)
print(df2.columns)
logger.debug(df2.columns)
# df2['Cost']['sum'] = df2['Cost']['sum'].apply('${:,.2f}'.format)
df2.iloc[:, (df2.columns.get_level_values(1)=='sum') & (df2.columns.get_level_values(0)=='Cost')] = df2.iloc[:, (df2.columns.get_level_values(1)=='sum') & (df2.columns.get_level_values(0)=='Cost')].applymap('${:,.2f}'.format)
return df2
@@ -27,7 +30,7 @@ def make_report_xlsx(records:list[dict]) -> DataFrame:
# for ii in range(data_size):
# new_dict = {}
# for genus in sub_dict:
# print(genus)
# logger.debug(genus)
# sub_name = list(sub_dict[genus].keys())[ii]
# new_dict[genus] = sub_dict[genus][sub_name]
# output.append({"date":dict_name, "name": sub_name, "data": new_dict})
@@ -55,10 +58,10 @@ def make_report_xlsx(records:list[dict]) -> DataFrame:
# # col_dict = entry[col_name]
# # series = pd.Series(data=col_dict.values(), index=col_dict.keys(), name=col_name)
# # # df[col_name] = series.values
# # # print(df.index)
# # # logger.debug(df.index)
# # series_list.append(series)
# # df = DataFrame(series_list).T.fillna(0)
# # print(df)
# # logger.debug(df)
# dfs['name'] = df
# return dfs
@@ -74,14 +77,14 @@ def convert_control_by_mode(ctx:dict, control:models.Control, mode:str):
for key in data[genus]:
_dict[key] = data[genus][key]
output.append(_dict)
# print(output)
# logger.debug(output)
return output
def convert_data_list_to_df(ctx:dict, input:list[dict], subtype:str|None=None) -> DataFrame:
df = DataFrame.from_records(input)
safe = ['name', 'submitted_date', 'genus', 'target']
print(df)
logger.debug(df)
for column in df.columns:
if "percent" in column:
count_col = [item for item in df.columns if "count" in item][0]
@@ -90,5 +93,5 @@ def convert_data_list_to_df(ctx:dict, input:list[dict], subtype:str|None=None) -
if column not in safe:
if subtype != None and column != subtype:
del df[column]
# print(df)
# logger.debug(df)
return df

View File

@@ -1,5 +1,5 @@
import yaml
import sys, os, stat, platform
import sys, os, stat, platform, shutil
import logging
from logging import handlers
from pathlib import Path
@@ -8,17 +8,17 @@ from sqlalchemy.orm import Session
from sqlalchemy import create_engine
logger = logging.getLogger(__name__)
logger = logging.getLogger(f"submissions.{__name__}")
package_dir = Path(__file__).parents[2].resolve()
logger.debug(f"Package dir: {package_dir}")
if platform.system == "Windows":
os_config_dir = "AppData"
logger.debug(f"Got platform Windows, config_dir: {os_config_dir}")
if platform.system() == "Windows":
os_config_dir = "AppData/local"
print(f"Got platform Windows, config_dir: {os_config_dir}")
else:
os_config_dir = ".config"
logger.debug(f"Got platform other, config_dir: {os_config_dir}")
print(f"Got platform other, config_dir: {os_config_dir}")
main_aux_dir = Path.home().joinpath(f"{os_config_dir}/submissions")
@@ -27,6 +27,8 @@ CONFIGDIR = main_aux_dir.joinpath("config")
LOGDIR = main_aux_dir.joinpath("logs")
class GroupWriteRotatingFileHandler(handlers.RotatingFileHandler):
def doRollover(self):
@@ -79,6 +81,16 @@ def get_config(settings_path: str|None) -> dict:
## register the tag handler
yaml.add_constructor('!join', join)
# if user hasn't defined config path in cli args
logger.debug(f"Making directory: {CONFIGDIR.__str__()}")
try:
CONFIGDIR.mkdir(parents=True)
except FileExistsError:
pass
logger.debug(f"Making directory: {LOGDIR.__str__()}")
try:
LOGDIR.mkdir(parents=True)
except FileExistsError:
pass
if settings_path == None:
# Check user .config/ozma directory
# if Path.exists(Path.joinpath(CONFIGDIR, "config.yml")):
@@ -94,6 +106,7 @@ def get_config(settings_path: str|None) -> dict:
settings_path = Path(sys._MEIPASS).joinpath("files", "config.yml")
else:
settings_path = package_dir.joinpath('config.yml')
shutil.copyfile(settings_path.__str__(), CONFIGDIR.joinpath("config.yml").__str__())
else:
if Path(settings_path).is_dir():
settings_path = settings_path.joinpath("config.yml")
@@ -103,6 +116,7 @@ def get_config(settings_path: str|None) -> dict:
logger.error("No config.yml file found. Using empty dictionary.")
return {}
logger.debug(f"Using {settings_path} for config file.")
with open(settings_path, "r") as stream:
try:
settings = yaml.load(stream, Loader=yaml.Loader)
@@ -141,7 +155,7 @@ def create_database_session(database_path: Path|None) -> Session:
return session
def setup_logger(verbose:bool=False):
def setup_logger(verbosity:int=3):
"""Set logger levels using settings.
Args:
@@ -161,34 +175,38 @@ def setup_logger(verbose:bool=False):
fh.setLevel(logging.DEBUG)
fh.name = "File"
# create console handler with a higher log level
ch = logging.StreamHandler()
if verbose:
ch.setLevel(logging.DEBUG)
else:
ch.setLevel(logging.WARNING)
ch = logging.StreamHandler(stream=sys.stdout)
match verbosity:
case 3:
ch.setLevel(logging.DEBUG)
case 2:
ch.setLevel(logging.INFO)
case 1:
ch.setLevel(logging.WARNING)
ch.name = "Stream"
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
ch.setLevel(logging.ERROR)
# ch.setLevel(logging.ERROR)
# add the handlers to the logger
logger.addHandler(fh)
logger.addHandler(ch)
stderr_logger = logging.getLogger('STDERR')
# stderr_logger = logging.getLogger('STDERR')
return logger
# sl = StreamToLogger(stderr_logger, logging.ERROR)
# sys.stderr = sl
def set_logger_verbosity(verbosity):
"""Does what it says.
"""
handler = [item for item in logger.parent.handlers if item.name == "Stream"][0]
match verbosity:
case 3:
handler.setLevel(logging.DEBUG)
case 2:
handler.setLevel(logging.INFO)
case 1:
handler.setLevel(logging.WARNING)
# def set_logger_verbosity(verbosity):
# """Does what it says.
# """
# handler = [item for item in logger.parent.handlers if item.name == "Stream"][0]
# match verbosity:
# case 3:
# handler.setLevel(logging.DEBUG)
# case 2:
# handler.setLevel(logging.INFO)
# case 1:
# handler.setLevel(logging.WARNING)

View File

@@ -4,7 +4,7 @@ from PyQt6.QtWidgets import (
QTabWidget, QWidget, QVBoxLayout,
QPushButton, QMenuBar, QFileDialog,
QLineEdit, QMessageBox, QComboBox, QDateEdit, QHBoxLayout,
QSpinBox
QSpinBox, QScrollArea
)
from PyQt6.QtGui import QAction, QIcon
from PyQt6.QtCore import QDateTime, QDate, QSignalBlocker
@@ -108,8 +108,9 @@ class App(QMainWindow):
prsr = SheetParser(fname, **self.ctx)
except PermissionError:
return
print(f"prsr.sub = {prsr.sub}")
logger.debug(f"prsr.sub = {prsr.sub}")
# replace formlayout with tab1.layout
# self.form = self.table_widget.formlayout
for item in self.table_widget.formlayout.parentWidget().findChildren(QWidget):
item.setParent(None)
variable_parser = re.compile(r"""
@@ -128,11 +129,11 @@ class App(QMainWindow):
mo = variable_parser.fullmatch(item).lastgroup
except AttributeError:
mo = "other"
print(f"Mo: {mo}")
logger.debug(f"Mo: {mo}")
match mo:
case 'submitting_lab':
self.table_widget.formlayout.addWidget(QLabel(item.replace("_", " ").title()))
print(f"{item}: {prsr.sub[item]}")
logger.debug(f"{item}: {prsr.sub[item]}")
add_widget = QComboBox()
labs = [item.__str__() for item in lookup_all_orgs(ctx=self.ctx)]
try:
@@ -167,15 +168,15 @@ class App(QMainWindow):
add_widget.setEditable(True)
# Ensure that all reagenttypes have a name that matches the items in the excel parser
query_var = item.replace("lot_", "")
print(f"Query for: {query_var}")
logger.debug(f"Query for: {query_var}")
if isinstance(prsr.sub[item], numpy.float64):
print(f"{prsr.sub[item]} is a numpy float!")
logger.debug(f"{prsr.sub[item]} is a numpy float!")
try:
prsr.sub[item] = int(prsr.sub[item])
except ValueError:
pass
relevant_reagents = [item.__str__() for item in lookup_regent_by_type_name_and_kit_name(ctx=self.ctx, type_name=query_var, kit_name=prsr.sub['extraction_kit'])]
print(f"Relevant reagents: {relevant_reagents}")
logger.debug(f"Relevant reagents: {relevant_reagents}")
if prsr.sub[item] not in relevant_reagents and prsr.sub[item] != 'nan':
try:
check = not numpy.isnan(prsr.sub[item])
@@ -187,7 +188,7 @@ class App(QMainWindow):
add_widget.addItems(relevant_reagents)
# TODO: make samples not appear in frame.
case 'samples':
print(f"{item}: {prsr.sub[item]}")
logger.debug(f"{item}: {prsr.sub[item]}")
self.samples = prsr.sub[item]
case _:
self.table_widget.formlayout.addWidget(QLabel(item.replace("_", " ").title()))
@@ -216,28 +217,7 @@ class App(QMainWindow):
html += '</body></html>'
self.table_widget.webengineview.setHtml(html)
self.table_widget.webengineview.update()
# type = self.table_widget.control_typer.currentText()
# mode = self.table_widget.mode_typer.currentText()
# controls = get_all_controls_by_type(ctx=self.ctx, type=type)
# data = []
# for control in controls:
# dicts = convert_control_by_mode(ctx=self.ctx, control=control, mode=mode)
# data.append(dicts)
# data = [item for sublist in data for item in sublist]
# # print(data)
# df = convert_data_list_to_df(ctx=self.ctx, input=data)
# fig = create_charts(ctx=self.ctx, df=df)
# print(fig)
# html = '<html><body>'
# html += plotly.offline.plot(fig, output_type='div', auto_open=True, image = 'png', image_filename='plot_image')
# html += '</body></html>'
# html = plotly.io.to_html(fig)
# # print(html)
# # with open("C:\\Users\\lwark\\Desktop\\test.html", "w") as f:
# # f.write(html)
# self.table_widget.webengineview.setHtml(html)
# self.table_widget.webengineview.update()
def submit_new_sample(self):
@@ -297,8 +277,8 @@ class App(QMainWindow):
case QLineEdit():
# ad hoc check to prevent double reporting of qdatedit under lineedit for some reason
if not isinstance(prev_item, QDateEdit) and not isinstance(prev_item, QComboBox) and not isinstance(prev_item, QSpinBox):
print(f"Previous: {prev_item}")
print(f"Item: {item}")
logger.debug(f"Previous: {prev_item}")
logger.debug(f"Item: {item}")
values.append(item.text())
case QComboBox():
values.append(item.currentText())
@@ -346,7 +326,7 @@ class App(QMainWindow):
except TypeError:
pass
if self.table_widget.datepicker.start_date.date() > self.table_widget.datepicker.end_date.date():
print("that is not allowed!")
logger.warning("Start date after end date is not allowed!")
# self.table_widget.datepicker.start_date.setDate(e_date)
threemonthsago = self.table_widget.datepicker.end_date.date().addDays(-90)
with QSignalBlocker(self.table_widget.datepicker.start_date) as blocker:
@@ -372,12 +352,12 @@ class App(QMainWindow):
def chart_maker(self):
print(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}")
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}")
if self.table_widget.sub_typer.currentText() == "":
self.subtype = None
else:
self.subtype = self.table_widget.sub_typer.currentText()
print(f"Subtype: {self.subtype}")
logger.debug(f"Subtype: {self.subtype}")
controls = get_all_controls_by_type(ctx=self.ctx, con_type=self.con_type, start_date=self.start_date, end_date=self.end_date)
if controls == None:
return
@@ -386,14 +366,14 @@ class App(QMainWindow):
dicts = convert_control_by_mode(ctx=self.ctx, control=control, mode=self.mode)
data.append(dicts)
data = [item for sublist in data for item in sublist]
# print(data)
# logger.debug(data)
df = convert_data_list_to_df(ctx=self.ctx, input=data, subtype=self.subtype)
if self.subtype == None:
title = self.mode
else:
title = f"{self.mode} - {self.subtype}"
fig = create_charts(ctx=self.ctx, df=df, ytitle=title)
print(f"Updating figure...")
logger.debug(f"Updating figure...")
html = '<html><body>'
if fig != None:
html += plotly.offline.plot(fig, output_type='div', include_plotlyjs='cdn')#, image = 'png', auto_open=True, image_filename='plot_image')
@@ -404,7 +384,7 @@ class App(QMainWindow):
# f.write(html)
self.table_widget.webengineview.setHtml(html)
self.table_widget.webengineview.update()
print("Figure updated... I hope.")
logger.debug("Figure updated... I hope.")
# def datechange(self):
@@ -412,7 +392,7 @@ class App(QMainWindow):
# s_date = self.table_widget.datepicker.start_date.date()
# e_date = self.table_widget.datepicker.end_date.date()
# if s_date > e_date:
# print("that is not allowed!")
# logger.debug("that is not allowed!")
# # self.table_widget.datepicker.start_date.setDate(e_date)
# threemonthsago = e_date.addDays(-90)
# self.table_widget.datepicker.start_date.setDate(threemonthsago)
@@ -448,6 +428,12 @@ class AddSubForm(QWidget):
self.formlayout = QVBoxLayout(self)
self.formwidget.setLayout(self.formlayout)
self.formwidget.setFixedWidth(300)
self.interior = QScrollArea()
self.interior.setWidgetResizable(True)
self.interior.setFixedWidth(325)
self.interior.setParent(self.tab1)
self.interior.setWidget(self.formwidget)
self.sheetwidget = QWidget(self)
self.sheetlayout = QVBoxLayout(self)
@@ -455,22 +441,16 @@ class AddSubForm(QWidget):
self.sub_wid = SubmissionsSheet(parent.ctx)
self.sheetlayout.addWidget(self.sub_wid)
self.tab1.layout = QHBoxLayout(self)
self.tab1.setLayout(self.tab1.layout)
# self.tab1.layout.addLayout(self.formlayout)
# self.tab1.layout.addWidget(self.formwidget)
self.tab1.layout.addWidget(self.formwidget)
self.tab1.layout.addWidget(self.sheetwidget)
# self.tab1.layout.addLayout(self.sheetlayout)
# self.tab1.setWidgetResizable(True)
# self.tab1.setVerticalScrollBar(QScrollBar())
# self.tab1.layout.addWidget(self.scroller)
# self.tab1.setWidget(self.scroller)
# self.tab1.setMinimumHeight(300)
self.datepicker = ControlsDatePicker()
self.webengineview = QWebEngineView()
# data = '''<html>Hello World</html>'''
# self.webengineview.setHtml(data)
self.tab2.layout = QVBoxLayout(self)
self.control_typer = QComboBox()
con_types = get_all_Control_Types_names(ctx=parent.ctx)
@@ -493,3 +473,5 @@ class AddSubForm(QWidget):
self.tab3.setLayout(self.tab3.layout)
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
print(self.tab1.layout.parentWidget().findChildren(QScrollArea))

View File

@@ -14,6 +14,9 @@ from jinja2 import Environment, FileSystemLoader
import sys
from pathlib import Path
import logging
logger = logging.getLogger(f"submissions.{__name__}")
if getattr(sys, 'frozen', False):
loader_path = Path(sys._MEIPASS).joinpath("files", "templates")
@@ -62,7 +65,7 @@ class AddReagentForm(QDialog):
exp_input.setDate(QDate.currentDate())
type_input = QComboBox()
type_input.addItems([item.replace("_", " ").title() for item in get_all_reagenttype_names(ctx=ctx)])
print(f"Trying to find index of {reagent_type}")
logger.debug(f"Trying to find index of {reagent_type}")
try:
reagent_type = reagent_type.replace("_", " ").title()
except AttributeError:
@@ -132,7 +135,7 @@ class SubmissionsSheet(QTableView):
def show_details(self, item):
index=(self.selectionModel().currentIndex())
# print(index)
# logger.debug(index)
value=index.sibling(index.row(),0).data()
dlg = SubmissionDetails(ctx=self.ctx, id=value)
# dlg.show()
@@ -245,7 +248,7 @@ class KitAdder(QWidget):
def submit(self):
labels, values, reagents = self.extract_form_info(self)
info = {item[0]:item[1] for item in zip(labels, values)}
print(info)
logger.debug(info)
# info['reagenttypes'] = reagents
# del info['name']
# del info['extension_of_life_(months)']
@@ -257,7 +260,7 @@ class KitAdder(QWidget):
yml_type[used]['kits'][info['kit_name']] = {}
yml_type[used]['kits'][info['kit_name']]['cost'] = info['cost_per_run']
yml_type[used]['kits'][info['kit_name']]['reagenttypes'] = reagents
print(yml_type)
logger.debug(yml_type)
create_kit_from_yaml(ctx=self.ctx, exp=yml_type)
def extract_form_info(self, object):
@@ -265,7 +268,7 @@ class KitAdder(QWidget):
values = []
reagents = {}
for item in object.findChildren(QWidget):
print(item.parentWidget())
logger.debug(item.parentWidget())
# if not isinstance(item.parentWidget(), ReagentTypeForm):
match item:
case QLabel():
@@ -273,8 +276,8 @@ class KitAdder(QWidget):
case QLineEdit():
# ad hoc check to prevent double reporting of qdatedit under lineedit for some reason
if not isinstance(prev_item, QDateEdit) and not isinstance(prev_item, QComboBox) and not isinstance(prev_item, QSpinBox) and not isinstance(prev_item, QScrollBar):
print(f"Previous: {prev_item}")
print(f"Item: {item}, {item.text()}")
logger.debug(f"Previous: {prev_item}")
logger.debug(f"Item: {item}, {item.text()}")
values.append(item.text())
case QComboBox():
values.append(item.currentText())
@@ -286,7 +289,7 @@ class KitAdder(QWidget):
re_labels, re_values, _ = self.extract_form_info(item)
reagent = {item[0]:item[1] for item in zip(re_labels, re_values)}
print(reagent)
logger.debug(reagent)
# reagent = {reagent['name:']:{'eol':reagent['extension_of_life_(months):']}}
reagents[reagent['name']] = {'eol_ext':int(reagent['extension_of_life_(months)'])}
prev_item = item

View File

@@ -5,7 +5,7 @@ from plotly.graph_objects import Figure
import logging
from backend.excel import get_unique_values_in_df_column
logger = logging.getLogger("controls.tools.vis_functions")
logger = logging.getLogger(f"submissions.{__name__}")
def create_charts(ctx:dict, df:pd.DataFrame, ytitle:str|None=None) -> Figure:
@@ -160,7 +160,7 @@ def construct_chart(ctx:dict, df:pd.DataFrame, modes:list, ytitle:str|None=None)
color_discrete_sequence=None
else:
color = "target"
print(get_unique_values_in_df_column(df, 'target'))
# print(get_unique_values_in_df_column(df, 'target'))
match get_unique_values_in_df_column(df, 'target'):
case ['Target']:
color_discrete_sequence=["blue"]