Moved relevant reagent lot aggregator to KitTypeReagentRole object.

This commit is contained in:
lwark
2024-09-17 14:50:04 -05:00
parent 7c3dfd53a0
commit 0cb1d3a104
7 changed files with 60 additions and 44 deletions

View File

@@ -14,7 +14,7 @@ from sqlalchemy.orm import relationship, validates, Query
from sqlalchemy.ext.associationproxy import association_proxy
from datetime import date
import logging, re
from tools import check_authorization, setup_lookup, Report, Result, jinja_template_loading
from tools import check_authorization, setup_lookup, Report, Result, jinja_template_loading, check_regex_match
from typing import List, Literal, Generator, Any
from pandas import ExcelFile
from pathlib import Path
@@ -175,7 +175,7 @@ class KitType(BaseClass):
return [item.reagent_role for item in relevant_associations]
# TODO: Move to BasicSubmission?
def construct_xl_map_for_use(self, submission_type: str | SubmissionType) -> Generator[str, str]:
def construct_xl_map_for_use(self, submission_type: str | SubmissionType) -> Generator[(str, str)]:
"""
Creates map of locations in Excel workbook for a SubmissionType
@@ -1139,6 +1139,23 @@ class KitTypeReagentRoleAssociation(BaseClass):
base_dict[k] = v
return base_dict
def get_all_relevant_reagents(self) -> Generator[Reagent, None, None]:
"""
Creates a generator that will resolve in to a list filling the role associated with this object.
Returns:
Generator: Generates of reagents.
"""
# logger.debug(f"Attempting lookup of reagents by type: {reagent.type}")
reagents = self.reagent_role.instances
try:
regex = self.uses['exclude_regex']
except KeyError:
regex = "^$"
relevant_reagents = [reagent for reagent in reagents if
not check_regex_match(pattern=regex, check=str(reagent.lot))]
for rel_reagent in relevant_reagents:
yield rel_reagent
class SubmissionReagentAssociation(BaseClass):
"""

View File

