Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plate_reader #60

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
63ae074
updated pyproject.toml to include packages
mark-polk Oct 6, 2024
34004bf
instantiate Experiment Class
mark-polk Oct 6, 2024
b8dce34
added labels attribute to Experiment Class
mark-polk Oct 6, 2024
c99e9d4
instantiate automatically generated poetry.lock file
mark-polk Oct 6, 2024
6348921
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 6, 2024
b8d25b3
instantiate Measurement and Parameters classes
mark-polk Oct 6, 2024
b17f44a
removed parameters from separate class to Measurement attribute
mark-polk Oct 6, 2024
7f5e44b
added start time, end time, and duration to Measurement class
mark-polk Oct 6, 2024
3ef25ce
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 6, 2024
fa1754f
added Luminescence_Scan_Data class
mark-polk Oct 6, 2024
06785ad
Merge branch 'mpp_exp' of https://github.com/choderalab/missense-kina…
mark-polk Oct 6, 2024
c703457
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 6, 2024
d8764c0
changes made during review
mark-polk Oct 8, 2024
e45ff3e
Merge branch 'mpp_exp' of https://github.com/choderalab/missense-kina…
mark-polk Oct 8, 2024
21e1954
reworked module to use dataclasses and abstract base classes
mark-polk Oct 8, 2024
94f1b31
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 8, 2024
6043b63
added basic get parameter
mark-polk Oct 8, 2024
741c257
added start, end time tracking
mark-polk Oct 8, 2024
db8aef1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 8, 2024
38ed2dd
fixed use of f strings
mark-polk Oct 8, 2024
c677a22
added initial scatterplotting function to Luminescence_Scan
jessicaw9910 Oct 8, 2024
a5565f1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import logging
import xml.etree.ElementTree as ET
from abc import ABC, abstractmethod
from dataclasses import dataclass
from datetime import datetime

# i-control manual: https://bif.wisc.edu/wp-content/uploads/sites/389/2017/11/i-control_Manual.pdf

logger = logging.getLogger(__name__)


@dataclass
class Measurement(ABC):
"""Abstract class for measurements."""

filepath: str
"""str: Filepath to i-control output .XML."""
label: str
"""str: Label parameter in i-control."""

def __post_init__(self):
self.parse_for_section()
self.parse_for_time()

def parse_for_section(self):
try:
tree = ET.parse(self.filepath)
root = tree.getroot()
# TODO: check that i-control does not allow duplicate labels
self.section_element = root.find(f".//Section[@Name='{self.label}']")
if self.section_element is None:
logger.error("Label not found.")
except ET.ParseError as e:
logging.error(f"Could not parse input {self.filepath}", exc_info=e)

def parse_for_time(self):
self.time_start = datetime.fromisoformat(
self.section_element.find(".//Time_Start").text
)
self.time_end = datetime.fromisoformat(
self.section_element.find(".//Time_End").text
)

def get_parameter(self, parameter: str) -> str:
# TODO: Add units handling
parameter_attribute = self.section_element.find(
f".//Parameter[@Name='{parameter}']"
).attrib["Value"]
return parameter_attribute

@abstractmethod
def get_data(self) -> int: ...

@abstractmethod
def plot_data(
self
) -> Tuple[matplotlib.figure.Figure, plt.Axes] | None:
...


@dataclass
class Luminescence_Scan(Measurement):
"""Class to parse Luminescence Scan measurement."""

def get_data(self, cycle: int, temperature: int, well: str, wavelength: int):
data_element = self.section_element.find(
f".//Data[@Cycle='{str(cycle)}'][@Temperature='{str(temperature)}']"
)
if data_element is None:
logger.error("Data not found.")
else:
well_element = data_element.find(f".//Well[@Pos='{well}']")
scan_element = well_element.find(f".//Scan[@WL='{str(wavelength)}']")
return int(scan_element.text)

def plot_data(
cycle: int
temperature: int,
well: str,
header: str,
plot_type: str | None = None,
):
if plot_type is None:
plot_type = "scatter"

list_plot_type = ["scatter"]
if plot_type not in list_plot_type:
logging.error(f"Plot type {plot_type} not yet supported...")
return None

if plot_type == "scatter":
lmin = int(self.get_parameter("Wavelength Start"))
lmax = int(self.get_parameter("Wavelength End"))
lstep = int(self.get_parameter("Wavelength Step Size"))
ll = np.arange(lmin, lmax+lstep, lstep)

fig, ax = plt.subplots()

try:
counter = 0
for l in ll:
ax.plot(l, self.get_data(cycle, temperature, well, l), "b.", alpha=0.5)
counter += 1
assert counter == int(self.get_parameter("Scan Number"))
print(f"All {counter} points accounted for")
except AssertionError as e:
logging.error(f"{counter} / {int(self.get_parameter('Scan Number'))} points accounted for...")
return None

ax.set_box_aspect(1)
ax.set_title("Water") # make this a parameter?
ax.set_xlabel("Wavelength (nm)")
ax.set_ylabel("Luminescence (RLU)")
ax.set_xlim([lmin, lmax])
ax.set_xticks(np.arange(lmin, lmax+50, 50)) # make this a parameter?

return (fig, ax)
7 changes: 7 additions & 0 deletions missense_kinase_toolkit/experiments/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions missense_kinase_toolkit/experiments/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ description = "Tools to facilitate experimental analyses for missense_kinase_too
authors = ["Jess White <[email protected]>"]
license = "MIT"
readme = "README.md"
#https://safjan.com/the-importance-of-adding-py-typed-file-to-your-typed-package/
packages = [
{include = "missense_kinase_toolkit"},
{include = "missense_kinase_toolkit/py.typed"}
]

[tool.poetry.dependencies]
python = "^3.9"
Expand Down