Conversion of some functions to generators.

This commit is contained in:
lwark
2024-07-31 13:08:56 -05:00
parent eb6cdc63e2
commit 8266275354
15 changed files with 374 additions and 369 deletions

View File

@@ -84,7 +84,7 @@ class ControlType(BaseClass):
Returns:
List[ControlType]: Control types that have targets
"""
return [item for item in cls.query() if item.targets]# != []]
return [item for item in cls.query() if item.targets]
@classmethod
def build_positive_regex(cls) -> Pattern:
@@ -141,7 +141,9 @@ class Control(BaseClass):
# logger.debug("calculating kraken count total to use in percentage")
kraken_cnt_total = sum([kraken[item]['kraken_count'] for item in kraken])
# logger.debug("Creating new kraken.")
new_kraken = [dict(name=item, kraken_count=kraken[item]['kraken_count'], kraken_percent="{0:.0%}".format(kraken[item]['kraken_count'] / kraken_cnt_total)) for item in kraken]
new_kraken = [dict(name=item, kraken_count=kraken[item]['kraken_count'],
kraken_percent="{0:.0%}".format(kraken[item]['kraken_count'] / kraken_cnt_total)) for item in
kraken]
new_kraken = sorted(new_kraken, key=itemgetter('kraken_count'), reverse=True)
# logger.debug("setting targets")
if not self.controltype.targets:

View File

@@ -8,7 +8,7 @@ from sqlalchemy.ext.associationproxy import association_proxy
from datetime import date
import logging, re
from tools import check_authorization, setup_lookup, Report, Result
from typing import List, Literal
from typing import List, Literal, Generator
from pandas import ExcelFile
from pathlib import Path
from . import Base, BaseClass, Organization
@@ -168,9 +168,9 @@ 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) -> dict:
def construct_xl_map_for_use(self, submission_type: str | SubmissionType) -> Generator[str, str]:
"""
Creates map of locations in excel workbook for a SubmissionType
Creates map of locations in Excel workbook for a SubmissionType
Args:
submission_type (str | SubmissionType): Submissiontype.name
@@ -178,7 +178,7 @@ class KitType(BaseClass):
Returns:
dict: Dictionary containing information locations.
"""
info_map = {}
# info_map = {}
# NOTE: Account for submission_type variable type.
match submission_type:
case str():
@@ -193,10 +193,10 @@ class KitType(BaseClass):
# logger.debug("Get all KitTypeReagentTypeAssociation for SubmissionType")
for assoc in assocs:
try:
info_map[assoc.reagent_role.name] = assoc.uses
yield assoc.reagent_role.name, assoc.uses
except TypeError:
continue
return info_map
# return info_map
@classmethod
@setup_lookup
@@ -409,6 +409,7 @@ class Reagent(BaseClass):
rtype = reagent_role.name.replace("_", " ")
except AttributeError:
rtype = "Unknown"
# logger.debug(f"Role for {self.name}: {rtype}")
# NOTE: Calculate expiry with EOL from ReagentType
try:
place_holder = self.expiry + reagent_role.eol_ext
@@ -611,7 +612,8 @@ class SubmissionType(BaseClass):
) #: Association of equipmentroles
equipment = association_proxy("submissiontype_equipmentrole_associations", "equipment_role",
creator=lambda eq: SubmissionTypeEquipmentRoleAssociation(equipment_role=eq)) #: Proxy of equipmentrole associations
creator=lambda eq: SubmissionTypeEquipmentRoleAssociation(
equipment_role=eq)) #: Proxy of equipmentrole associations
submissiontype_kit_rt_associations = relationship(
"KitTypeReagentRoleAssociation",
@@ -665,7 +667,7 @@ class SubmissionType(BaseClass):
def construct_info_map(self, mode: Literal['read', 'write']) -> dict:
"""
Make of map of where all fields are located in excel sheet
Make of map of where all fields are located in Excel sheet
Args:
mode (Literal["read", "write"]): Which mode to get locations for
@@ -673,15 +675,16 @@ class SubmissionType(BaseClass):
Returns:
dict: Map of locations
"""
info = {k:v for k,v in self.info_map.items() if k != "custom"}
info = {k: v for k, v in self.info_map.items() if k != "custom"}
logger.debug(f"Info map: {info}")
output = {}
match mode:
case "read":
output = {k: v[mode] for k, v in info.items() if v[mode]}
case "write":
output = {k: v[mode] + v['read'] for k, v in info.items() if v[mode] or v['read']}
output = {k: v for k, v in output.items() if all([isinstance(item, dict) for item in v])}
case _:
output = {}
output['custom'] = self.info_map['custom']
return output
@@ -694,36 +697,38 @@ class SubmissionType(BaseClass):
"""
return self.sample_map
def construct_equipment_map(self) -> dict:
def construct_equipment_map(self) -> Generator[str, dict]:
"""
Constructs map of equipment to excel cells.
Returns:
dict: Map equipment locations in excel sheet
"""
output = {}
# output = {}
# logger.debug("Iterating through equipment roles")
for item in self.submissiontype_equipmentrole_associations:
emap = item.uses
if emap is None:
emap = {}
output[item.equipment_role.name] = emap
return output
# output[item.equipment_role.name] = emap
yield item.equipment_role.name, emap
# return output
def construct_tips_map(self) -> dict:
def construct_tips_map(self) -> Generator[str, dict]:
"""
Constructs map of tips to excel cells.
Returns:
dict: Tip locations in the excel sheet.
"""
output = {}
# output = {}
for item in self.submissiontype_tiprole_associations:
tmap = item.uses
if tmap is None:
tmap = {}
output[item.tip_role.name] = tmap
return output
# output[item.tip_role.name] = tmap
yield item.tip_role.name, tmap
# return output
def get_equipment(self, extraction_kit: str | KitType | None = None) -> List['PydEquipmentRole']:
"""
@@ -1280,15 +1285,16 @@ class EquipmentRole(BaseClass):
Returns:
dict: This EquipmentRole dict
"""
output = {}
for key, value in self.__dict__.items():
match key:
case "processes":
pass
case _:
value = value
output[key] = value
return output
# output = {}
return {key: value for key, value in self.__dict__.items() if key != "processes"}
# match key:
# case "processes":
# pass
# case _:
# value = value
# yield key, value
# # output[key] = value
# return output
def to_pydantic(self, submission_type: SubmissionType,
extraction_kit: str | KitType | None = None) -> "PydEquipmentRole":
@@ -1668,7 +1674,6 @@ class SubmissionTipsAssociation(BaseClass):
back_populates="tips_submission_associations") #: associated equipment
role_name = Column(String(32), primary_key=True) #, ForeignKey("_tiprole.name"))
def to_sub_dict(self) -> dict:
"""
This item as a dictionary

View File

@@ -25,7 +25,7 @@ from openpyxl.worksheet.worksheet import Worksheet
from openpyxl.drawing.image import Image as OpenpyxlImage
from tools import row_map, setup_lookup, jinja_template_loading, rreplace, row_keys, check_key_or_attr, Result, Report
from datetime import datetime, date
from typing import List, Any, Tuple, Literal
from typing import List, Any, Tuple, Literal, Generator
from dateutil.parser import parse
from pathlib import Path
from jinja2.exceptions import TemplateNotFound
@@ -289,7 +289,7 @@ class BasicSubmission(BaseClass):
try:
reagents = [item.to_sub_dict(extraction_kit=self.extraction_kit) for item in
self.submission_reagent_associations]
for k in self.extraction_kit.construct_xl_map_for_use(self.submission_type):
for k, v in self.extraction_kit.construct_xl_map_for_use(self.submission_type):
if k == 'info':
continue
if not any([item['role'] == k for item in reagents]):
@@ -841,6 +841,7 @@ class BasicSubmission(BaseClass):
for k, v in fields.items():
sheet = xl[v['sheet']]
sample[k] = sheet.cell(row=idx, column=v['column']).value
# yield sample
samples.append(sample)
return samples
@@ -1381,7 +1382,7 @@ class Wastewater(BasicSubmission):
return input_dict
@classmethod
def parse_pcr(cls, xl: Workbook, rsl_plate_num: str) -> list:
def parse_pcr(cls, xl: Workbook, rsl_plate_num: str) -> List[dict]:
"""
Parse specific to wastewater samples.
"""
@@ -1393,6 +1394,7 @@ class Wastewater(BasicSubmission):
sample['sample'] = re.sub('-N\\d$', '', sample['sample'])
# NOTE: if sample is already in output skip
if sample['sample'] in [item['sample'] for item in output]:
logger.warning(f"Already have {sample['sample']}")
continue
# NOTE: Set ct values
sample[f"ct_{sample['target'].lower()}"] = sample['ct'] if isinstance(sample['ct'], float) else 0.0

View File

@@ -84,8 +84,9 @@ class SheetParser(object):
if extraction_kit is None:
extraction_kit = self.sub['extraction_kit']
# logger.debug(f"Parsing reagents for {extraction_kit}")
self.sub['reagents'] = ReagentParser(xl=self.xl, submission_type=self.submission_type,
extraction_kit=extraction_kit).parse_reagents()
parser = ReagentParser(xl=self.xl, submission_type=self.submission_type,
extraction_kit=extraction_kit)
self.sub['reagents'] = [item for item in parser.parse_reagents()]
def parse_samples(self):
"""
@@ -303,21 +304,21 @@ class ReagentParser(object):
if isinstance(submission_type, dict):
submission_type = submission_type['value']
reagent_map = self.kit_object.construct_xl_map_for_use(submission_type)
reagent_map = {k: v for k, v in self.kit_object.construct_xl_map_for_use(submission_type)}
try:
del reagent_map['info']
except KeyError:
pass
return reagent_map
def parse_reagents(self) -> List[dict]:
def parse_reagents(self) -> Generator[dict, None, None]:
"""
Extracts reagent information from the excel form.
Extracts reagent information from the Excel form.
Returns:
List[PydReagent]: List of parsed reagents.
"""
listo = []
# listo = []
for sheet in self.xl.sheetnames:
ws = self.xl[sheet]
relevant = {k.strip(): v for k, v in self.map.items() if sheet in self.map[k]['sheet']}
@@ -337,9 +338,8 @@ class ReagentParser(object):
else:
comment = ""
except (KeyError, IndexError):
listo.append(
dict(role=item.strip(), lot=None, expiry=None, name=None, comment="", missing=True))
continue
yield dict(role=item.strip(), lot=None, expiry=None, name=None, comment="", missing=True)
# continue
# NOTE: If the cell is blank tell the PydReagent
if check_not_nan(lot):
missing = False
@@ -355,9 +355,9 @@ class ReagentParser(object):
logger.warning(f"name is not a string.")
check = True
if check:
listo.append(dict(role=item.strip(), lot=lot, expiry=expiry, name=name, comment=comment,
missing=missing))
return listo
yield dict(role=item.strip(), lot=lot, expiry=expiry, name=name, comment=comment,
missing=missing)
# return listo
class SampleParser(object):
@@ -556,14 +556,14 @@ class EquipmentParser(object):
self.xl = xl
self.map = self.fetch_equipment_map()
def fetch_equipment_map(self) -> List[dict]:
def fetch_equipment_map(self) -> dict:
"""
Gets the map of equipment locations in the submission type's spreadsheet
Returns:
List[dict]: List of locations
"""
return self.submission_type.construct_equipment_map()
return {k: v for k, v in self.submission_type.construct_equipment_map()}
def get_asset_number(self, input: str) -> str:
"""
@@ -642,14 +642,14 @@ class TipParser(object):
self.xl = xl
self.map = self.fetch_tip_map()
def fetch_tip_map(self) -> List[dict]:
def fetch_tip_map(self) -> dict:
"""
Gets the map of equipment locations in the submission type's spreadsheet
Returns:
List[dict]: List of locations
"""
return self.submission_type.construct_tips_map()
return {k:v for k,v in self.submission_type.construct_tips_map()}
def parse_tips(self) -> List[dict]:
"""

