Improve plate mapping by using layout in submission forms rather than PCR. Pre-moving excel maps to DB.
This commit is contained in:
@@ -1,3 +1,7 @@
|
|||||||
|
## 202306.03
|
||||||
|
|
||||||
|
- Improve WW plate mapping by using layout in submission forms rather than PCR.
|
||||||
|
|
||||||
## 202306.02
|
## 202306.02
|
||||||
|
|
||||||
- Addition of bacterial plate maps to details export.
|
- Addition of bacterial plate maps to details export.
|
||||||
|
|||||||
5
TODO.md
5
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 creation of hitpicking .csvs because of reasons that may or may not exist.
|
||||||
- [x] Create a method for commenting submissions.
|
- [x] Create a method for commenting submissions.
|
||||||
- [x] Create barcode generator, because of reasons that may or may not exist.
|
- [x] Create barcode generator, because of reasons that may or may not exist.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
# Version of the realpython-reader package
|
# Version of the realpython-reader package
|
||||||
__project__ = "submissions"
|
__project__ = "submissions"
|
||||||
__version__ = "202306.2b"
|
__version__ = "202306.3b"
|
||||||
__author__ = {"name":"Landon Wark", "email":"Landon.Wark@phac-aspc.gc.ca"}
|
__author__ = {"name":"Landon Wark", "email":"Landon.Wark@phac-aspc.gc.ca"}
|
||||||
__copyright__ = "2022-2023, Government of Canada"
|
__copyright__ = "2022-2023, Government of Canada"
|
||||||
|
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ class SheetParser(object):
|
|||||||
elu_map = full.iloc[9:18, 5:]
|
elu_map = full.iloc[9:18, 5:]
|
||||||
elu_map.set_index(elu_map.columns[0], inplace=True)
|
elu_map.set_index(elu_map.columns[0], inplace=True)
|
||||||
elu_map.columns = elu_map.iloc[0]
|
elu_map.columns = elu_map.iloc[0]
|
||||||
|
elu_map = elu_map.tail(-1)
|
||||||
return elu_map
|
return elu_map
|
||||||
def parse_reagents(df:pd.DataFrame) -> None:
|
def parse_reagents(df:pd.DataFrame) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -274,10 +275,13 @@ class SheetParser(object):
|
|||||||
for c in df.columns.to_list():
|
for c in df.columns.to_list():
|
||||||
logger.debug(f"Checking {ii.name}{c}")
|
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":
|
if check_not_nan(df.loc[ii.name, int(c)]) and df.loc[ii.name, int(c)] != "EMPTY":
|
||||||
|
try:
|
||||||
return_list.append(dict(sample_name=re.sub(r"\s?\(.*\)", "", df.loc[ii.name, int(c)]), \
|
return_list.append(dict(sample_name=re.sub(r"\s?\(.*\)", "", df.loc[ii.name, int(c)]), \
|
||||||
well=f"{ii.name}{c}",
|
well=f"{ii.name}{c}",
|
||||||
artic_plate=self.sub['rsl_plate_num']))
|
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)}")
|
logger.debug(f"massaged sample list for {self.sub['rsl_plate_num']}: {pprint.pprint(return_list)}")
|
||||||
return return_list
|
return return_list
|
||||||
submission_info = self.xl.parse("First Strand", dtype=object)
|
submission_info = self.xl.parse("First Strand", dtype=object)
|
||||||
@@ -355,8 +359,12 @@ class SampleParser(object):
|
|||||||
"""
|
"""
|
||||||
def search_df_for_sample(sample_rsl:str):
|
def search_df_for_sample(sample_rsl:str):
|
||||||
logger.debug(f"Attempting to find sample {sample_rsl} in \n {self.elution_map}")
|
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)
|
||||||
well = self.elution_map.where(self.elution_map==sample_rsl).dropna(how='all').dropna(axis=1)
|
# 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
|
self.elution_map.at[well.index[0], well.columns[0]] = np.nan
|
||||||
try:
|
try:
|
||||||
col = str(int(well.columns[0]))
|
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}")
|
logger.error(f"Problem parsing out column number for {well}:\n {e}")
|
||||||
return f"{well.index[0]}{col}"
|
return f"{well.index[0]}{col}"
|
||||||
new_list = []
|
new_list = []
|
||||||
|
return_val = None
|
||||||
for sample in self.samples:
|
for sample in self.samples:
|
||||||
new = WWSample()
|
new = WWSample()
|
||||||
if check_not_nan(sample["Unnamed: 7"]):
|
if check_not_nan(sample["Unnamed: 7"]):
|
||||||
@@ -389,9 +398,16 @@ class SampleParser(object):
|
|||||||
# new.site_status = sample['Unnamed: 7']
|
# new.site_status = sample['Unnamed: 7']
|
||||||
new.notes = str(sample['Unnamed: 6']) # previously Unnamed: 8
|
new.notes = str(sample['Unnamed: 6']) # previously Unnamed: 8
|
||||||
new.well_number = sample['Unnamed: 1']
|
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)
|
new_list.append(new)
|
||||||
return None, new_list
|
return return_val, new_list
|
||||||
|
|
||||||
def parse_wastewater_artic_samples(self) -> Tuple[str|None, list[WWSample]]:
|
def parse_wastewater_artic_samples(self) -> Tuple[str|None, list[WWSample]]:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ def import_submission_function(obj:QMainWindow) -> Tuple[QMainWindow, dict|None]
|
|||||||
if prsr.sub['rsl_plate_num'] == None:
|
if prsr.sub['rsl_plate_num'] == None:
|
||||||
prsr.sub['rsl_plate_num'] = RSLNamer(fname.__str__()).parsed_name
|
prsr.sub['rsl_plate_num'] = RSLNamer(fname.__str__()).parsed_name
|
||||||
logger.debug(f"prsr.sub = {prsr.sub}")
|
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']
|
obj.current_submission_type = prsr.sub['submission_type']
|
||||||
# destroy any widgets from previous imports
|
# destroy any widgets from previous imports
|
||||||
for item in obj.table_widget.formlayout.parentWidget().findChildren(QWidget):
|
for item in obj.table_widget.formlayout.parentWidget().findChildren(QWidget):
|
||||||
|
|||||||
Reference in New Issue
Block a user