Improved retrieval of existing reagents.

This commit is contained in:
Landon Wark
2023-02-08 12:06:11 -06:00
parent 963ac7d4a4
commit c3db706e7c
8 changed files with 249 additions and 40 deletions

View File

@@ -1,4 +1,6 @@
from . import models
from .models.kits import reagenttypes_kittypes
from .models.submissions import reagents_submissions
import pandas as pd
import sqlalchemy.exc
import sqlite3
@@ -7,13 +9,23 @@ from datetime import date, datetime, timedelta
from sqlalchemy import and_
import uuid
# import base64
from sqlalchemy import JSON
from sqlalchemy import JSON, event
from sqlalchemy.engine import Engine
import json
# from dateutil.relativedelta import relativedelta
from getpass import getuser
import numpy as np
logger = logging.getLogger(f"submissions.{__name__}")
# The below should allow automatic creation of foreign keys in the database
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
def get_kits_by_use( ctx:dict, kittype_str:str|None) -> list:
pass
# ctx dict should contain the database session
@@ -266,7 +278,7 @@ def lookup_regent_by_type_name(ctx:dict, type_name:str) -> list[models.Reagent]:
def lookup_regent_by_type_name_and_kit_name(ctx:dict, type_name:str, kit_name:str) -> list[models.Reagent]:
"""
Lookup reagents by their type name and kits they belong to
Lookup reagents by their type name and kits they belong to (Broken)
Args:
ctx (dict): settings pass by gui
@@ -276,11 +288,31 @@ def lookup_regent_by_type_name_and_kit_name(ctx:dict, type_name:str, kit_name:st
Returns:
list[models.Reagent]: list of retrieved reagents
"""
# What I want to do is get the reagent type by name
# Hang on, this is going to be a long one.
by_type = ctx['database_session'].query(models.Reagent).join(models.Reagent.type, aliased=True).filter(models.ReagentType.name.endswith(type_name))
# add filter for kit name
add_in = by_type.join(models.ReagentType.kits).filter(models.KitType.name==kit_name)
return add_in
# by_type = ctx['database_session'].query(models.Reagent).join(models.Reagent.type, aliased=True).filter(models.ReagentType.name.endswith(type_name)).all()
rt_types = ctx['database_session'].query(models.ReagentType).filter(models.ReagentType.name.endswith(type_name))
# add filter for kit name... which I can not get to work.
# add_in = by_type.join(models.ReagentType.kits).filter(models.KitType.name==kit_name)
try:
check = not np.isnan(kit_name)
except TypeError:
check = True
if check:
kit_type = lookup_kittype_by_name(ctx=ctx, name=kit_name)
logger.debug(f"reagenttypes: {[item.name for item in rt_types.all()]}, kit: {kit_type.name}")
rt_types = rt_types.join(reagenttypes_kittypes).filter(reagenttypes_kittypes.c.kits_id==kit_type.id).first()
# for item in by_type:
# logger.debug([thing.name for thing in item.type.kits])
# output = [item for item in by_type if kit_name in [thing.name for thing in item.type.kits]]
# else:
output = rt_types.instances
return output
def lookup_all_submissions_by_type(ctx:dict, type:str|None=None) -> list[models.BasicSubmission]:
@@ -346,6 +378,10 @@ def submissions_to_df(ctx:dict, type:str|None=None) -> pd.DataFrame:
df = df.drop("controls", axis=1)
except:
logger.warning(f"Couldn't drop 'controls' column from submissionsheet df.")
try:
df = df.drop("ext_info", axis=1)
except:
logger.warning(f"Couldn't drop 'controls' column from submissionsheet df.")
# logger.debug(f"Post: {df['Technician']}")
return df
@@ -428,6 +464,9 @@ def create_kit_from_yaml(ctx:dict, exp:dict) -> None:
else:
rt = look_up
rt.kits.append(kit)
# add this because I think it's necessary to get proper back population
# rt.kit_id.append(kit.id)
kit.reagent_types_id.append(rt.id)
ctx['database_session'].add(rt)
logger.debug(rt.__dict__)
logger.debug(kit.__dict__)
@@ -521,3 +560,15 @@ def get_control_subtypes(ctx:dict, type:str, mode:str) -> list[str]:
return []
subtypes = [item for item in jsoner[genera] if "_hashes" not in item and "_ratio" not in item]
return subtypes
def get_all_controls(ctx:dict):
return ctx['database_session'].query(models.Control).all()
def lookup_submission_by_rsl_num(ctx:dict, rsl_num:str):
return ctx['database_session'].query(models.BasicSubmission).filter(models.BasicSubmission.rsl_plate_num.startswith(rsl_num)).first()
def lookup_submissions_using_reagent(ctx:dict, reagent:models.Reagent) -> list[models.BasicSubmission]:
return ctx['database_session'].query(models.BasicSubmission).join(reagents_submissions).filter(reagents_submissions.c.reagent_id==reagent.id)

View File

@@ -6,6 +6,6 @@ metadata = Base.metadata
from .controls import Control, ControlType
from .kits import KitType, ReagentType, Reagent
from .submissions import BasicSubmission, BacterialCulture, Wastewater
from .organizations import Organization, Contact
from .samples import WWSample, BCSample
from .samples import WWSample, BCSample
from .submissions import BasicSubmission, BacterialCulture, Wastewater

View File

@@ -3,6 +3,7 @@ from sqlalchemy import Column, String, TIMESTAMP, INTEGER, ForeignKey, Table, JS
from sqlalchemy.orm import relationship
from datetime import datetime as dt
import logging
import json
logger = logging.getLogger(f"submissions.{__name__}")
@@ -69,6 +70,10 @@ class BasicSubmission(Base):
ext_kit = self.extraction_kit.name
except AttributeError:
ext_kit = None
try:
ext_info = json.loads(self.extraction_info)
except TypeError:
ext_info = None
output = {
"id": self.id,
"Plate Number": self.rsl_plate_num,
@@ -80,8 +85,9 @@ class BasicSubmission(Base):
"Extraction Kit": ext_kit,
"Technician": self.technician,
"Cost": self.run_cost,
"ext_info": ext_info
}
logger.debug(f"{self.rsl_plate_num} technician: {output['Technician']}")
# logger.debug(f"{self.rsl_plate_num} extraction: {output['Extraction Status']}")
return output

View File

@@ -92,6 +92,9 @@ class SheetParser(object):
def _parse_reagents(df:pd.DataFrame) -> None:
for ii, row in df.iterrows():
# skip positive control
if ii == 11:
continue
logger.debug(f"Running reagent parse for {row[1]} with type {type(row[1])} and value: {row[2]} with type {type(row[2])}")
try:
check = not np.isnan(row[1])
@@ -162,7 +165,7 @@ class SheetParser(object):
check = True
if not isinstance(row[5], float) and check:
# must be prefixed with 'lot_' to be recognized by gui
output_key = re.sub(r"\d{1,3}%", "", row[0].replace(' ', '_').lower())
output_key = re.sub(r"\d{1,3}%", "", row[0].lower().strip().replace(' ', '_'))
try:
output_var = row[5].upper()
except AttributeError: