Prior to moving settings to pydantic-settings
This commit is contained in:
@@ -4,7 +4,7 @@ from pathlib import Path
|
||||
|
||||
# Version of the realpython-reader package
|
||||
__project__ = "submissions"
|
||||
__version__ = "202307.3b"
|
||||
__version__ = "202307.4b"
|
||||
__author__ = {"name":"Landon Wark", "email":"Landon.Wark@phac-aspc.gc.ca"}
|
||||
__copyright__ = "2022-2023, Government of Canada"
|
||||
|
||||
|
||||
@@ -11,8 +11,9 @@ from PyQt6.QtWidgets import (
|
||||
QMessageBox, QFileDialog, QMenu, QLabel,
|
||||
QDialogButtonBox, QToolBar
|
||||
)
|
||||
from PyQt6.QtWebEngineWidgets import QWebEngineView
|
||||
from PyQt6.QtCore import Qt, QAbstractTableModel, QSortFilterProxyModel
|
||||
from PyQt6.QtGui import QFontMetrics, QAction, QCursor, QPixmap, QPainter
|
||||
from PyQt6.QtGui import QAction, QCursor, QPixmap, QPainter
|
||||
from backend.db import submissions_to_df, lookup_submission_by_id, delete_submission_by_id, lookup_submission_by_rsl_num, hitpick_plate
|
||||
from backend.excel import make_hitpicks
|
||||
from configure import jinja_template_loading
|
||||
@@ -266,40 +267,25 @@ class SubmissionDetails(QDialog):
|
||||
# don't want id
|
||||
del self.base_dict['id']
|
||||
# retrieve jinja template
|
||||
template = env.get_template("submission_details.txt")
|
||||
# template = env.get_template("submission_details.txt")
|
||||
# render using object dict
|
||||
text = template.render(sub=self.base_dict)
|
||||
# text = template.render(sub=self.base_dict)
|
||||
# create text field
|
||||
txt_editor = QTextEdit(self)
|
||||
txt_editor.setReadOnly(True)
|
||||
txt_editor.document().setPlainText(text)
|
||||
# txt_editor = QTextEdit(self)
|
||||
# txt_editor.setReadOnly(True)
|
||||
# txt_editor.document().setPlainText(text)
|
||||
# resize
|
||||
font = txt_editor.document().defaultFont()
|
||||
fontMetrics = QFontMetrics(font)
|
||||
textSize = fontMetrics.size(0, txt_editor.toPlainText())
|
||||
w = textSize.width() + 10
|
||||
h = textSize.height() + 10
|
||||
txt_editor.setMinimumSize(w, h)
|
||||
txt_editor.setMaximumSize(w, h)
|
||||
txt_editor.resize(w, h)
|
||||
interior.resize(w,900)
|
||||
txt_editor.setText(text)
|
||||
interior.setWidget(txt_editor)
|
||||
self.layout = QVBoxLayout()
|
||||
self.setFixedSize(w, 900)
|
||||
# button to export a pdf version
|
||||
btn = QPushButton("Export PDF")
|
||||
btn.setParent(self)
|
||||
btn.setFixedWidth(w)
|
||||
btn.clicked.connect(self.export)
|
||||
|
||||
|
||||
def export(self):
|
||||
"""
|
||||
Renders submission to html, then creates and saves .pdf file to user selected file.
|
||||
"""
|
||||
template = env.get_template("submission_details.html")
|
||||
# make barcode because, reasons
|
||||
# font = txt_editor.document().defaultFont()
|
||||
# fontMetrics = QFontMetrics(font)
|
||||
# textSize = fontMetrics.size(0, txt_editor.toPlainText())
|
||||
# w = textSize.width() + 10
|
||||
# h = textSize.height() + 10
|
||||
# txt_editor.setMinimumSize(w, h)
|
||||
# txt_editor.setMaximumSize(w, h)
|
||||
# txt_editor.resize(w, h)
|
||||
# interior.resize(w,900)
|
||||
# txt_editor.setText(text)
|
||||
# interior.setWidget(txt_editor)
|
||||
self.base_dict['barcode'] = base64.b64encode(make_plate_barcode(self.base_dict['Plate Number'], width=120, height=30)).decode('utf-8')
|
||||
sub = lookup_submission_by_rsl_num(ctx=self.ctx, rsl_num=self.base_dict['Plate Number'])
|
||||
plate_dicto = hitpick_plate(sub)
|
||||
@@ -312,10 +298,45 @@ class SubmissionDetails(QDialog):
|
||||
logger.error(f"No plate map found for {sub.rsl_plate_num}")
|
||||
# platemap.save("test.jpg", 'JPEG')
|
||||
self.base_dict['platemap'] = base64.b64encode(image_io.getvalue()).decode('utf-8')
|
||||
logger.debug(self.base_dict)
|
||||
html = template.render(sub=self.base_dict)
|
||||
with open("test.html", "w") as f:
|
||||
f.write(html)
|
||||
template = env.get_template("submission_details.html")
|
||||
self.html = template.render(sub=self.base_dict)
|
||||
webview = QWebEngineView()
|
||||
webview.setMinimumSize(900, 500)
|
||||
webview.setMaximumSize(900, 500)
|
||||
webview.setHtml(self.html)
|
||||
self.layout = QVBoxLayout()
|
||||
interior.resize(900, 500)
|
||||
interior.setWidget(webview)
|
||||
self.setFixedSize(900, 500)
|
||||
# button to export a pdf version
|
||||
btn = QPushButton("Export PDF")
|
||||
btn.setParent(self)
|
||||
btn.setFixedWidth(900)
|
||||
btn.clicked.connect(self.export)
|
||||
|
||||
|
||||
def export(self):
|
||||
"""
|
||||
Renders submission to html, then creates and saves .pdf file to user selected file.
|
||||
"""
|
||||
# template = env.get_template("submission_details.html")
|
||||
# # make barcode because, reasons
|
||||
# self.base_dict['barcode'] = base64.b64encode(make_plate_barcode(self.base_dict['Plate Number'], width=120, height=30)).decode('utf-8')
|
||||
# sub = lookup_submission_by_rsl_num(ctx=self.ctx, rsl_num=self.base_dict['Plate Number'])
|
||||
# plate_dicto = hitpick_plate(sub)
|
||||
# platemap = make_plate_map(plate_dicto)
|
||||
# logger.debug(f"platemap: {platemap}")
|
||||
# image_io = BytesIO()
|
||||
# try:
|
||||
# platemap.save(image_io, 'JPEG')
|
||||
# except AttributeError:
|
||||
# logger.error(f"No plate map found for {sub.rsl_plate_num}")
|
||||
# # platemap.save("test.jpg", 'JPEG')
|
||||
# self.base_dict['platemap'] = base64.b64encode(image_io.getvalue()).decode('utf-8')
|
||||
# logger.debug(self.base_dict)
|
||||
# html = template.render(sub=self.base_dict)
|
||||
# with open("test.html", "w") as f:
|
||||
# f.write(html)
|
||||
try:
|
||||
home_dir = Path(self.ctx["directory_path"]).joinpath(f"Submission_Details_{self.base_dict['Plate Number']}.pdf").resolve().__str__()
|
||||
except FileNotFoundError:
|
||||
@@ -326,7 +347,7 @@ class SubmissionDetails(QDialog):
|
||||
return
|
||||
try:
|
||||
with open(fname, "w+b") as f:
|
||||
pisa.CreatePDF(html, dest=f)
|
||||
pisa.CreatePDF(self.html, dest=f)
|
||||
except PermissionError as e:
|
||||
logger.error(f"Error saving pdf: {e}")
|
||||
msg = QMessageBox()
|
||||
|
||||
@@ -816,7 +816,7 @@ def import_pcr_results_function(obj:QMainWindow) -> Tuple[QMainWindow, dict]:
|
||||
|
||||
def autofill_excel(obj:QMainWindow, xl_map:dict, reagents:List[dict], missing_reagents:List[str], info:dict):
|
||||
"""
|
||||
Automatically fills in excel cells with reagent info.
|
||||
Automatically fills in excel cells with submission info.
|
||||
|
||||
Args:
|
||||
obj (QMainWindow): Original main app window
|
||||
@@ -829,13 +829,15 @@ def autofill_excel(obj:QMainWindow, xl_map:dict, reagents:List[dict], missing_re
|
||||
|
||||
logger.debug(f"Here is the info dict coming in:\n{pprint.pformat(info)}")
|
||||
logger.debug(f"Here are the missing reagents:\n{missing_reagents}")
|
||||
# pare down the xl map to only the missing data.
|
||||
relevant_map = {k:v for k,v in xl_map.items() if k in missing_reagents}
|
||||
# logger.debug(relevant_map)
|
||||
# pare down reagents to only what's missing
|
||||
relevant_reagents = [item for item in reagents if item['type'] in missing_reagents]
|
||||
# hacky manipulation of submission type so it looks better.
|
||||
info['submission_type'] = info['submission_type'].replace("_", " ").title()
|
||||
# pare down info to just what's missing
|
||||
relevant_info = {k:v for k,v in info.items() if k in missing_reagents}
|
||||
logger.debug(f"Here is the relevant info: {pprint.pformat(relevant_info)}")
|
||||
# logger.debug(f"Relevant reagents:\n{relevant_reagents}")
|
||||
# construct new objects to put into excel sheets:
|
||||
new_reagents = []
|
||||
for reagent in relevant_reagents:
|
||||
@@ -846,12 +848,14 @@ def autofill_excel(obj:QMainWindow, xl_map:dict, reagents:List[dict], missing_re
|
||||
new_reagent['expiry'] = relevant_map[new_reagent['type']]['expiry']
|
||||
new_reagent['expiry']['value'] = reagent['expiry']
|
||||
new_reagent['sheet'] = relevant_map[new_reagent['type']]['sheet']
|
||||
# name is only present for Bacterial Culture
|
||||
try:
|
||||
new_reagent['name'] = relevant_map[new_reagent['type']]['name']
|
||||
new_reagent['name']['value'] = reagent['type']
|
||||
except:
|
||||
pass
|
||||
new_reagents.append(new_reagent)
|
||||
# construct new info objects to put into excel sheets
|
||||
new_info = []
|
||||
for item in relevant_info:
|
||||
new_item = {}
|
||||
@@ -860,11 +864,15 @@ def autofill_excel(obj:QMainWindow, xl_map:dict, reagents:List[dict], missing_re
|
||||
new_item['value'] = relevant_info[item]
|
||||
new_info.append(new_item)
|
||||
logger.debug(f"New reagents: {new_reagents}")
|
||||
# open the workbook using openpyxl
|
||||
workbook = load_workbook(obj.xl)
|
||||
# get list of sheet names
|
||||
sheets = workbook.sheetnames
|
||||
logger.debug(workbook.sheetnames)
|
||||
# logger.debug(workbook.sheetnames)
|
||||
for sheet in sheets:
|
||||
# open sheet
|
||||
worksheet=workbook[sheet]
|
||||
# Get relevant reagents for that sheet
|
||||
sheet_reagents = [item for item in new_reagents if sheet in item['sheet']]
|
||||
for reagent in sheet_reagents:
|
||||
logger.debug(f"Attempting: {reagent['type']}:")
|
||||
@@ -874,10 +882,12 @@ def autofill_excel(obj:QMainWindow, xl_map:dict, reagents:List[dict], missing_re
|
||||
worksheet.cell(row=reagent['name']['row'], column=reagent['name']['column'], value=reagent['name']['value'].replace("_", " ").upper())
|
||||
except:
|
||||
pass
|
||||
# Get relevant info for that sheet
|
||||
sheet_info = [item for item in new_info if sheet in item['location']['sheets']]
|
||||
for item in sheet_info:
|
||||
logger.debug(f"Attempting: {item['type']}")
|
||||
worksheet.cell(row=item['location']['row'], column=item['location']['column'], value=item['value'])
|
||||
# Hacky way to
|
||||
if info['submission_type'] == "Bacterial Culture":
|
||||
workbook["Sample List"].cell(row=14, column=2, value=getuser())
|
||||
fname = select_save_file(obj=obj, default_name=info['rsl_plate_num'], extension="xlsx")
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
{# template for constructing submission details #}
|
||||
{% set excluded = ['reagents', 'samples', 'controls', 'ext_info', 'pcr_info', 'comments'] %}
|
||||
{# for key, value in sub.items() if key != 'reagents' and key != 'samples' and key != 'controls' and key != 'ext_info' #}
|
||||
{% for key, value in sub.items() if key not in excluded %}
|
||||
{% if key=='Cost' %} {{ key }}: {{ "${:,.2f}".format(value) }} {% else %} {{ key }}: {{ value }} {% endif %}
|
||||
{% endfor %}
|
||||
Reagents:
|
||||
{% for item in sub['reagents'] %}
|
||||
{{ item['type'] }}: {{ item['lot'] }} (EXP: {{ item['expiry'] }}){% endfor %}
|
||||
{% if sub['samples']%}
|
||||
Samples:
|
||||
{% for item in sub['samples'] %}
|
||||
{{ item['well'] }}: {{ item['name'] }}{% endfor %}{% endif %}
|
||||
{% if sub['controls'] %}
|
||||
Attached Controls:
|
||||
{% for item in sub['controls'] %}
|
||||
{{ item['name'] }}: {{ item['type'] }} (Targets: {{ item['targets'] }})
|
||||
{% if item['kraken'] %}
|
||||
{{ item['name'] }} Top 5 Kraken Results
|
||||
{% for genera in item['kraken'] %}
|
||||
{{ genera['name'] }}: {{ genera['kraken_count'] }} ({{ genera['kraken_percent'] }}){% endfor %}{% endif %}
|
||||
{% endfor %}{% endif %}
|
||||
{% if sub['ext_info'] %}{% for entry in sub['ext_info'] %}
|
||||
Extraction Status:
|
||||
{% for key, value in entry.items() %}
|
||||
{{ key|replace('_', ' ')|title() }}: {{ value }}{% endfor %}{% endfor %}{% endif %}
|
||||
{% if sub['pcr_info'] %}{% for entry in sub['pcr_info'] %}
|
||||
{% if 'comment' not in entry.keys() %}qPCR Momentum Status:{% else %}
|
||||
qPCR Status{% endif %}
|
||||
{% for key, value in entry.items() if key != 'imported_by' %}
|
||||
{{ key|replace('_', ' ')|title() }}: {{ value }}{% endfor %}{% endfor %}
|
||||
{% endif %}
|
||||
{% if sub['comments'] %}
|
||||
Comments:
|
||||
{% for item in sub['comments'] %}
|
||||
{{ item['name'] }}:
|
||||
{{ item['text'] }}
|
||||
- {{ item['time'] }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user