View File

@@ -20,22 +20,20 @@ env = jinja_template_loading()
class ReportMaker(object):
def __init__(self, start_date: date, end_date: date):
subs = BasicSubmission.query(start_date=start_date, end_date=end_date)
records = [item.to_dict(report=True) for item in subs]
self.detailed_df, self.summary_df = self.make_report_xlsx(records=records)
self.html = self.make_report_html(df=self.summary_df, start_date=start_date, end_date=end_date)
self.start_date = start_date
self.end_date = end_date
self.subs = BasicSubmission.query(start_date=start_date, end_date=end_date)
self.detailed_df, self.summary_df = self.make_report_xlsx()
self.html = self.make_report_html(df=self.summary_df)
def make_report_xlsx(self, records: list[dict]) -> Tuple[DataFrame, DataFrame]:
def make_report_xlsx(self) -> Tuple[DataFrame, DataFrame]:
"""
create the dataframe for a report
Args:
records (list[dict]): list of dictionaries created from submissions
Returns:
DataFrame: output dataframe
"""
df = DataFrame.from_records(records)
df = DataFrame.from_records([item.to_dict(report=True) for item in self.subs])
# NOTE: put submissions with the same lab together
df = df.sort_values("submitting_lab")
# NOTE: aggregate cost and sample count columns
@@ -47,7 +45,7 @@ class ReportMaker(object):
df = df.sort_values(['submitting_lab', "submitted_date"])
return df, df2
def make_report_html(self, df: DataFrame, start_date: date, end_date: date) -> str:
def make_report_html(self, df: DataFrame) -> str:
"""
generates html from the report dataframe
@@ -84,7 +82,7 @@ class ReportMaker(object):
output.append(adder)
old_lab = lab
# logger.debug(output)
dicto = {'start_date': start_date, 'end_date': end_date, 'labs': output}
dicto = {'start_date': self.start_date, 'end_date': self.end_date, 'labs': output}
temp = env.get_template('summary_report.html')
html = temp.render(input=dicto)
return html

View File

@@ -1,13 +1,13 @@
'''
contains writer objects for pushing values to submission sheet templates.
'''
"""
contains writer objects for pushing values to submission sheet templates.
"""
import logging
from copy import copy
from operator import itemgetter
from pathlib import Path
# from pathlib import Path
from pprint import pformat
from typing import List
from typing import List, Generator
from openpyxl import load_workbook, Workbook
from backend.db.models import SubmissionType, KitType, BasicSubmission
from backend.validators.pydant import PydSubmission
@@ -30,7 +30,7 @@ class SheetWriter(object):
Args:
submission (PydSubmission): Object containing submission information.
missing_only (bool, optional): Whether to only fill in missing values. Defaults to False.
"""
"""
self.sub = OrderedDict(submission.improved_dict())
for k, v in self.sub.items():
match k:
@@ -47,7 +47,6 @@ class SheetWriter(object):
else:
self.sub[k] = v
# logger.debug(f"\n\nWriting to {submission.filepath.__str__()}\n\n")
if self.filepath.stem.startswith("tmp"):
template = self.submission_type.template_file
workbook = load_workbook(BytesIO(template))
@@ -124,7 +123,7 @@ class InfoWriter(object):
submission_type (SubmissionType | str): Type of submission expected (Wastewater, Bacterial Culture, etc.)
info_dict (dict): Dictionary of information to write.
sub_object (BasicSubmission | None, optional): Submission object containing methods. Defaults to None.
"""
"""
logger.debug(f"Info_dict coming into InfoWriter: {pformat(info_dict)}")
if isinstance(submission_type, str):
submission_type = SubmissionType.query(name=submission_type)
@@ -148,7 +147,7 @@ class InfoWriter(object):
Returns:
dict: merged dictionary
"""
output = {}
# output = {}
for k, v in info_dict.items():
if v is None:
continue
@@ -162,9 +161,10 @@ class InfoWriter(object):
pass
dicto['value'] = v
if len(dicto) > 0:
output[k] = dicto
# output[k] = dicto
yield k, dicto
# logger.debug(f"Reconciled info: {pformat(output)}")
return output
# return output
def write_info(self) -> Workbook:
"""
@@ -173,7 +173,7 @@ class InfoWriter(object):
Returns:
Workbook: workbook with info written.
"""
for k, v in self.info.items():
for k, v in self.info:
# NOTE: merge all comments to fit in single cell.
if k == "comment" and isinstance(v['value'], list):
json_join = [item['text'] for item in v['value'] if 'text' in item.keys()]
@@ -203,16 +203,17 @@ class ReagentWriter(object):
submission_type (SubmissionType | str): Type of submission expected (Wastewater, Bacterial Culture, etc.)
extraction_kit (KitType | str): Extraction kit used.
reagent_list (list): List of reagent dicts to be written to excel.
"""
"""
self.xl = xl
if isinstance(submission_type, str):
submission_type = SubmissionType.query(name=submission_type)
if isinstance(extraction_kit, str):
kit_type = KitType.query(name=extraction_kit)
reagent_map = kit_type.construct_xl_map_for_use(submission_type)
reagent_map = {k: v for k, v in kit_type.construct_xl_map_for_use(submission_type)}
# self.reagents = {k: v for k, v in self.reconcile_map(reagent_list=reagent_list, reagent_map=reagent_map)}
self.reagents = self.reconcile_map(reagent_list=reagent_list, reagent_map=reagent_map)
def reconcile_map(self, reagent_list: List[dict], reagent_map: dict) -> List[dict]:
def reconcile_map(self, reagent_list: List[dict], reagent_map: dict) -> Generator[dict, None, None]:
"""
Merge reagents with their locations
@@ -223,7 +224,7 @@ class ReagentWriter(object):
Returns:
List[dict]: merged dictionary
"""
output = []
# output = []
for reagent in reagent_list:
try:
mp_info = reagent_map[reagent['role']]
@@ -238,8 +239,9 @@ class ReagentWriter(object):
dicto = v
placeholder[k] = dicto
placeholder['sheet'] = mp_info['sheet']
output.append(placeholder)
return output
# output.append(placeholder)
yield placeholder
# return output
def write_reagents(self) -> Workbook:
"""
@@ -263,21 +265,24 @@ class SampleWriter(object):
"""
object to write sample data into excel file
"""
def __init__(self, xl: Workbook, submission_type: SubmissionType | str, sample_list: list):
"""
Args:
xl (Workbook): Openpyxl workbook from submitted excel file.
submission_type (SubmissionType | str): Type of submission expected (Wastewater, Bacterial Culture, etc.)
sample_list (list): List of sample dictionaries to be written to excel file.
"""
"""
if isinstance(submission_type, str):
submission_type = SubmissionType.query(name=submission_type)
self.submission_type = submission_type
self.xl = xl
self.sample_map = submission_type.construct_sample_map()['lookup_table']
self.samples = self.reconcile_map(sample_list)
# self.samples = self.reconcile_map(sample_list)
samples = [item for item in self.reconcile_map(sample_list)]
self.samples = sorted(samples, key=lambda k: k['submission_rank'])
def reconcile_map(self, sample_list: list) -> List[dict]:
def reconcile_map(self, sample_list: list) -> Generator[dict, None, None]:
"""
Merge sample info with locations
@@ -287,7 +292,7 @@ class SampleWriter(object):
Returns:
List[dict]: List of merged dictionaries
"""
output = []
# output = []
multiples = ['row', 'column', 'assoc_id', 'submission_rank']
for sample in sample_list:
# logger.debug(f"Writing sample: {sample}")
@@ -297,8 +302,8 @@ class SampleWriter(object):
if k in multiples:
continue
new[k] = v
output.append(new)
return sorted(output, key=lambda k: k['submission_rank'])
yield new
# return sorted(output, key=lambda k: k['submission_rank'])
def write_samples(self) -> Workbook:
"""
@@ -331,15 +336,15 @@ class EquipmentWriter(object):
xl (Workbook): Openpyxl workbook from submitted excel file.
submission_type (SubmissionType | str): Type of submission expected (Wastewater, Bacterial Culture, etc.)
equipment_list (list): List of equipment dictionaries to write to excel file.
"""
"""
if isinstance(submission_type, str):
submission_type = SubmissionType.query(name=submission_type)
self.submission_type = submission_type
self.xl = xl
equipment_map = self.submission_type.construct_equipment_map()
equipment_map = {k: v for k, v in self.submission_type.construct_equipment_map()}
self.equipment = self.reconcile_map(equipment_list=equipment_list, equipment_map=equipment_map)
def reconcile_map(self, equipment_list: list, equipment_map: dict) -> List[dict]:
def reconcile_map(self, equipment_list: list, equipment_map: dict) -> Generator[dict, None, None]:
"""
Merges equipment with location data
@@ -350,9 +355,9 @@ class EquipmentWriter(object):
Returns:
List[dict]: List of merged dictionaries
"""
output = []
# output = []
if equipment_list is None:
return output
return
for ii, equipment in enumerate(equipment_list, start=1):
mp_info = equipment_map[equipment['role']]
# logger.debug(f"{equipment['role']} map: {mp_info}")
@@ -376,8 +381,9 @@ class EquipmentWriter(object):
except KeyError:
placeholder['sheet'] = "Equipment"
# logger.debug(f"Final output of {equipment['role']} : {placeholder}")
output.append(placeholder)
return output
yield placeholder
# output.append(placeholder)
# return output
def write_equipment(self) -> Workbook:
"""
@@ -419,15 +425,15 @@ class TipWriter(object):
xl (Workbook): Openpyxl workbook from submitted excel file.
submission_type (SubmissionType | str): Type of submission expected (Wastewater, Bacterial Culture, etc.)
tips_list (list): List of tip dictionaries to write to the excel file.
"""
"""
if isinstance(submission_type, str):
submission_type = SubmissionType.query(name=submission_type)
self.submission_type = submission_type
self.xl = xl
tips_map = self.submission_type.construct_tips_map()
tips_map = {k: v for k, v in self.submission_type.construct_tips_map()}
self.tips = self.reconcile_map(tips_list=tips_list, tips_map=tips_map)
def reconcile_map(self, tips_list: List[dict], tips_map: dict) -> List[dict]:
def reconcile_map(self, tips_list: List[dict], tips_map: dict) -> Generator[dict, None, None]:
"""
Merges tips with location data
@@ -438,9 +444,9 @@ class TipWriter(object):
Returns:
List[dict]: List of merged dictionaries
"""
output = []
# output = []
if tips_list is None:
return output
return
for ii, tips in enumerate(tips_list, start=1):
mp_info = tips_map[tips['role']]
# logger.debug(f"{tips['role']} map: {mp_info}")
@@ -462,8 +468,9 @@ class TipWriter(object):
except KeyError:
placeholder['sheet'] = "Tips"
# logger.debug(f"Final output of {tips['role']} : {placeholder}")
output.append(placeholder)
return output
yield placeholder
# output.append(placeholder)
# return output
def write_tips(self) -> Workbook:
"""
@@ -497,13 +504,13 @@ class TipWriter(object):
class DocxWriter(object):
"""
Object to render
"""
"""
def __init__(self, base_dict: dict):
"""
Args:
base_dict (dict): dictionary of info to be written to template.
"""
"""
self.sub_obj = BasicSubmission.find_polymorphic_subclass(polymorphic_identity=base_dict['submission_type'])
env = jinja_template_loading()
temp_name = f"{base_dict['submission_type'].replace(' ', '').lower()}_subdocument.docx"
@@ -530,12 +537,12 @@ class DocxWriter(object):
rows = max([sample['row'] for sample in sample_list])
if columns == 0:
columns = max([sample['column'] for sample in sample_list])
output = []
# output = []
for row in range(0, rows):
contents = [''] * columns
for column in range(0, columns):
try:
ooi = [item for item in sample_list if item['row']==row+1 and item['column']==column+1][0]
ooi = [item for item in sample_list if item['row'] == row + 1 and item['column'] == column + 1][0]
except IndexError:
continue
contents[column] = ooi['submitter_id']
@@ -545,8 +552,9 @@ class DocxWriter(object):
contents += [''] * (columns - len(contents))
if not contents:
contents = [''] * columns
output.append(contents)
return output
yield contents
# output.append(contents)
# return output
def create_merged_template(self, *args) -> BytesIO:
"""
@@ -554,7 +562,7 @@ class DocxWriter(object):
Returns:
BytesIO: Merged docx template
"""
"""
merged_document = Document()
output = BytesIO()
for index, file in enumerate(args):
@@ -567,7 +575,6 @@ class DocxWriter(object):
merged_document.save(output)
return output
def save(self, filename: Path | str):
if isinstance(filename, str):
filename = Path(filename)

