def test_active_samples_on_flow_cell( active_flow_cell_store: Store, flowcell_name: str, active_wipe_demultiplex_api: DeleteDemuxAPI, ): """Test if the function to find active samples works correctly""" # GIVEN a flowcell with active samples related to it store_: Store = active_flow_cell_store samples_on_flow_cell: List[Sample] = (store_.query(Flowcell).filter( Flowcell.name == flowcell_name).first().samples) assert samples_on_flow_cell for sample in samples_on_flow_cell: active: bool = store_.active_sample(internal_id=sample.internal_id) assert active # WHEN checking for active samples on flowcell active_wipe_demultiplex_api._set_samples_on_flow_cell() active_samples_on_flow_cell: Optional[ List[str]] = active_wipe_demultiplex_api.active_samples_on_flow_cell() # THEN there should be active samples found assert any(sample.internal_id in active_samples_on_flow_cell for sample in samples_on_flow_cell)
def demultiplex_flowcell( context: CGConfig, dry_run: bool, flowcell_id: str, bcl_converter: str, ): """Demultiplex a flowcell on slurm using CG flowcell-id is the flowcell run directory name, e.g. '201203_A00689_0200_AHVKJCDRXX' """ LOG.info("Running cg demultiplex flowcell, using %s.", bcl_converter) flowcell_directory: Path = Path(context.demultiplex.run_dir) / flowcell_id demultiplex_api: DemultiplexingAPI = context.demultiplex_api demultiplex_api.set_dry_run(dry_run=dry_run) LOG.info(f"SETTING FLOWCELL ID TO {flowcell_id}") LOG.info(f"SETTING OUT DIR TO {demultiplex_api.out_dir}") try: flowcell_obj = Flowcell(flowcell_path=flowcell_directory, bcl_converter=bcl_converter) except FlowcellError as e: raise click.Abort from e delete_demux_api: DeleteDemuxAPI = DeleteDemuxAPI( config=context, demultiplex_base=demultiplex_api.out_dir, dry_run=dry_run, run_path=flowcell_directory, ) delete_demux_api.delete_flow_cell( cg_stats=True, demultiplexing_dir=True, run_dir=False, housekeeper=True, init_files=True, status_db=False, ) if not demultiplex_api.is_demultiplexing_possible( flowcell=flowcell_obj) and not dry_run: LOG.warning("Can not start demultiplexing!") return if not flowcell_obj.validate_sample_sheet(): LOG.warning( "Malformed sample sheet. Run cg demultiplex samplesheet validate %s", flowcell_obj.sample_sheet_path, ) raise click.Abort slurm_job_id: int = demultiplex_api.start_demultiplexing( flowcell=flowcell_obj) tb_api: TrailblazerAPI = context.trailblazer_api demultiplex_api.add_to_trailblazer(tb_api=tb_api, slurm_job_id=slurm_job_id, flowcell=flowcell_obj)
def demultiplex_all(context: CGConfig, bcl_converter: str, flowcells_directory: click.Path, dry_run: bool): """Demultiplex all flowcells that are ready under the flowcells_directory""" LOG.info("Running cg demultiplex all, using %s.", bcl_converter) if flowcells_directory: flowcells_directory: Path = Path(str(flowcells_directory)) else: flowcells_directory: Path = Path(context.demultiplex.run_dir) demultiplex_api: DemultiplexingAPI = context.demultiplex_api demultiplex_api.set_dry_run(dry_run=dry_run) tb_api: TrailblazerAPI = context.trailblazer_api LOG.info("Search for flowcells ready to demultiplex in %s", flowcells_directory) for sub_dir in flowcells_directory.iterdir(): if not sub_dir.is_dir(): continue LOG.info("Found directory %s", sub_dir) try: flowcell_obj = Flowcell(flowcell_path=sub_dir, bcl_converter=bcl_converter) except FlowcellError: continue if not demultiplex_api.is_demultiplexing_possible( flowcell=flowcell_obj) and not dry_run: continue if not flowcell_obj.validate_sample_sheet(): LOG.warning( "Malformed sample sheet. Run cg demultiplex samplesheet validate %s", flowcell_obj.sample_sheet_path, ) continue delete_demux_api: DeleteDemuxAPI = DeleteDemuxAPI( config=context, demultiplex_base=demultiplex_api.out_dir, dry_run=dry_run, run_path=(flowcells_directory / sub_dir), ) delete_demux_api.delete_flow_cell( cg_stats=False, demultiplexing_dir=True, run_dir=False, housekeeper=True, init_files=False, status_db=False, ) slurm_job_id: int = demultiplex_api.start_demultiplexing( flowcell=flowcell_obj) demultiplex_api.add_to_trailblazer(tb_api=tb_api, slurm_job_id=slurm_job_id, flowcell=flowcell_obj)
def test_no_active_samples_on_flow_cell( populated_wipe_demultiplex_api: DeleteDemuxAPI, flowcell_name: str): """Test if the function to find no active samples works correctly""" # GIVEN a flowcell with no active samples related to it store_: Store = populated_wipe_demultiplex_api.status_db samples_on_flow_cell: List[Sample] = (store_.query(Flowcell).filter( Flowcell.name == flowcell_name).first().samples) assert samples_on_flow_cell for sample in samples_on_flow_cell: active: bool = store_.active_sample(internal_id=sample.internal_id) assert not active # WHEN checking for active samples on flowcell populated_wipe_demultiplex_api._set_samples_on_flow_cell() active_samples_on_flow_cell: Optional[List[ str]] = populated_wipe_demultiplex_api.active_samples_on_flow_cell() # THEN the no samples on the flowcell should be found active assert not active_samples_on_flow_cell
def fixture_active_wipe_demultiplex_api( active_wipe_demux_context: CGConfig, demultiplexed_flowcells_working_directory: Path, flowcell_full_name: str, ) -> DeleteDemuxAPI: """Yield an instantiated DeleteDemuxAPI with active samples on a flowcell""" return DeleteDemuxAPI( config=active_wipe_demux_context, demultiplex_base=demultiplexed_flowcells_working_directory, dry_run=False, run_path=Path(flowcell_full_name), )
def fixture_populated_wipe_demultiplex_api( populated_wipe_demux_context: CGConfig, demultiplexed_flowcells_working_directory: Path, tmp_flow_cell_run_path: Path, ) -> DeleteDemuxAPI: """Yield an initialized populated DeleteDemuxAPI""" return DeleteDemuxAPI( config=populated_wipe_demux_context, demultiplex_base=demultiplexed_flowcells_working_directory, dry_run=False, run_path=tmp_flow_cell_run_path, )
def fixture_wipe_demultiplex_api( cg_context: CGConfig, demultiplexed_flowcells_working_directory: Path, flowcell_full_name: str, stats_api: StatsAPI, ) -> DeleteDemuxAPI: """Yield an initialized DeleteDemuxAPI""" cg_context.cg_stats_api_ = stats_api return DeleteDemuxAPI( config=cg_context, demultiplex_base=demultiplexed_flowcells_working_directory, dry_run=False, run_path=Path(flowcell_full_name), )
def test_delete_flow_cell_housekeeper_only_sample_level( caplog, cg_context: CGConfig, demultiplexed_flowcells_working_directory: Path, flowcell_full_name: str, populated_flow_cell_store: Store, sample_level_housekeeper_api: HousekeeperAPI, tmp_fastq_paths: List[Path], ): """Test function to remove fastqs from Housekeeper when there are only files on sample level (not on flow cell name) """ caplog.set_level(logging.INFO) cg_context.housekeeper_api_ = sample_level_housekeeper_api cg_context.status_db_ = populated_flow_cell_store # GIVEN a DeleteDemuxAPI with a HousekeeperAPI with no files with flow cell name as a tag sample_level_files: List[Path] = tmp_fastq_paths wipe_demultiplex_api: DeleteDemuxAPI = DeleteDemuxAPI( config=cg_context, demultiplex_base=demultiplexed_flowcells_working_directory, dry_run=False, run_path=Path(flowcell_full_name), ) wipe_demultiplex_api._set_samples_on_flow_cell() # WHEN wiping files in Housekeeper wipe_demultiplex_api.delete_flow_cell_housekeeper() # THEN you should be notified that there are no files on flow cell names assert ( f"Housekeeper: No files found with tag: {wipe_demultiplex_api.flow_cell_name}" in caplog.text) # AND you should be notified that there were fastq files removed on sample level for file in sample_level_files: assert f"{file.as_posix()} deleted" in caplog.text
def test_delete_flow_cell_housekeeper_flowcell_name( caplog, cg_context: CGConfig, demultiplexed_flowcells_working_directory: Path, flow_cell_name_housekeeper_api: HousekeeperAPI, flowcell_full_name: str, populated_flow_cell_store: Store, tmp_fastq_paths: List[Path], tmp_sample_sheet_path: Path, ): """Test function to remove files from Housekeeper using flow cell name as a tag""" caplog.set_level(logging.INFO) cg_context.housekeeper_api_ = flow_cell_name_housekeeper_api cg_context.status_db_ = populated_flow_cell_store # GIVEN fastq_files: List[Path] = tmp_fastq_paths sample_sheet_file: Path = tmp_sample_sheet_path wipe_demultiplex_api: DeleteDemuxAPI = DeleteDemuxAPI( config=cg_context, demultiplex_base=demultiplexed_flowcells_working_directory, dry_run=False, run_path=Path(flowcell_full_name), ) wipe_demultiplex_api._set_samples_on_flow_cell() # WHEN wipe_demultiplex_api.delete_flow_cell_housekeeper() # THEN assert ( f"Housekeeper: No files found with tag: {wipe_demultiplex_api.flow_cell_name}" not in caplog.text) assert f"Deleted {sample_sheet_file.as_posix()} from housekeeper" in caplog.text for fastq_file in fastq_files: assert f"{fastq_file.as_posix()} deleted" in caplog.text
def test_set_dry_run_delete_demux_api( caplog, cg_context: CGConfig, demultiplexed_flowcells_working_directory: Path, flowcell_full_name: str, stats_api: StatsAPI, ): """Test to test function to set the API to run in dry run mode""" caplog.set_level(logging.DEBUG) cg_context.cg_stats_api_ = stats_api # WHEN setting the dry_run mode on a DeleteDemuxAPI wipe_demultiplex_api: DeleteDemuxAPI = DeleteDemuxAPI( config=cg_context, demultiplex_base=demultiplexed_flowcells_working_directory, dry_run=True, run_path=flowcell_full_name, ) # THEN the dry run parameter should be set to True and it should be logged assert wipe_demultiplex_api.dry_run assert f"DeleteDemuxAPI: Setting dry run mode to True" in caplog.text
def test_initiate_delete_demux_api( caplog, cg_context: CGConfig, demultiplexed_flowcells_working_directory: Path, flowcell_full_name: str, ): """Test to initialize the DeleteDemuxAPI""" caplog.set_level(logging.DEBUG) # GIVEN a correct config config = cg_context # WHEN initializing the DeleteDemuxAPI DeleteDemuxAPI( config=config, demultiplex_base=demultiplexed_flowcells_working_directory, dry_run=True, run_path=flowcell_full_name, ) # THEN the API should be correctly initialized assert "DeleteDemuxAPI: API initiated" in caplog.text
def delete_flow_cell( context: CGConfig, dry_run: bool, demultiplexing_dir: str, cg_stats: bool, demultiplex_base: bool, housekeeper: bool, init_files: bool, run_dir: bool, run_directory: str, status_db: bool, yes: bool, ): """Delete a flowcell. If --status-db is passed then all other options will be treated as True""" demultiplex_base: Path = Path(demultiplex_base) run_path: Path = Path(run_directory) wipe_demux_api: DeleteDemuxAPI = DeleteDemuxAPI( config=context, demultiplex_base=demultiplex_base, dry_run=dry_run, run_path=run_path) if yes or click.confirm( f"Are you sure you want to delete the flow cell from the following databases:\n" f"cg-stats={True if status_db else cg_stats}\nDemultiplexing-dir={True if status_db else demultiplexing_dir}\n" f"Housekeeper={True if status_db else housekeeper}\nInit_files={True if status_db else init_files}\n" f"Run-dir={True if status_db else run_dir}\nStatusdb={status_db}"): wipe_demux_api.delete_flow_cell( cg_stats=cg_stats, demultiplexing_dir=demultiplexing_dir, housekeeper=housekeeper, init_files=init_files, run_dir=run_dir, status_db=status_db, )