post documentation and code clean-up.

This commit is contained in:
lwark
2024-07-05 14:00:25 -05:00
parent c460e5eeca
commit e589420815
8 changed files with 106 additions and 46 deletions

View File

@@ -1,3 +1,7 @@
## 202407.01
- Better documentation.
## 202406.04
- Exported submission details will now be in docx format.

View File

@@ -9,20 +9,57 @@
1. Ensure a properly formatted Submission Excel form has been filled out.
a. The program can fill in reagent fields and some other information automatically, but should be checked for accuracy afterwards.
2. Click on 'File' in the menu bar, followed by 'Import Submission' and use the file dialog to locate the form.
1. The excel file may also be dragged into the grey area on the left hand side of the screen from Windows File Explorer. If so, skip step 3.
3. Click 'Ok'.
4. Most of the fields in the form should be automatically filled in from the form area to the left of the screen.
5. You may need to maximize the app to ensure you can see all the info.
6. Any fields that are not automatically filled in can be filled in manually from the drop down menus.
a. Any reagent lots not found in the drop downs can be typed in manually.
1. Any reagent lots not found in the drop downs can be typed in manually.
7. Once you are certain all the information is correct, click 'Submit' at the bottom of the form.
8. Add in any new reagents the app doesn't have in the database.
9. Once the new run shows up at the bottom of the Submissions, everything is fine.
10. In case of any mistakes, the run can be overwritten by a reimport.
## Adding Equipment to a Run:
1. Right click on the run in the Submissions Table to access the context menu.
2. Click on “Add Equipment”.
3. Select equipment used for each equipment role from the drop down menu.
1. Any tips associated with a liquid handler will also be available in a separate drop down menu.
5. Select (or input) the process used on with the equipment.
1. Equipment that is not necessary may disabled using the check boxes to the left of each entry.
## Importing PCR results (Wastewater only):
This is meant to import .xslx files created from the Design & Analysis Software
1. Click on 'File' -> 'Import PCR Results'.
2. Use the file dialog to locate the .xlsx file you want to import.
3. Click 'Okay'.
## Using the Gel Box (Wastewater Artic only):
1. Right click on the run in the Submissions Table to access the context menu.
2. Click on “Gel Box”.
3. Choose the .jpg file exported from the Egel reader.
4. Click “Okay”.
5. If none exists, eEnter the DNA Core Submission Number and gel barcode at the top of the window.
6. Use the histogram slide on the right side of the window to adjust the image contrast.
7. Use the mouse scroll to zoom in on relevant areas of the image.
8. Enter the control status in the grid at the bottom of the window.
9. Add any relevant comments.
10. Click “Okay”.
## Check existing Run:
1. Details of existing runs can be checked by double clicking on the row of interest in the summary sheet on the right of the 'Submissions' tab.
2. All information available on the run should be available in the resulting text window. This information can be exported by clicking 'Export PDF' at the top.
2. All information available on the run should be available in the resulting text window.
1. This information can be exported by clicking 'Export DOCX' at the top.
## Signing Off on a run:
1. Open the “Submission Details” window (see 7.6 above).
2. Scroll down to bottom of the details window.
3. If the current user is authorized a button marked “Sign Off” will appear at the bottom of the page. Click it.
## Generating a report:
@@ -31,20 +68,22 @@
3. Use the file dialog to select a location to save the report.
a. Both an excel sheet and a pdf should be generated containing summary information for submissions made by each client lab.
## Importing PCR results:
## Exporting a run as an Excel file:
1. Right click on the run in the Submissions Table to access the context menu.
2. Select “Export” from the context menu.
3. Select the folder and input the filename in the “Save File” dialog.
4. Click “Okay”.
5. Ensure the resulting Excel workbook contains all the relevant information.
This is meant to import .xslx files created from the Design & Analysis Software
1. Click on 'File' -> 'Import PCR Results'.
2. Use the file dialog to locate the .xlsx file you want to import.
3. Click 'Okay'.
## Checking Controls:
1. Controls for bacterial runs are now incorporated directly into the submissions database using webview. (Admittedly this performance is not as good as with a browser, so you will have to triage your data)
2. Click on the "Controls" tab.
3. Range of dates for controls can be selected from the date pickers at the top.
a. If start date is set after end date, the start date will default back to 3 months before end date.
b. Recommendation is to use less than 6 month date range keeping in mind that higher data density will affect performance (with kraken being the worst so far)
1. If start date is set after end date, the start date will default back to 3 months before end date.
2. Recommendation is to use less than 6 month date range keeping in mind that higher data density will affect performance (with kraken being the worst so far)
4. Analysis type and subtype can be set using the drop down menus. (Only kraken has a subtype so far).
## Adding new Kit:
@@ -69,7 +108,3 @@ This is meant to import .xslx files created from the Design & Analysis Software
1. Click "Monthly" -> "Link PCR Logs".
2. Chose the .csv file taken from the PCR table runlogs folder.
## Hitpicking:
1. Select all submissions you wish to hitpick using "Ctrl + click". All must have PCR results.
2. Right click on the last sample and select "Hitpick" from the contex menu.
3. Select location to save csv file.

