diff --git a/dataflow_transfer/run_classes/__init__.py b/dataflow_transfer/run_classes/__init__.py index 705c5c7..ffb1215 100644 --- a/dataflow_transfer/run_classes/__init__.py +++ b/dataflow_transfer/run_classes/__init__.py @@ -5,6 +5,7 @@ MiSeqRun, # noqa: F401 NextSeqRun, # noqa: F401 NovaSeqXPlusRun, # noqa: F401 + MiSeqi100Run, # noqa: F401 ) from dataflow_transfer.run_classes.ont_runs import MinIONRun, PromethIONRun # noqa: F401 diff --git a/dataflow_transfer/run_classes/element_runs.py b/dataflow_transfer/run_classes/element_runs.py index 97f448e..a3ea109 100644 --- a/dataflow_transfer/run_classes/element_runs.py +++ b/dataflow_transfer/run_classes/element_runs.py @@ -22,6 +22,6 @@ class AVITIRun(ElementRun): def __init__(self, run_dir, configuration): self.run_id_format = ( - "^\d{8}_AV\d{6}_(A|BP)\d{10}$" # 20251007_AV242106_A2507535225 + r"^\d{8}_AV\d{6}_(A|BP)\d{10}$" # 20251007_AV242106_A2507535225 ) super().__init__(run_dir, configuration) diff --git a/dataflow_transfer/run_classes/illumina_runs.py b/dataflow_transfer/run_classes/illumina_runs.py index b74bb4c..3e35acb 100644 --- a/dataflow_transfer/run_classes/illumina_runs.py +++ b/dataflow_transfer/run_classes/illumina_runs.py @@ -20,7 +20,7 @@ class NovaSeqXPlusRun(IlluminaRun): def __init__(self, run_dir, configuration): self.run_id_format = ( - "^\d{8}_[A-Z0-9]+_\d{4}_[A-Z0-9]+$" # 20251010_LH00202_0284_B22CVHTLT1 + r"^\d{8}_[A-Z0-9]+_\d{4}_[A-Z0-9]+$" # 20251010_LH00202_0284_B22CVHTLT1 ) super().__init__(run_dir, configuration) @@ -33,7 +33,7 @@ class NextSeqRun(IlluminaRun): def __init__(self, run_dir, configuration): self.run_id_format = ( - "^\d{6}_[A-Z0-9]+_\d{3}_[A-Z0-9]+$" # 251015_VH00203_572_AAHFHCCM5 + r"^\d{6}_[A-Z0-9]+_\d{3}_[A-Z0-9]+$" # 251015_VH00203_572_AAHFHCCM5 ) super().__init__(run_dir, configuration) @@ -46,6 +46,17 @@ class MiSeqRun(IlluminaRun): def __init__(self, run_dir, configuration): self.run_id_format = ( - "^\d{6}_[A-Z0-9]+_\d{4}_[A-Z0-9\-]+$" # 251015_M01548_0646_000000000-M6D7K + r"^\d{6}_[A-Z0-9]+_\d{4}_[A-Z0-9\-]+$" # 251015_M01548_0646_000000000-M6D7K ) super().__init__(run_dir, configuration) + + +@register_run_class +class MiSeqi100Run(IlluminaRun): + """Defines a MiSeqi100 sequencing run""" + + run_type = "MiSeqi100" + + def __init__(self, run_dir, configuration): + self.run_id_format = r"^\d{8}_[A-Z0-9]+_\d{4}_[A-Z0-9]{10}-SC3$" # 20260128_SH01140_0002_ASC2150561-SC3 + super().__init__(run_dir, configuration) diff --git a/dataflow_transfer/run_classes/ont_runs.py b/dataflow_transfer/run_classes/ont_runs.py index dfd11d7..243b685 100644 --- a/dataflow_transfer/run_classes/ont_runs.py +++ b/dataflow_transfer/run_classes/ont_runs.py @@ -19,7 +19,7 @@ class PromethIONRun(ONTRun): run_type = "PromethION" def __init__(self, run_dir, configuration): - self.run_id_format = "^\d{8}_\d{4}_[A-Z0-9]{2}_P[A-Z0-9]+_[a-f0-9]{8}$" # 20251015_1051_3B_PBG60686_0af3a2e0 + self.run_id_format = r"^\d{8}_\d{4}_[A-Z0-9]{2}_P[A-Z0-9]+_[a-f0-9]{8}$" # 20251015_1051_3B_PBG60686_0af3a2e0 super().__init__(run_dir, configuration) @@ -30,5 +30,5 @@ class MinIONRun(ONTRun): run_type = "MinION" def __init__(self, run_dir, configuration): - self.run_id_format = "^\d{8}_\d{4}_MN[A-Z0-9]+_[A-Z0-9]+_[a-f0-9]{8}$" # 20240229_1404_MN19414_ASH657_7a74bf8f + self.run_id_format = r"^\d{8}_\d{4}_MN[A-Z0-9]+_[A-Z0-9]+_[a-f0-9]{8}$" # 20240229_1404_MN19414_ASH657_7a74bf8f super().__init__(run_dir, configuration) diff --git a/dataflow_transfer/tests/test_run_classes.py b/dataflow_transfer/tests/test_run_classes.py index 8f46a92..09457fe 100644 --- a/dataflow_transfer/tests/test_run_classes.py +++ b/dataflow_transfer/tests/test_run_classes.py @@ -85,6 +85,32 @@ def miseqseq_testobj(tmp_path): return illumina_runs.MiSeqRun(str(run_dir), config) +@pytest.fixture +def miseqseqi100_testobj(tmp_path): + config = { + "log": {"file": "test.log"}, + "transfer_details": {"user": "testuser", "host": "testhost"}, + "statusdb": { + "username": "dbuser", + "password": "dbpass", + "url:": "dburl", + "database": "dbname", + }, + "sequencers": { + "MiSeqi100": { + "miarka_destination": "/data/MiSeqi100", + "metadata_for_statusdb": ["RunInfo.xml", "RunParameters.xml"], + "ignore_folders": ["nosync"], + "rsync_options": ["--chmod=Dg+s,g+rw"], + } + }, + } + run_id = "20260128_SH01140_0002_ASC2150561-SC3" + run_dir = tmp_path / run_id + run_dir.mkdir() + return illumina_runs.MiSeqi100Run(str(run_dir), config) + + @pytest.fixture(autouse=True) def mock_statusdbsession(monkeypatch): class MockStatusdbSession: @@ -106,6 +132,7 @@ def update_db_doc(self, doc): ("novaseqxplus_testobj", "NovaSeqXPlus"), ("nextseq_testobj", "NextSeq"), ("miseqseq_testobj", "MiSeq"), + ("miseqseqi100_testobj", "MiSeqi100"), ], ) def test_confirm_run_type(run_fixture, expected_run_type, request): @@ -124,6 +151,7 @@ def test_confirm_run_type(run_fixture, expected_run_type, request): "novaseqxplus_testobj", "nextseq_testobj", "miseqseq_testobj", + "miseqseqi100_testobj", ], ) def test_sequencing_ongoing(run_fixture, request): @@ -146,6 +174,8 @@ def test_sequencing_ongoing(run_fixture, request): ("nextseq_testobj", True), ("miseqseq_testobj", False), ("miseqseq_testobj", True), + ("miseqseqi100_testobj", False), + ("miseqseqi100_testobj", True), ], ) def test_generate_rsync_command(run_fixture, final_sync, request): @@ -174,6 +204,10 @@ def test_generate_rsync_command(run_fixture, final_sync, request): ("miseqseq_testobj", True, False), ("miseqseq_testobj", False, True), ("miseqseq_testobj", True, True), + ("miseqseqi100_testobj", False, False), + ("miseqseqi100_testobj", True, False), + ("miseqseqi100_testobj", False, True), + ("miseqseqi100_testobj", True, True), ], ) def test_start_transfer(run_fixture, rsync_running, final, request, monkeypatch): @@ -219,6 +253,8 @@ def mock_update_statusdb(status, additional_info=None): ("nextseq_testobj", False), ("miseqseq_testobj", True), ("miseqseq_testobj", False), + ("miseqseqi100_testobj", True), + ("miseqseqi100_testobj", False), ], ) def test_final_sync_successful(run_fixture, sync_successful, request): @@ -249,6 +285,10 @@ def test_final_sync_successful(run_fixture, sync_successful, request): ("miseqseq_testobj", "sequencing_started", True), ("miseqseq_testobj", "sequencing_finished", False), ("miseqseq_testobj", "sequencing_finished", True), + ("miseqseqi100_testobj", "sequencing_started", False), + ("miseqseqi100_testobj", "sequencing_started", True), + ("miseqseqi100_testobj", "sequencing_finished", False), + ("miseqseqi100_testobj", "sequencing_finished", True), ], ) def test_has_status(run_fixture, status_to_check, expected_result, request): @@ -268,6 +308,12 @@ def get_events(self, run_id): @pytest.mark.parametrize( "run_fixture, existing_statuses, status_to_update", [ + ("novaseqxplus_testobj", [], "sequencing_started"), + ( + "novaseqxplus_testobj", + [{"event_type": "sequencing_started"}], + "transfer_started", + ), ( "nextseq_testobj", [], @@ -288,6 +334,16 @@ def get_events(self, run_id): [{"event_type": "sequencing_started"}], "transfer_started", ), + ( + "miseqseqi100_testobj", + [], + "sequencing_started", + ), + ( + "miseqseqi100_testobj", + [{"event_type": "sequencing_started"}], + "transfer_started", + ), ], ) def test_update_statusdb( diff --git a/pyproject.toml b/pyproject.toml index 88ed6df..e8b5d7b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ ignore = [ [project] name = "dataflow_transfer" -version = "1.0.4" +version = "1.0.5" description = "Script for transferring sequencing data from sequencers to storage" authors = [ { name = "Sara Sjunnebo", email = "sara.sjunnebo@scilifelab.se" },