Skip to content

Commit

Permalink
Introduced 'On hold external' QC state.
Browse files Browse the repository at this point in the history
This state will be assigned to wells when the
outcome of the QC assessment depends on liasing
with a third party. The existing 'On hold' state
will be used for flagging internal investigations.

As fas as QC statuses and workflow is concerned,
the new state is handled in the same way as the
existing 'On hold' state.
  • Loading branch information
mgcam committed Mar 22, 2024
1 parent f599e37 commit 0577d55
Show file tree
Hide file tree
Showing 10 changed files with 49 additions and 14 deletions.
22 changes: 22 additions & 0 deletions alembic/versions/2.1.0_extend_qc_state_dict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""extend_qc_state_dict
Revision ID: 2.1.0
Revises: 2.0.0
Create Date: 2024-03-19 12:31:26.359652
"""
from alembic import op

# revision identifiers, used by Alembic.
revision = "2.1.0"
down_revision = "2.0.0"
branch_labels = None
depends_on = None


def upgrade() -> None:
op.execute("INSERT INTO qc_state_dict VALUES ('On hold external', NULL)")


def downgrade() -> None:
op.execute("DELETE FROM qc_state_dict WHERE state='On hold external'")
4 changes: 2 additions & 2 deletions lang_qc/db/helper/wells.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ class PacBioPagedWellsFactory(WellWh, PagedResponse):
# For MySQL it's OK to use case-sensitive comparison operators since
# its string comparisons for the collation we use are case-insensitive.
FILTERS: ClassVar = {
QcFlowStatusEnum.ON_HOLD.name: (QcStateDict.state == "On hold"),
QcFlowStatusEnum.ON_HOLD.name: (QcStateDict.state.ilike("On hold%")),
QcFlowStatusEnum.QC_COMPLETE.name: (QcState.is_preliminary == 0),
QcFlowStatusEnum.IN_PROGRESS.name: and_(
QcState.is_preliminary == 1, QcStateDict.state != "On hold"
QcState.is_preliminary == 1, QcStateDict.state.notilike("On hold%")
),
QcFlowStatusEnum.ABORTED.name: or_(
PacBioRunWellMetrics.well_status.like("Abort%"),
Expand Down
4 changes: 3 additions & 1 deletion lang_qc/endpoints/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ def _states_for_update(session) -> List:
states = []
for (name, row) in qc_state_dict(session).items():
if name not in ["Aborted", "Claimed"]:
states.append({"description": name, "only_prelim": row.state == "On hold"})
states.append(
{"description": name, "only_prelim": "on hold" in row.state.lower()}
)

return states
1 change: 1 addition & 0 deletions tests/endpoints/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def test_get_config(test_client: TestClient, load_dicts_and_users):
{"description": "Failed, Instrument", "only_prelim": False},
{"description": "Failed, SMRT cell", "only_prelim": False},
{"description": "On hold", "only_prelim": True},
{"description": "On hold external", "only_prelim": True},
{"description": "Undecided", "only_prelim": False},
],
}
Expand Down
2 changes: 1 addition & 1 deletion tests/endpoints/test_dump_qc_states.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def test_get_qc_by_product_id(test_client: TestClient, load_data4well_retrieval)
assert SECOND_GOOD_CHECKSUM in response_data
list_1 = response_data[FIRST_GOOD_CHECKSUM]
list_2 = response_data[SECOND_GOOD_CHECKSUM]
qc_states = ["On hold", "Failed, Instrument"]
qc_states = ["On hold external", "Failed, Instrument"]
for index, l in enumerate([list_1, list_2]):
assert len(l) == 2
# The list of QC state objects contains QC states
Expand Down
5 changes: 4 additions & 1 deletion tests/endpoints/test_filtered_wells.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,10 @@ def test_on_hold_filter(test_client: TestClient, load_data4well_retrieval):
"""Test passing `on_hold` filter."""

status = "on_hold"
expected_data = [{"TRACTION_RUN_1:D1": "On hold"}, {"TRACTION_RUN_1:B1": "On hold"}]
expected_data = [
{"TRACTION_RUN_1:D1": "On hold external"},
{"TRACTION_RUN_1:B1": "On hold"},
]
num_total = len(expected_data)

response = test_client.get(
Expand Down
2 changes: 1 addition & 1 deletion tests/endpoints/test_wells4run.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test_existing_run(test_client: TestClient, load_data4well_retrieval):
label_list = [well["label"] for well in resp["wells"]]
assert label_list == ["A1", "B1", "C1", "D1"]
qc_states = [well["qc_state"]["qc_state"] for well in resp["wells"]]
assert qc_states == ["Claimed", "On hold", "Claimed", "On hold"]
assert qc_states == ["Claimed", "On hold", "Claimed", "On hold external"]

assert (
resp["wells"][0]["instrument_name"] == "64016"
Expand Down
3 changes: 2 additions & 1 deletion tests/fixtures/well_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
{"state": "Passed", "outcome": 1},
{"state": "Claimed", "outcome": None},
{"state": "On hold", "outcome": None},
{"state": "On hold external", "outcome": None},
]

PLATFORMS = [
Expand Down Expand Up @@ -66,7 +67,7 @@
["TRACTION_RUN_1", "A1", "Claimed", True, "2022-12-07 07:15:19", None],
["TRACTION_RUN_1", "B1", "On hold", True, "2022-12-08 07:15:19", None],
["TRACTION_RUN_1", "C1", "Claimed", True, "2022-12-08 08:15:19", None],
["TRACTION_RUN_1", "D1", "On hold", True, "2022-12-08 09:15:19", None],
["TRACTION_RUN_1", "D1", "On hold external", True, "2022-12-08 09:15:19", None],
["TRACTION_RUN_1", "E1", "Claimed", True, "2022-12-07 09:15:19", None],
["TRACTION_RUN_2", "A1", "Failed, Instrument", True, "2022-12-07 15:13:56", 1],
["TRACTION_RUN_2", "B1", "Failed, Instrument", False, "2022-12-08 15:18:56", 1],
Expand Down
11 changes: 8 additions & 3 deletions tests/test_pb_wells_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test_query_for_status(
assert isinstance(state, QcState)
assert state.is_preliminary == 1
assert state.qc_type.qc_type == "sequencing"
assert state.qc_state_dict.state == "On hold"
assert state.qc_state_dict.state in ("On hold", "On hold external")
compare_dates(state.date_updated, update_dates[index])

factory = PacBioPagedWellsFactory(
Expand Down Expand Up @@ -400,8 +400,13 @@ def test_known_run_names_input(
label_list = [well.label for well in wells]
assert label_list == ["A1", "B1", "C1", "D1"]

qc_states = [well.qc_state.qc_state for well in wells]
expected_qc_states = ["Claimed", "On hold", "Claimed", "On hold"]
qc_states = sorted([well.qc_state.qc_state for well in wells])
expected_qc_states = [
"Claimed",
"Claimed",
"On hold",
"On hold external",
]
assert qc_states == expected_qc_states

factory = PacBioPagedWellsFactory(
Expand Down
9 changes: 5 additions & 4 deletions tests/test_qc_state_retrieval.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def test_bulk_retrieval(qcdb_test_session, load_data4well_retrieval):
# product IDs is performed.
assert get_qc_states_by_id_product_list(qcdb_test_session, ["dodo"]) == {}

qc_state_descriptions = ["On hold", "Failed, Instrument"]
qc_state_descriptions = ["On hold external", "Failed, Instrument"]

qc_states = get_qc_states_by_id_product_list(qcdb_test_session, two_good_ids_list)
assert len(qc_states) == 2
Expand Down Expand Up @@ -140,23 +140,23 @@ def test_product_qc_state_retrieval(qcdb_test_session, load_data4well_retrieval)
assert qc_state is not None
assert qc_state.seq_product.id_product == FIRST_GOOD_CHECKSUM
assert qc_state.qc_type.qc_type == "sequencing"
assert qc_state.qc_state_dict.state == "On hold"
assert qc_state.qc_state_dict.state == "On hold external"

qc_state = get_qc_state_for_product(
session=qcdb_test_session, id_product=FIRST_GOOD_CHECKSUM, qc_type="sequencing"
)
assert qc_state is not None
assert qc_state.seq_product.id_product == FIRST_GOOD_CHECKSUM
assert qc_state.qc_type.qc_type == "sequencing"
assert qc_state.qc_state_dict.state == "On hold"
assert qc_state.qc_state_dict.state == "On hold external"

qc_state = get_qc_state_for_product(
session=qcdb_test_session, id_product=FIRST_GOOD_CHECKSUM, qc_type="library"
)
assert qc_state is not None
assert qc_state.seq_product.id_product == FIRST_GOOD_CHECKSUM
assert qc_state.qc_type.qc_type == "library"
assert qc_state.qc_state_dict.state == "On hold"
assert qc_state.qc_state_dict.state == "On hold external"

qc_state = get_qc_state_for_product(qcdb_test_session, SECOND_GOOD_CHECKSUM)
assert qc_state is not None
Expand All @@ -183,6 +183,7 @@ def test_dict_helper(qcdb_test_session, load_dicts_and_users):
"Failed, SMRT cell",
"Claimed",
"On hold",
"On hold external",
"Undecided",
]
assert list(qc_state_dict(qcdb_test_session).keys()) == expected_sorted_states

0 comments on commit 0577d55

Please sign in to comment.