View File

@@ -1,9 +1,10 @@
'''
"""
All database related operations.
'''
"""
from sqlalchemy import event
from sqlalchemy.engine import Engine
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
"""
@@ -19,4 +20,5 @@ def set_sqlite_pragma(dbapi_connection, connection_record):
cursor.execute("PRAGMA foreign_keys=ON")
cursor.close()
from .models import *

View File

@@ -1,6 +1,6 @@
'''
"""
Contains all models for sqlalchemy
'''
"""
from __future__ import annotations
import sys, logging
from sqlalchemy import Column, INTEGER, String, JSON
@@ -27,6 +27,7 @@ class BaseClass(Base):
__table_args__ = {'extend_existing': True} #: Will only add new columns
@classmethod
@declared_attr
def __tablename__(cls) -> str:
"""
@@ -37,6 +38,7 @@ class BaseClass(Base):
"""
return f"_{cls.__name__.lower()}"
@classmethod
@declared_attr
def __database_session__(cls) -> Session:
"""
@@ -51,6 +53,7 @@ class BaseClass(Base):
from test_settings import ctx
return ctx.database_session
@classmethod
@declared_attr
def __directory_path__(cls) -> Path:
"""
@@ -65,6 +68,7 @@ class BaseClass(Base):
from test_settings import ctx
return ctx.directory_path
@classmethod
@declared_attr
def __backup_path__(cls) -> Path:
"""
@@ -192,3 +196,4 @@ from .controls import *
from .organizations import *
from .kits import *
from .submissions import *
BasicSubmission.reagents.creator = lambda reg: SubmissionReagentAssociation(reagent=reg)

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, Any
from typing import List, Literal
from pandas import ExcelFile
from pathlib import Path
from . import Base, BaseClass, Organization
@@ -126,8 +126,9 @@ class KitType(BaseClass):
cascade="all, delete-orphan",
) #: Relation to SubmissionType
used_for = association_proxy("kit_submissiontype_associations",
"submission_type") #: Association proxy to SubmissionTypeKitTypeAssociation
used_for = association_proxy("kit_submissiontype_associations", "submission_type",
creator=lambda ST: SubmissionTypeKitTypeAssociation(
submission_type=ST)) #: Association proxy to SubmissionTypeKitTypeAssociation
def __repr__(self) -> str:
"""
@@ -375,8 +376,9 @@ class Reagent(BaseClass):
cascade="all, delete-orphan",
) #: Relation to SubmissionSampleAssociation
submissions = association_proxy("reagent_submission_associations",
"submission") #: Association proxy to SubmissionSampleAssociation.samples
submissions = association_proxy("reagent_submission_associations", "submission",
creator=lambda sub: SubmissionReagentAssociation(
submission=sub)) #: Association proxy to SubmissionSampleAssociation.samples
def __repr__(self):
if self.name is not None:
@@ -597,7 +599,9 @@ class SubmissionType(BaseClass):
cascade="all, delete-orphan",
) #: Association of kittypes
kit_types = association_proxy("submissiontype_kit_associations", "kit_type") #: Proxy of kittype association
kit_types = association_proxy("submissiontype_kit_associations", "kit_type",
creator=lambda kit: SubmissionTypeKitTypeAssociation(
kit_type=kit)) #: Proxy of kittype association
submissiontype_equipmentrole_associations = relationship(
"SubmissionTypeEquipmentRoleAssociation",
@@ -605,8 +609,8 @@ class SubmissionType(BaseClass):
cascade="all, delete-orphan"
) #: Association of equipmentroles
equipment = association_proxy("submissiontype_equipmentrole_associations",
"equipment_role") #: Proxy of equipmentrole associations
equipment = association_proxy("submissiontype_equipmentrole_associations", "equipment_role",
creator=lambda eq: SubmissionTypeEquipmentRoleAssociation(equipment_role=eq)) #: Proxy of equipmentrole associations
submissiontype_kit_rt_associations = relationship(
"KitTypeReagentRoleAssociation",
@@ -827,12 +831,13 @@ class SubmissionTypeKitTypeAssociation(BaseClass):
submission_type = relationship(SubmissionType,
back_populates="submissiontype_kit_associations") #: joined submission type
def __init__(self, kit_type=None, submission_type=None):
def __init__(self, kit_type=None, submission_type=None,
mutable_cost_column: int = 0.00, mutable_cost_sample: int = 0.00, constant_cost: int = 0.00):
self.kit_type = kit_type
self.submission_type = submission_type
self.mutable_cost_column = 0.00
self.mutable_cost_sample = 0.00
self.constant_cost = 0.00
self.mutable_cost_column = mutable_cost_column
self.mutable_cost_sample = mutable_cost_sample
self.constant_cost = constant_cost
def __repr__(self) -> str:
"""
@@ -1539,11 +1544,11 @@ class Process(BaseClass):
pass
return cls.execute_query(query=query, limit=limit)
@check_authorization
def save(self):
super().save()
class TipRole(BaseClass):
"""
An abstract role that a tip fills during a process

View File

@@ -79,7 +79,7 @@ class BasicSubmission(BaseClass):
) #: Relation to SubmissionSampleAssociation
samples = association_proxy("submission_sample_associations",
"sample") #: Association proxy to SubmissionSampleAssociation.samples
"sample", creator=lambda sample: SubmissionSampleAssociation(sample=sample)) #: Association proxy to SubmissionSampleAssociation.samples
submission_reagent_associations = relationship(
"SubmissionReagentAssociation",
@@ -853,14 +853,14 @@ class BasicSubmission(BaseClass):
@classmethod
def custom_sample_autofill_row(cls, sample, worksheet: Worksheet) -> int:
"""
_summary_
Updates row information
Args:
sample (_type_): _description_
worksheet (Workbook): _description_
Returns:
int: _description_
int: New row number
"""
return None
@@ -1307,7 +1307,6 @@ class BacterialCulture(BasicSubmission):
row = idx.index.to_list()[0]
return row + 1
class Wastewater(BasicSubmission):
"""
derivative submission type from BasicSubmission
@@ -2053,7 +2052,6 @@ class BasicSample(BaseClass):
dict: well location and name (sample id, organism) NOTE: keys must sync with WWSample to_sub_dict above
"""
# logger.debug(f"Converting {self} to dict.")
# start = time()
sample = {}
sample['submitter_id'] = self.submitter_id
sample['sample_type'] = self.sample_type

View File

@@ -69,6 +69,7 @@ class App(QMainWindow):
helpMenu = menuBar.addMenu("&Help")
helpMenu.addAction(self.helpAction)
helpMenu.addAction(self.docsAction)
helpMenu.addAction(self.githubAction)
fileMenu.addAction(self.importAction)
methodsMenu.addAction(self.searchLog)
methodsMenu.addAction(self.searchSample)
@@ -103,6 +104,7 @@ class App(QMainWindow):
self.docsAction = QAction("&Docs", self)
self.searchLog = QAction("Search Log", self)
self.searchSample = QAction("Search Sample", self)
self.githubAction = QAction("Github", self)
def _connectActions(self):
"""
@@ -118,6 +120,7 @@ class App(QMainWindow):
self.docsAction.triggered.connect(self.openDocs)
self.searchLog.triggered.connect(self.runSearch)
self.searchSample.triggered.connect(self.runSampleSearch)
self.githubAction.triggered.connect(self.openGithub)
def showAbout(self):
"""
@@ -138,6 +141,14 @@ class App(QMainWindow):
# logger.debug(f"Attempting to open {url}")
webbrowser.get('windows-default').open(f"file://{url.__str__()}")
def openGithub(self):
"""
Opens the instructions html page
"""
url = "https://github.com/landowark/submissions"
webbrowser.get('windows-default').open(url)
def result_reporter(self):
"""
Report any anomolous results - if any - to the user

View File

@@ -18,7 +18,7 @@ class EquipmentUsage(QDialog):
def __init__(self, parent, submission: BasicSubmission) -> QDialog:
super().__init__(parent)
self.submission = submission
self.setWindowTitle("Equipment Checklist")
self.setWindowTitle(f"Equipment Checklist - {submission.rsl_plate_num}")
self.used_equipment = self.submission.get_used_equipment()
self.kit = self.submission.extraction_kit
# logger.debug(f"Existing equipment: {self.used_equipment}")