Skip to content

Commit

Permalink
Update Calculate Amount scripts for more flexibility (#562)
Browse files Browse the repository at this point in the history
Changes are needed for the new Pacbio Revio workflow but they also affect many other steps that have different types of calculate amount automations using the same script

### Changed

For script calculate_amount_ng.py:
- From options.py, "subtract_volume_option" was substituted with "subtract_volume" as it offers more flexibility
- From options.py, "preset_volume" was added so that a volume specified in the cli can be used in the calculation

For script twist_qc_amount.py:
- From options.py, "subtract_volume" was added and substitutes the hardcoded volume subtraction in the script - the value can be modified in the cli command instead.
- Its pytest test_twist_qc_amount.py was modified to reflect the added option mentioned above
  • Loading branch information
idalindegaard authored Nov 28, 2024
1 parent 1460816 commit d948f1e
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 17 deletions.
15 changes: 10 additions & 5 deletions cg_lims/EPPs/udf/calculate/calculate_amount_ng.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
@options.concentration_udf()
@options.amount_udf_option()
@options.volume_udf()
@options.subtract_volume_option()
@options.subtract_volume()
@options.preset_volume()
@options.measurement()
@options.input()
@click.pass_context
Expand All @@ -25,12 +26,14 @@ def calculate_amount_ng(
volume_udf: str,
concentration_udf: str,
subtract_volume: str,
preset_volume: float,
measurement: bool = False,
input: bool = False,
):
"""Calculates and auto-fills the quantities of DNA in sample from concentration and volume
measurements. The volume is subtracted by either 0 or 3 in the calculations. This is
because the lab uses 0 or 3 ul in the initial qc measurements."""
measurements. The volume can be subtracted by an optional specification in the cli. This is
because the lab uses some microliters of the sample in the qc measurements. A pre-set
volume can be set in the cli as well."""

LOG.info(f"Running {ctx.command_path} with params: {ctx.params}")

Expand All @@ -43,13 +46,15 @@ def calculate_amount_ng(
missing_udfs_count: int = 0
artifacts_with_missing_udf: List = []
for artifact in artifacts:
vol: float = artifact.udf.get(volume_udf)
if preset_volume:
vol = float(preset_volume)
elif volume_udf:
vol = artifact.udf.get(volume_udf)
conc: float = artifact.udf.get(concentration_udf)
if None in [conc, vol]:
missing_udfs_count += 1
artifacts_with_missing_udf.append(artifact.id)
continue

artifact.udf[amount_udf] = conc * (vol - int(subtract_volume))
artifact.put()
if missing_udfs_count:
Expand Down
13 changes: 9 additions & 4 deletions cg_lims/EPPs/udf/calculate/twist_qc_amount.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import List

import click
from cg_lims import options
from cg_lims.exceptions import FailingQCError, LimsError, MissingUDFsError
from cg_lims.get.artifacts import get_artifacts
from cg_lims.get.samples import get_one_sample_from_artifact
Expand All @@ -29,7 +30,7 @@ def get_qc(source: str, conc: float, amount: float, max_amount: float) -> str:
return qc


def calculate_amount_and_set_qc(artifacts: List[Artifact]) -> None:
def calculate_amount_and_set_qc(artifacts: List[Artifact], subtract_volume: int) -> None:
"""Calculate amount and set qc for twist samples"""

missing_udfs_count = 0
Expand All @@ -43,7 +44,7 @@ def calculate_amount_and_set_qc(artifacts: List[Artifact]) -> None:
missing_udfs_count += 1
continue

amount = conc * (vol - 3)
amount = conc * (vol - subtract_volume)
artifact.udf["Amount (ng)"] = amount
max_amount = get_maximum_amount(artifact=artifact, default_amount=MAXIMUM_SAMPLE_AMOUNT)
qc = get_qc(source=source, conc=conc, amount=amount, max_amount=max_amount)
Expand All @@ -64,8 +65,12 @@ def calculate_amount_and_set_qc(artifacts: List[Artifact]) -> None:


@click.command()
@options.subtract_volume()
@click.pass_context
def twist_qc_amount(ctx):
def twist_qc_amount(
ctx: click.Context,
subtract_volume: str,
):
"""Calculates amount of samples for qc validation."""

LOG.info(f"Running {ctx.command_path} with params: {ctx.params}")
Expand All @@ -74,7 +79,7 @@ def twist_qc_amount(ctx):

try:
artifacts = get_artifacts(process=process, measurement=True)
calculate_amount_and_set_qc(artifacts=artifacts)
calculate_amount_and_set_qc(artifacts=artifacts, subtract_volume=int(subtract_volume))
message = "Amounts have been calculated and qc flags set for all samples."
LOG.info(message)
click.echo(message)
Expand Down
17 changes: 9 additions & 8 deletions tests/EPPs/udf/calculate/test_twist_qc_amount.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@


@pytest.mark.parametrize(
"volume,concentration,source",
[(3, 1, "blood"), (10, 0.1, "cfDNA"), (50, 300, "blood"), (300, 2, "blood"), (10, 10, "blood")],
"volume,concentration,source,subtract",
[(3, 1, "blood",2), (10, 0.1, "cfDNA",2), (50, 300, "blood",2), (300, 2, "blood",2), (10, 10, "blood",2)],
)
def test_calculate_amount_and_set_qc_failing(
volume: int, concentration: float, source: int, artifact_1: Artifact, sample_1: Sample
volume: int, concentration: float, source: int, artifact_1: Artifact, sample_1: Sample, subtract: int
):
# GIVEN: A sample with udf Source: <source>,
# and a related Artifact with udfs: Concentration: <concentration> and Volume (ul): <volume>
# and a subtraction volume
server("flat_tests")
artifact_1.udf["Volume (ul)"] = volume
artifact_1.udf["Concentration"] = concentration
Expand All @@ -26,13 +27,13 @@ def test_calculate_amount_and_set_qc_failing(

# THEN FailingQCError is being raised and the artifacts should be FAILED
with pytest.raises(FailingQCError):
calculate_amount_and_set_qc(artifacts=[artifact_1])
calculate_amount_and_set_qc(artifacts=[artifact_1], subtract_volume=subtract)
assert artifact_1.qc_flag == "FAILED"


@pytest.mark.parametrize("volume,concentration,source", [(35, 10, "cfDNA"), (50, 50, "blood")])
@pytest.mark.parametrize("volume,concentration,source,subtract", [(35, 10, "cfDNA",2), (50, 50, "blood",2)])
def test_calculate_amount_and_set_qc_passing(
volume: int, concentration: float, source: int, artifact_1: Artifact, sample_1: Sample
volume: int, concentration: float, source: int, artifact_1: Artifact, sample_1: Sample, subtract: int
):
# GIVEN: A sample with udf Source: <source>,
# and a related Artifact with udfs: Concentration: <concentration> and Volume (ul): <volume>
Expand All @@ -46,7 +47,7 @@ def test_calculate_amount_and_set_qc_passing(
sample_1.put()

# WHEN running calculate_amount_and_set_qc
calculate_amount_and_set_qc(artifacts=[artifact_1])
calculate_amount_and_set_qc(artifacts=[artifact_1], subtract_volume=subtract)

# THEN the artifacts should be PASSED
assert artifact_1.qc_flag == "PASSED"
Expand All @@ -67,4 +68,4 @@ def test_calculate_amount_and_set_qc_missing_udf(
# WHEN running calculate_amount_and_set_qc
# THEN MissingUDFsError is being raised
with pytest.raises(MissingUDFsError):
calculate_amount_and_set_qc(artifacts=artifacts)
calculate_amount_and_set_qc(artifacts=artifacts, subtract_volume=2)

0 comments on commit d948f1e

Please sign in to comment.