View File

@@ -851,6 +851,7 @@ class PydSubmission(BaseModel, extra='allow'):
# logger.debug(f"Template rendered as: {render}")
return render
@report_result
def check_kit_integrity(self, extraction_kit: str | dict | None = None) -> Tuple[List[PydReagent], Report]:
"""
Ensures all reagents expected in kit are listed in Submission
@@ -873,7 +874,7 @@ class PydSubmission(BaseModel, extra='allow'):
ext_kit.get_reagents(required=True, submission_type=self.submission_type['value'])]
# logger.debug(f"Kit reagents: {ext_kit_rtypes}")
# logger.debug(f"Submission reagents: {self.reagents}")
# Exclude any reagenttype found in this pyd not expected in kit.
# NOTE: Exclude any reagenttype found in this pyd not expected in kit.
expected_check = [item.role for item in ext_kit_rtypes]
output_reagents = [rt for rt in self.reagents if rt.role in expected_check]
# logger.debug(f"Already have these reagent types: {output_reagents}")
@@ -882,7 +883,7 @@ class PydSubmission(BaseModel, extra='allow'):
missing_reagents += [rt for rt in output_reagents if rt.missing]
output_reagents += [rt for rt in missing_reagents if rt not in output_reagents]
# logger.debug(f"Missing reagents types: {missing_reagents}")
# if lists are equal return no problem
# NOTE: if lists are equal return no problem
if len(missing_reagents) == 0:
result = None
else: