From e35081392e85d2bbea372d24f0682c4cf8c28a34 Mon Sep 17 00:00:00 2001 From: Landon Wark Date: Mon, 18 Mar 2024 09:47:20 -0500 Subject: [PATCH] Adaptations to allow for stand alone scripts. --- src/submissions/backend/db/models/kits.py | 1 - .../backend/db/models/organizations.py | 9 ++++++++- src/submissions/backend/db/models/submissions.py | 4 ++-- src/submissions/backend/excel/parser.py | 11 +++++++---- src/submissions/backend/validators/pydant.py | 8 +++++--- .../frontend/widgets/submission_widget.py | 6 +++--- src/submissions/tools.py | 15 +++++++++------ 7 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/submissions/backend/db/models/kits.py b/src/submissions/backend/db/models/kits.py index 110a009..5aef6a0 100644 --- a/src/submissions/backend/db/models/kits.py +++ b/src/submissions/backend/db/models/kits.py @@ -339,7 +339,6 @@ class Reagent(BaseClass): submissions = association_proxy("reagent_submission_associations", "submission") #: Association proxy to SubmissionSampleAssociation.samples - def __repr__(self): if self.name != None: return f"" diff --git a/src/submissions/backend/db/models/organizations.py b/src/submissions/backend/db/models/organizations.py index a3ca0a3..9bfcd94 100644 --- a/src/submissions/backend/db/models/organizations.py +++ b/src/submissions/backend/db/models/organizations.py @@ -41,7 +41,8 @@ class Organization(BaseClass): @classmethod @setup_lookup - def query(cls, + def query(cls, + id:int|None=None, name:str|None=None, limit:int=0, ) -> Organization|List[Organization]: @@ -56,6 +57,12 @@ class Organization(BaseClass): Organization|List[Organization]: """ query: Query = cls.__database_session__.query(cls) + match id: + case int(): + query = query.filter(cls.id==id) + limit = 1 + case _: + pass match name: case str(): # logger.debug(f"Looking up organization with name: {name}") diff --git a/src/submissions/backend/db/models/submissions.py b/src/submissions/backend/db/models/submissions.py index ee42ad0..d092948 100644 --- a/src/submissions/backend/db/models/submissions.py +++ b/src/submissions/backend/db/models/submissions.py @@ -1242,9 +1242,9 @@ class Wastewater(BasicSubmission): outstr = super().enforce_name(instr=instr, data=data) try: outstr = re.sub(r"PCR(-|_)", "", outstr) - except AttributeError as e: + except (AttributeError, TypeError) as e: logger.error(f"Problem using regex: {e}") - outstr = RSLNamer.construct_new_plate_name(instr=outstr) + outstr = RSLNamer.construct_new_plate_name(data=data) outstr = outstr.replace("RSLWW", "RSL-WW") outstr = re.sub(r"WW(\d{4})", r"WW-\1", outstr, flags=re.IGNORECASE) outstr = re.sub(r"(\d{4})-(\d{2})-(\d{2})", r"\1\2\3", outstr) diff --git a/src/submissions/backend/excel/parser.py b/src/submissions/backend/excel/parser.py index de9ea1b..9111eba 100644 --- a/src/submissions/backend/excel/parser.py +++ b/src/submissions/backend/excel/parser.py @@ -274,7 +274,7 @@ class SampleParser(object): object to pull data for samples in excel sheet and construct individual sample objects """ - def __init__(self, xl:pd.ExcelFile, submission_type:str) -> None: + def __init__(self, xl:pd.ExcelFile, submission_type:str, sample_map:dict|None=None) -> None: """ convert sample sub-dataframe to dictionary of records @@ -286,7 +286,7 @@ class SampleParser(object): self.samples = [] self.xl = xl self.submission_type = submission_type - sample_info_map = self.fetch_sample_info_map(submission_type=submission_type) + sample_info_map = self.fetch_sample_info_map(submission_type=submission_type, sample_map=sample_map) logger.debug(f"sample_info_map: {sample_info_map}") self.plate_map = self.construct_plate_map(plate_map_location=sample_info_map['plate_map']) logger.debug(f"plate_map: {self.plate_map}") @@ -298,7 +298,7 @@ class SampleParser(object): if isinstance(self.lookup_table, pd.DataFrame): self.parse_lookup_table() - def fetch_sample_info_map(self, submission_type:str) -> dict: + def fetch_sample_info_map(self, submission_type:str, sample_map:dict|None=None) -> dict: """ Gets info locations in excel book for submission type. @@ -311,7 +311,10 @@ class SampleParser(object): logger.debug(f"Looking up submission type: {submission_type}") submission_type = SubmissionType.query(name=submission_type) logger.debug(f"info_map: {pformat(submission_type.info_map)}") - sample_info_map = submission_type.info_map['samples'] + if sample_map is None: + sample_info_map = submission_type.info_map['samples'] + else: + sample_info_map = sample_map self.custom_sub_parser = BasicSubmission.find_polymorphic_subclass(polymorphic_identity=submission_type.name).parse_samples self.custom_sample_parser = BasicSample.find_polymorphic_subclass(polymorphic_identity=f"{submission_type.name} Sample").parse_sample return sample_info_map diff --git a/src/submissions/backend/validators/pydant.py b/src/submissions/backend/validators/pydant.py index f8b888c..078d95b 100644 --- a/src/submissions/backend/validators/pydant.py +++ b/src/submissions/backend/validators/pydant.py @@ -518,7 +518,7 @@ class PydSubmission(BaseModel, extra='allow'): case "samples": for sample in self.samples: sample, associations, _ = sample.toSQL(submission=instance) - logger.debug(f"Sample SQL object to be added to submission: {sample.__dict__}") + # logger.debug(f"Sample SQL object to be added to submission: {sample.__dict__}") for assoc in associations: instance.submission_sample_associations.append(assoc) case "equipment": @@ -534,7 +534,6 @@ class PydSubmission(BaseModel, extra='allow'): association.save() logger.debug(f"Equipment association SQL object to be added to submission: {association.__dict__}") instance.submission_equipment_associations.append(association) - case _: try: instance.set_attribute(key=key, value=value) @@ -548,7 +547,10 @@ class PydSubmission(BaseModel, extra='allow'): instance.calculate_base_cost() except (TypeError, AttributeError) as e: logger.debug(f"Looks like that kit doesn't have cost breakdown yet due to: {e}, using full plate cost.") - instance.run_cost = instance.extraction_kit.cost_per_run + try: + instance.run_cost = instance.extraction_kit.cost_per_run + except AttributeError: + instance.run_cost = 0 logger.debug(f"Calculated base run cost of: {instance.run_cost}") # Apply any discounts that are applicable for client and kit. try: diff --git a/src/submissions/frontend/widgets/submission_widget.py b/src/submissions/frontend/widgets/submission_widget.py index c74d510..60bbe08 100644 --- a/src/submissions/frontend/widgets/submission_widget.py +++ b/src/submissions/frontend/widgets/submission_widget.py @@ -469,11 +469,11 @@ class SubmissionFormWidget(QWidget): Args: fname (Path | None, optional): Input filename. Defaults to None. """ - pyd = self.parse_form() + self.parse_form() if isinstance(fname, bool) or fname == None: - fname = select_save_file(obj=self, default_name=pyd.construct_filename(), extension="csv") + fname = select_save_file(obj=self, default_name=self.pyd.construct_filename(), extension="csv") try: - pyd.csv.to_csv(fname.__str__(), index=False) + self.pyd.csv.to_csv(fname.__str__(), index=False) except PermissionError: logger.debug(f"Could not get permissions to {fname}. Possibly the request was cancelled.") diff --git a/src/submissions/tools.py b/src/submissions/tools.py index 8d6cef0..9564f9e 100644 --- a/src/submissions/tools.py +++ b/src/submissions/tools.py @@ -117,12 +117,15 @@ def check_regex_match(pattern:str, check:str) -> bool: return False def get_first_blank_df_row(df:pd.DataFrame) -> int: - #First, find NaN entries in first column - # blank_row_bool = df.iloc[:,2].isna() - # logger.debug(f"Blank row bool: {blank_row_bool}") - # #Next, get index of first NaN entry - # blank_row_index = [i for i, x in enumerate(blank_row_bool) if x][0] - # return blank_row_index + """ + For some reason I need a whole function for this. + + Args: + df (pd.DataFrame): Input dataframe. + + Returns: + int: Index of the row after the last used row. + """ return df.shape[0] + 1 # Settings