diff --git a/CHANGELOG.md b/CHANGELOG.md index 6450fba..2a3336f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 202306.03 + +- Improve WW plate mapping by using layout in submission forms rather than PCR. + ## 202306.02 - Addition of bacterial plate maps to details export. diff --git a/TODO.md b/TODO.md index 7d477eb..d563989 100644 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,7 @@ -- [ ] Improve plate mapping by using layout in submission forms rather than PCR. +- [ ] Move submission types from config.yml into database. +- [x] Solve bug for plate mapping when two samples of same name are in different rows. + - Try importing "L:\Robotics Laboratory Support\Submissions\Wastewater\2023\2023-06-21\RSL-WW-20230621-1.xlsx" for example. +- [x] Improve plate mapping by using layout in submission forms rather than PCR. - [x] Create a method for creation of hitpicking .csvs because of reasons that may or may not exist. - [x] Create a method for commenting submissions. - [x] Create barcode generator, because of reasons that may or may not exist. diff --git a/src/submissions/__init__.py b/src/submissions/__init__.py index 6bec4e6..67138a0 100644 --- a/src/submissions/__init__.py +++ b/src/submissions/__init__.py @@ -4,7 +4,7 @@ from pathlib import Path # Version of the realpython-reader package __project__ = "submissions" -__version__ = "202306.2b" +__version__ = "202306.3b" __author__ = {"name":"Landon Wark", "email":"Landon.Wark@phac-aspc.gc.ca"} __copyright__ = "2022-2023, Government of Canada" diff --git a/src/submissions/backend/excel/parser.py b/src/submissions/backend/excel/parser.py index 8fdd4d5..f0cce13 100644 --- a/src/submissions/backend/excel/parser.py +++ b/src/submissions/backend/excel/parser.py @@ -173,6 +173,7 @@ class SheetParser(object): elu_map = full.iloc[9:18, 5:] elu_map.set_index(elu_map.columns[0], inplace=True) elu_map.columns = elu_map.iloc[0] + elu_map = elu_map.tail(-1) return elu_map def parse_reagents(df:pd.DataFrame) -> None: """ @@ -274,10 +275,13 @@ class SheetParser(object): for c in df.columns.to_list(): logger.debug(f"Checking {ii.name}{c}") if check_not_nan(df.loc[ii.name, int(c)]) and df.loc[ii.name, int(c)] != "EMPTY": - - return_list.append(dict(sample_name=re.sub(r"\s?\(.*\)", "", df.loc[ii.name, int(c)]), \ + try: + return_list.append(dict(sample_name=re.sub(r"\s?\(.*\)", "", df.loc[ii.name, int(c)]), \ well=f"{ii.name}{c}", artic_plate=self.sub['rsl_plate_num'])) + except TypeError as e: + logger.error(f"Got an int for {c}, skipping.") + continue logger.debug(f"massaged sample list for {self.sub['rsl_plate_num']}: {pprint.pprint(return_list)}") return return_list submission_info = self.xl.parse("First Strand", dtype=object) @@ -355,8 +359,12 @@ class SampleParser(object): """ def search_df_for_sample(sample_rsl:str): logger.debug(f"Attempting to find sample {sample_rsl} in \n {self.elution_map}") - print(f"Attempting to find sample {sample_rsl} in \n {self.elution_map}") - well = self.elution_map.where(self.elution_map==sample_rsl).dropna(how='all').dropna(axis=1) + well = self.elution_map.where(self.elution_map==sample_rsl) + # logger.debug(f"Well: {well}") + well = well.dropna(how='all').dropna(axis=1, how="all") + if well.size > 1: + well = well.iloc[0].to_frame().dropna().T + logger.debug(f"well {sample_rsl} post processing: {well.size}: {type(well)}, {well.index[0]}, {well.columns[0]}") self.elution_map.at[well.index[0], well.columns[0]] = np.nan try: col = str(int(well.columns[0])) @@ -366,6 +374,7 @@ class SampleParser(object): logger.error(f"Problem parsing out column number for {well}:\n {e}") return f"{well.index[0]}{col}" new_list = [] + return_val = None for sample in self.samples: new = WWSample() if check_not_nan(sample["Unnamed: 7"]): @@ -389,9 +398,16 @@ class SampleParser(object): # new.site_status = sample['Unnamed: 7'] new.notes = str(sample['Unnamed: 6']) # previously Unnamed: 8 new.well_number = sample['Unnamed: 1'] - new.elution_well = search_df_for_sample(new.rsl_number) + elu_well = search_df_for_sample(new.rsl_number) + if elu_well != None: + new.elution_well = elu_well + else: + # try: + return_val += f"{new.rsl_number}\n" + # except TypeError: + # return_val = f"{new.rsl_number}\n" new_list.append(new) - return None, new_list + return return_val, new_list def parse_wastewater_artic_samples(self) -> Tuple[str|None, list[WWSample]]: """ diff --git a/src/submissions/frontend/main_window_functions.py b/src/submissions/frontend/main_window_functions.py index da00665..abf09ee 100644 --- a/src/submissions/frontend/main_window_functions.py +++ b/src/submissions/frontend/main_window_functions.py @@ -61,6 +61,9 @@ def import_submission_function(obj:QMainWindow) -> Tuple[QMainWindow, dict|None] if prsr.sub['rsl_plate_num'] == None: prsr.sub['rsl_plate_num'] = RSLNamer(fname.__str__()).parsed_name logger.debug(f"prsr.sub = {prsr.sub}") + for sample in prsr.sub['samples']: + if hasattr(sample, "elution_well"): + logger.debug(f"Sample from import: {sample.elution_well}") obj.current_submission_type = prsr.sub['submission_type'] # destroy any widgets from previous imports for item in obj.table_widget.formlayout.parentWidget().findChildren(QWidget):