From 8fee07b0c33ac7c38665ed6292077bd66f1a54ec Mon Sep 17 00:00:00 2001 From: lwark Date: Mon, 29 Sep 2025 12:22:50 -0500 Subject: [PATCH] Qubit sample results now written to export. --- .../backend/db/models/procedures.py | 2 +- .../backend/db/models/submissions.py | 2 +- .../backend/excel/parsers/__init__.py | 2 +- .../excel/writers/results_writers/__init__.py | 11 ++++++++++ .../results_writers/qubit_results_writer.py | 22 +++++-------------- src/submissions/backend/managers/__init__.py | 2 +- src/submissions/backend/validators/pydant.py | 10 ++++----- .../frontend/widgets/procedure_creation.py | 11 +++++++++- 8 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/submissions/backend/db/models/procedures.py b/src/submissions/backend/db/models/procedures.py index b137643..001c391 100644 --- a/src/submissions/backend/db/models/procedures.py +++ b/src/submissions/backend/db/models/procedures.py @@ -929,7 +929,7 @@ class Procedure(BaseClass): logger.info(f"Add Results! {resultstype_name}") from backend.managers import results results_manager = getattr(results, f"{resultstype_name}Manager") - rs = results_manager(procedure=self, parent=obj, fname=Path("C:\\Users\lwark\Documents\Submission_Forms\QubitData_18-09-2025_13-43-53.csv")) + rs = results_manager(procedure=self, parent=obj)#, fname=Path("C:\\Users\lwark\Documents\Submission_Forms\QubitData_18-09-2025_13-43-53.csv")) procedure = rs.procedure_to_pydantic() samples = rs.samples_to_pydantic() if procedure: diff --git a/src/submissions/backend/db/models/submissions.py b/src/submissions/backend/db/models/submissions.py index b44d00a..2fb69b1 100644 --- a/src/submissions/backend/db/models/submissions.py +++ b/src/submissions/backend/db/models/submissions.py @@ -1926,7 +1926,7 @@ class ProcedureSampleAssociation(BaseClass): # NOTE: Figure out how to merge the misc_info if doing .update instead. relevant = {k: v for k, v in output.items() if k not in ['sample']} output = output['sample'].details_dict() - logger.debug(output) + # logger.debug(output) misc = output['misc_info'] output.update(relevant) output['misc_info'] = misc diff --git a/src/submissions/backend/excel/parsers/__init__.py b/src/submissions/backend/excel/parsers/__init__.py index 15eac59..33d7fac 100644 --- a/src/submissions/backend/excel/parsers/__init__.py +++ b/src/submissions/backend/excel/parsers/__init__.py @@ -62,7 +62,7 @@ class DefaultParser(object): self.sheet = sheet if not start_row: start_row = self.__class__.start_row - if self.filepath.suffix == ".xslx": + if self.filepath.suffix == ".xlsx": self.workbook = load_workbook(self.filepath, data_only=True) self.worksheet = self.workbook[self.sheet] elif self.filepath.suffix == ".csv": diff --git a/src/submissions/backend/excel/writers/results_writers/__init__.py b/src/submissions/backend/excel/writers/results_writers/__init__.py index d3f896a..dc85748 100644 --- a/src/submissions/backend/excel/writers/results_writers/__init__.py +++ b/src/submissions/backend/excel/writers/results_writers/__init__.py @@ -1,6 +1,8 @@ """ """ +from openpyxl import Workbook + from backend.excel.writers import DefaultKEYVALUEWriter, DefaultTABLEWriter from backend.db.models import ProcedureType from tools import flatten_list @@ -16,6 +18,15 @@ class DefaultResultsSampleWriter(DefaultTABLEWriter): super().__init__(pydant_obj=pydant_obj, proceduretype=proceduretype, *args, **kwargs) self.pydant_obj = flatten_list([sample.results for sample in pydant_obj.sample]) + def write_to_workbook(self, workbook: Workbook, sheet: str | None = None, + start_row: int | None = None, *args, **kwargs) -> Workbook: + try: + self.worksheet = workbook[f"{self.proceduretype.name[:15]} Results"] + except KeyError: + self.worksheet = workbook.create_sheet(f"{self.proceduretype.name[:15]} Results") + # worksheet = workbook[f"{self.proceduretype.name[:15]} Results"] + return workbook + from .qubit_results_writer import QubitInfoWriter, QubitSampleWriter from .pcr_results_writer import PCRInfoWriter, PCRSampleWriter diff --git a/src/submissions/backend/excel/writers/results_writers/qubit_results_writer.py b/src/submissions/backend/excel/writers/results_writers/qubit_results_writer.py index b4c8cfc..66e0af1 100644 --- a/src/submissions/backend/excel/writers/results_writers/qubit_results_writer.py +++ b/src/submissions/backend/excel/writers/results_writers/qubit_results_writer.py @@ -1,16 +1,13 @@ """ -Writers for PCR results from Design and Analysis Software +Writers for PCR results from Qubit device """ from __future__ import annotations import logging from pprint import pformat -from typing import Generator, TYPE_CHECKING from openpyxl import Workbook from openpyxl.styles import Alignment from . import DefaultResultsInfoWriter, DefaultResultsSampleWriter -from tools import flatten_list -if TYPE_CHECKING: - from backend.db.models import ProcedureType + logger = logging.getLogger(f"submissions.{__name__}") @@ -24,16 +21,12 @@ class QubitInfoWriter(DefaultResultsInfoWriter): class QubitSampleWriter(DefaultResultsSampleWriter): def write_to_workbook(self, workbook: Workbook, *args, **kwargs) -> Workbook: - try: - self.worksheet = workbook[f"{self.proceduretype.name[:15]} Results"] - except KeyError: - self.worksheet = workbook.create_sheet(f"{self.proceduretype.name[:15]} Results") - # worksheet = workbook[f"{self.proceduretype.name[:15]} Results"] + workbook = super().write_to_workbook(workbook=workbook, *args, **kwargs) header_row = self.proceduretype.allowed_result_methods['Qubit']['sample']['start_row'] for iii, header in enumerate(self.column_headers, start=1): - logger.debug(f"Row: {header_row}, column: {iii}") + # logger.debug(f"Row: {header_row}, column: {iii}") self.worksheet.cell(row=header_row, column=iii, value=header.replace("_", " ").title()) - logger.debug(f"Column headers: {self.column_headers}") + # logger.debug(f"Column headers: {self.column_headers}") for iii, result in enumerate(self.pydant_obj, start = 1): row = header_row + iii for k, v in result.result.items(): @@ -42,7 +35,7 @@ class QubitSampleWriter(DefaultResultsSampleWriter): except StopIteration: print(f"fail for {k.replace('_', ' ').title()}") continue - logger.debug(f"Writing to row: {row}, column {column}") + # logger.debug(f"Writing to row: {row}, column {column}") cell = self.worksheet.cell(row=row, column=column) cell.value = v cell.alignment = Alignment(horizontal='left') @@ -56,6 +49,3 @@ class QubitSampleWriter(DefaultResultsSampleWriter): for k, value in result.result.items(): output.append(k) return sorted(list(set(output))) - - - diff --git a/src/submissions/backend/managers/__init__.py b/src/submissions/backend/managers/__init__.py index b556245..a98cbbe 100644 --- a/src/submissions/backend/managers/__init__.py +++ b/src/submissions/backend/managers/__init__.py @@ -15,7 +15,7 @@ class DefaultManager(object): def __init__(self, parent, input_object: Path | str | None = None): self.parent = parent - logger.debug(f"Input object: {pformat(input_object.__dict__)}") + match input_object: case str(): self.input_object = Path(input_object) diff --git a/src/submissions/backend/validators/pydant.py b/src/submissions/backend/validators/pydant.py index 7ab51c4..bb3f2ce 100644 --- a/src/submissions/backend/validators/pydant.py +++ b/src/submissions/backend/validators/pydant.py @@ -254,12 +254,12 @@ class PydReagent(PydBaseClass): report = Report() if self.model_extra is not None: self.__dict__.update(self.model_extra) - reagent, new = ReagentLot.query_or_create(lot=self.lot, name=self.name) + reagentlot, new = ReagentLot.query_or_create(lot=self.lot, name=self.name) if new: - reagentrole = ReagentRole.query(name=self.reagentrole) - reagent.reagentrole = reagentrole - reagent.expiry = self.expiry - return reagent, report + reagent = Reagent.query(name=self.name) + reagentlot.reagent = reagent + reagentlot.expiry = self.expiry + return reagentlot, report class PydSample(PydBaseClass): diff --git a/src/submissions/frontend/widgets/procedure_creation.py b/src/submissions/frontend/widgets/procedure_creation.py index 2c43698..fe46cc4 100644 --- a/src/submissions/frontend/widgets/procedure_creation.py +++ b/src/submissions/frontend/widgets/procedure_creation.py @@ -56,7 +56,15 @@ class ProcedureCreation(QDialog): proceduretype_dict = self.proceduretype.details_dict() # NOTE: Add --New-- as an option for reagents. for key, value in self.procedure.reagentrole.items(): - value.append(dict(name="--New--")) + try: + check = "--New--" in [v['name'] for v in value] + except TypeError: + try: + check = "--New--" in [v.name for v in value] + except (TypeError, AttributeError): + check = True + if not check: + value.append(dict(name="--New--")) if self.procedure.equipment: for equipmentrole in proceduretype_dict['equipment']: # NOTE: Check if procedure equipment is present and move to head of the list if so. @@ -150,6 +158,7 @@ class ProcedureCreation(QDialog): def add_new_reagent(self, reagentrole: str, name: str, lot: str, expiry: str): from backend.validators.pydant import PydReagent expiry = datetime.datetime.strptime(expiry, "%Y-%m-%d") + logger.debug(f"{reagentrole}, {name}, {lot}, {expiry}") pyd = PydReagent(reagentrole=reagentrole, name=name, lot=lot, expiry=expiry) self.procedure.reagentrole[reagentrole].insert(0, pyd) self.set_html()