Added ability to not import reagents on first import.
This commit is contained in:
@@ -37,10 +37,11 @@ from .models import *
|
||||
|
||||
|
||||
def update_log(mapper, connection, target):
|
||||
logger.debug("\n\nBefore update\n\n")
|
||||
# logger.debug("\n\nBefore update\n\n")
|
||||
state = inspect(target)
|
||||
# logger.debug(state)
|
||||
update = dict(user=getuser(), time=datetime.now(), object=str(state.object), changes=[])
|
||||
object_name = state.object.truncated_name()
|
||||
update = dict(user=getuser(), time=datetime.now(), object=object_name, changes=[])
|
||||
# logger.debug(update)
|
||||
for attr in state.attrs:
|
||||
hist = attr.load_history()
|
||||
@@ -49,8 +50,10 @@ def update_log(mapper, connection, target):
|
||||
if attr.key == "custom":
|
||||
continue
|
||||
added = [str(item) for item in hist.added]
|
||||
if attr.key in ['submission_sample_associations', 'submission_reagent_associations']:
|
||||
added = ['Numbers truncated for space purposes.']
|
||||
if attr.key in ['artic_technician', 'submission_sample_associations', 'submission_reagent_associations',
|
||||
'submission_equipment_associations', 'submission_tips_associations', 'contact_id', 'gel_info',
|
||||
'gel_controls', 'source_plates']:
|
||||
continue
|
||||
deleted = [str(item) for item in hist.deleted]
|
||||
change = dict(field=attr.key, added=added, deleted=deleted)
|
||||
# logger.debug(f"Adding: {pformat(change)}")
|
||||
|
||||
@@ -25,6 +25,16 @@ logger = logging.getLogger(f"submissions.{__name__}")
|
||||
class LogMixin(Base):
|
||||
__abstract__ = True
|
||||
|
||||
def truncated_name(self):
|
||||
name = str(self)
|
||||
if len(name) > 64:
|
||||
name = name.replace("<", "").replace(">", "")
|
||||
if len(name) > 64:
|
||||
name = name.replace("agent", "")
|
||||
if len(name) > 64:
|
||||
name = f"...{name[-61:]}"
|
||||
return name
|
||||
|
||||
|
||||
class BaseClass(Base):
|
||||
"""
|
||||
|
||||
@@ -539,7 +539,7 @@ class IridaControl(Control):
|
||||
except AttributeError:
|
||||
consolidate = False
|
||||
report = Report()
|
||||
logger.debug(f"settings: {pformat(chart_settings)}")
|
||||
# logger.debug(f"settings: {pformat(chart_settings)}")
|
||||
controls = cls.query(subtype=chart_settings['sub_type'], start_date=chart_settings['start_date'],
|
||||
end_date=chart_settings['end_date'])
|
||||
# logger.debug(f"Controls found: {controls}")
|
||||
|
||||
@@ -427,9 +427,10 @@ class Reagent(BaseClass, LogMixin):
|
||||
|
||||
def __repr__(self):
|
||||
if self.name:
|
||||
return f"<Reagent({self.name}-{self.lot})>"
|
||||
name = f"<Reagent({self.name}-{self.lot})>"
|
||||
else:
|
||||
return f"<Reagent({self.role.name}-{self.lot})>"
|
||||
name = f"<Reagent({self.role.name}-{self.lot})>"
|
||||
return name
|
||||
|
||||
def to_sub_dict(self, extraction_kit: KitType = None, full_data: bool = False, **kwargs) -> dict:
|
||||
"""
|
||||
@@ -1347,7 +1348,7 @@ class SubmissionReagentAssociation(BaseClass):
|
||||
return PydReagent(**self.to_sub_dict(extraction_kit=extraction_kit))
|
||||
|
||||
|
||||
class Equipment(BaseClass):
|
||||
class Equipment(BaseClass, LogMixin):
|
||||
"""
|
||||
A concrete instance of equipment
|
||||
"""
|
||||
@@ -1851,7 +1852,7 @@ class TipRole(BaseClass):
|
||||
super().save()
|
||||
|
||||
|
||||
class Tips(BaseClass):
|
||||
class Tips(BaseClass, LogMixin):
|
||||
"""
|
||||
A concrete instance of tips.
|
||||
"""
|
||||
|
||||
@@ -174,7 +174,8 @@ class BasicSubmission(BaseClass, LogMixin):
|
||||
'platemap', 'export_map', 'equipment', 'tips', 'custom'],
|
||||
# NOTE: Fields not placed in ui form
|
||||
form_ignore=['reagents', 'ctx', 'id', 'cost', 'extraction_info', 'signed_by', 'comment', 'namer',
|
||||
'submission_object', "tips", 'contact_phone', 'custom', 'cost_centre'] + recover,
|
||||
'submission_object', "tips", 'contact_phone', 'custom', 'cost_centre', 'completed_date',
|
||||
'controls'] + recover,
|
||||
# NOTE: Fields not placed in ui form to be moved to pydantic
|
||||
form_recover=recover
|
||||
))
|
||||
|
||||
@@ -3,6 +3,7 @@ contains writer objects for pushing values to submission sheet templates.
|
||||
"""
|
||||
import logging
|
||||
from copy import copy
|
||||
from datetime import date
|
||||
from operator import itemgetter
|
||||
from pprint import pformat
|
||||
from typing import List, Generator, Tuple
|
||||
@@ -214,6 +215,10 @@ class ReagentWriter(object):
|
||||
Returns:
|
||||
List[dict]: merged dictionary
|
||||
"""
|
||||
filled_roles = [item['role'] for item in reagent_list]
|
||||
for map_obj in reagent_map.keys():
|
||||
if map_obj not in filled_roles:
|
||||
reagent_list.append(dict(name="Not Applicable", role=map_obj, lot="Not Applicable", expiry="Not Applicable"))
|
||||
for reagent in reagent_list:
|
||||
try:
|
||||
mp_info = reagent_map[reagent['role']]
|
||||
@@ -268,6 +273,7 @@ class SampleWriter(object):
|
||||
# NOTE: exclude any samples without a submission rank.
|
||||
samples = [item for item in self.reconcile_map(sample_list) if item['submission_rank'] > 0]
|
||||
self.samples = sorted(samples, key=itemgetter('submission_rank'))
|
||||
self.blank_lookup_table()
|
||||
|
||||
def reconcile_map(self, sample_list: list) -> Generator[dict, None, None]:
|
||||
"""
|
||||
@@ -291,6 +297,16 @@ class SampleWriter(object):
|
||||
new[k] = v
|
||||
yield new
|
||||
|
||||
def blank_lookup_table(self):
|
||||
"""
|
||||
Blanks out columns in the lookup table to ensure help values are removed before writing.
|
||||
"""
|
||||
sheet = self.xl[self.sample_map['sheet']]
|
||||
for row in range(self.sample_map['start_row'], self.sample_map['end_row'] + 1):
|
||||
for column in self.sample_map['sample_columns'].values():
|
||||
if sheet.cell(row, column).data_type != 'f':
|
||||
sheet.cell(row=row, column=column, value="")
|
||||
|
||||
def write_samples(self) -> Workbook:
|
||||
"""
|
||||
Performs writing operations.
|
||||
|
||||
7
src/submissions/backend/scripts/__init__.py
Normal file
7
src/submissions/backend/scripts/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from .irida import import_irida
|
||||
|
||||
def hello(ctx):
|
||||
print("\n\nHello!\n\n")
|
||||
|
||||
def goodbye(ctx):
|
||||
print("\n\nGoodbye\n\n")
|
||||
56
src/submissions/backend/scripts/irida.py
Normal file
56
src/submissions/backend/scripts/irida.py
Normal file
@@ -0,0 +1,56 @@
|
||||
import logging, sqlite3, json
|
||||
from pprint import pformat, pprint
|
||||
from datetime import datetime
|
||||
from tools import Settings
|
||||
from backend import BasicSample
|
||||
from backend.db import IridaControl, ControlType
|
||||
|
||||
logger = logging.getLogger(f"submissions.{__name__}")
|
||||
|
||||
def import_irida(ctx:Settings):
|
||||
"""
|
||||
Grabs Irida controls from secondary database.
|
||||
|
||||
Args:
|
||||
ctx (Settings): Settings inherited from app.
|
||||
|
||||
"""
|
||||
ct = ControlType.query(name="Irida Control")
|
||||
existing_controls = [item.name for item in IridaControl.query()]
|
||||
prm_list = ", ".join([f"'{thing}'" for thing in existing_controls])
|
||||
ctrl_db_path = ctx.directory_path.joinpath("submissions_parser_output", "submissions.db")
|
||||
# print(f"Incoming settings: {pformat(ctx)}")
|
||||
try:
|
||||
conn = sqlite3.connect(ctrl_db_path)
|
||||
except AttributeError as e:
|
||||
print(f"Error, could not import from irida due to {e}")
|
||||
return
|
||||
sql = f"SELECT name, submitted_date, submission_id, contains, matches, kraken, subtype, refseq_version, " \
|
||||
f"kraken2_version, kraken2_db_version, sample_id FROM _iridacontrol INNER JOIN _control on _control.id " \
|
||||
f"= _iridacontrol.id WHERE _control.name NOT IN ({prm_list})"
|
||||
cursor = conn.execute(sql)
|
||||
records = [dict(name=row[0], submitted_date=row[1], submission_id=row[2], contains=row[3], matches=row[4], kraken=row[5],
|
||||
subtype=row[6], refseq_version=row[7], kraken2_version=row[8], kraken2_db_version=row[9],
|
||||
sample_id=row[10]) for row in cursor]
|
||||
# incoming_controls = set(item['name'] for item in records)
|
||||
# relevant = list(incoming_controls - existing_controls)
|
||||
for record in records:
|
||||
instance = IridaControl.query(name=record['name'])
|
||||
if instance:
|
||||
logger.warning(f"Irida Control {instance.name} already exists, skipping.")
|
||||
continue
|
||||
record['contains'] = json.loads(record['contains'])
|
||||
assert isinstance(record['contains'], dict)
|
||||
record['matches'] = json.loads(record['matches'])
|
||||
assert isinstance(record['matches'], dict)
|
||||
record['kraken'] = json.loads(record['kraken'])
|
||||
assert isinstance(record['kraken'], dict)
|
||||
record['submitted_date'] = datetime.strptime(record['submitted_date'], "%Y-%m-%d %H:%M:%S.%f")
|
||||
assert isinstance(record['submitted_date'], datetime)
|
||||
instance = IridaControl(controltype=ct, **record)
|
||||
sample = BasicSample.query(submitter_id=instance.name)
|
||||
if sample:
|
||||
instance.sample = sample
|
||||
instance.submission = sample.submissions[0]
|
||||
# pprint(instance.__dict__)
|
||||
instance.save()
|
||||
Reference in New Issue
Block a user