@@ -124,17 +124,17 @@ class CustomFigure(Figure):
fig_len = len(self.data)
if len(modes) > 1:
for ii, mode in enumerate(modes):
# What I need to do is create a list of bools with the same length as the fig.data
# NOTE: What I need to do is create a list of bools with the same length as the fig.data
mode_vis = [True] * fig_len
# And break it into {len(modes)} chunks
# NOTE: And break it into {len(modes)} chunks
mode_vis = list(divide_chunks(mode_vis, len(modes)))
# Then, for each chunk, if the chunk index isn't equal to the index of the current mode, set to false
# NOTE: Then, for each chunk, if the chunk index isn't equal to the index of the current mode, set to false
for jj, sublist in enumerate(mode_vis):
if jj != ii:
mode_vis[jj] = [not elem for elem in mode_vis[jj]]
# Finally, flatten list.
# NOTE: Finally, flatten list.
mode_vis = [item for sublist in mode_vis for item in sublist]
# Now, yield button to add to list
# NOTE: Now, yield button to add to list
yield dict(label=mode, method="update", args=[
{"visible": mode_vis},
{"yaxis.title.text": mode},

View File

@@ -152,9 +152,10 @@ class SubmissionDetails(QDialog):
with open(template_path.joinpath("css", "styles.css"), "r") as f:
css = f.read()
# logger.debug(f"Submission_details: {pformat(self.base_dict)}")
# logger.debug(f"User is power user: {is_power_user()}")
self.html = self.template.render(sub=self.base_dict, signing_permission=is_power_user(), css=css)
self.webview.setHtml(self.html)
# self.btn.setEnabled(True)
@pyqtSlot(str)
def sign_off(self, submission: str | BasicSubmission):

View File

@@ -1,18 +1,15 @@
'''
Contains all submission related frontend functions
'''
import re
import sys
from PyQt6.QtWidgets import (
QWidget, QPushButton, QVBoxLayout,
QComboBox, QDateEdit, QLineEdit, QLabel
)
from PyQt6.QtCore import pyqtSignal, Qt
from pathlib import Path
from . import select_open_file, select_save_file
import logging, difflib, inspect
from pathlib import Path
from tools import Report, Result, check_not_nan, main_form_style, report_result
from tools import Report, Result, check_not_nan, main_form_style, report_result, check_regex_match
from backend.excel.parser import SheetParser
from backend.validators import PydSubmission, PydReagent
from backend.db import (
@@ -27,10 +24,11 @@ from datetime import date
logger = logging.getLogger(f"submissions.{__name__}")
class MyQComboBox(QComboBox):
def __init__(self, scrollWidget=None, *args, **kwargs):
super(MyQComboBox, self).__init__(*args, **kwargs)
self.scrollWidget=scrollWidget
self.scrollWidget = scrollWidget
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
logger.debug(f"Scrollwidget: {scrollWidget}")
@@ -40,10 +38,11 @@ class MyQComboBox(QComboBox):
else:
return self.scrollWidget.wheelEvent(*args, **kwargs)
class MyQDateEdit(QDateEdit):
def __init__(self, scrollWidget=None, *args, **kwargs):
super(MyQDateEdit, self).__init__(*args, **kwargs)
self.scrollWidget=scrollWidget
self.scrollWidget = scrollWidget
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
def wheelEvent(self, *args, **kwargs):
@@ -243,7 +242,8 @@ class SubmissionFormWidget(QWidget):
else:
widget = None
case _:
widget = self.InfoItem(parent=self, key=key, value=value, submission_type=submission_type, sub_obj=sub_obj)
widget = self.InfoItem(parent=self, key=key, value=value, submission_type=submission_type,
sub_obj=sub_obj)
# logger.debug(f"Setting widget enabled to: {not disable}")
if disable:
widget.input.setEnabled(False)
@@ -266,9 +266,6 @@ class SubmissionFormWidget(QWidget):
"""
extraction_kit = args[0]
# caller = inspect.stack()[1].function.__repr__().replace("'", "")
# logger.debug(f"Self.reagents: {self.reagents}")
# logger.debug(f"\n\n{pformat(caller)}\n\n")
# logger.debug(f"SubmissionType: {self.submission_type}")
report = Report()
# logger.debug(f"Extraction kit: {extraction_kit}")
# NOTE: Remove previous reagent widgets
@@ -723,26 +720,13 @@ class SubmissionFormWidget(QWidget):
def __init__(self, scrollWidget, reagent, extraction_kit: str) -> None:
super().__init__(scrollWidget=scrollWidget)
self.setEditable(True)
# logger.debug(f"Attempting lookup of reagents by type: {reagent.type}")
lookup = Reagent.query(reagent_role=reagent.role)
looked_up_rt = KitTypeReagentRoleAssociation.query(reagent_role=reagent.role,
kit_type=extraction_kit)
try:
regex = re.compile(rf"{looked_up_rt.uses['exclude_regex']}")
except KeyError:
regex = re.compile(r"^$")
relevant_reagents = [str(item.lot) for item in lookup if not regex.match(str(item.lot))]
output_reg = []
for rel_reagent in relevant_reagents:
# NOTE: extract strings from any sets.
if isinstance(rel_reagent, set):
for thing in rel_reagent:
output_reg.append(thing)
elif isinstance(rel_reagent, str):
output_reg.append(rel_reagent)
relevant_reagents = output_reg
# NOTE: if reagent in sheet is not found insert it into the front of relevant reagents so it shows
# relevant_reagents = [str(item.lot) for item in
# self.relevant_reagents(assoc=looked_up_rt)]
relevant_reagents = [str(item.lot) for item in looked_up_rt.get_all_relevant_reagents()]
# logger.debug(f"Relevant reagents for {reagent.lot}: {relevant_reagents}")
# NOTE: if reagent in sheet is not found insert it into the front of relevant reagents so it shows
if str(reagent.lot) not in relevant_reagents:
if check_not_nan(reagent.lot):
relevant_reagents.insert(0, str(reagent.lot))
@@ -778,5 +762,20 @@ class SubmissionFormWidget(QWidget):
self.setToolTip(f"Enter lot number for the reagent used for {reagent.role}")
# self.setStyleSheet(main_form_style)
def relevant_reagents(self, assoc: KitTypeReagentRoleAssociation):
# logger.debug(f"Attempting lookup of reagents by type: {reagent.type}")
lookup = Reagent.query(reagent_role=assoc.reagent_role)
try:
regex = assoc.uses['exclude_regex']
except KeyError:
regex = "^$"
relevant_reagents = [item for item in lookup if
not check_regex_match(pattern=regex, check=str(item.lot))]
for rel_reagent in relevant_reagents:
# # NOTE: extract strings from any sets.
# if isinstance(rel_reagent, set):
# for thing in rel_reagent:
# yield thing
# elif isinstance(rel_reagent, str):
# yield rel_reagent
yield rel_reagent

View File

@@ -66,10 +66,11 @@
<h3><u>Plate map:</u></h3>
<img height="600px" width="1300px" src="data:image/jpeg;base64,{{ sub['export_map'] | safe }}">
{% endif %}
{% endblock %}
{% if signing_permission %}
<button type="button" id="sign_btn">Sign Off</button>
{% endif %}
{% endblock %}
<br>
<br>
<br>
@@ -94,10 +95,8 @@
{% endfor %}
document.getElementById("sign_btn").addEventListener("click", function(){
backend.sign_off("{{ sub['plate_number'] }}");
})
document.addEventListener('DOMContentLoaded', function() {
backend.activate_export(true);
}, false);
});
{% endblock %}
</script>
</html>