diff --git a/SigProfilerMatrixGenerator/controllers/cli_controller.py b/SigProfilerMatrixGenerator/controllers/cli_controller.py index 5d5e608..894afb9 100644 --- a/SigProfilerMatrixGenerator/controllers/cli_controller.py +++ b/SigProfilerMatrixGenerator/controllers/cli_controller.py @@ -1,8 +1,11 @@ import argparse from typing import List -from SigProfilerMatrixGenerator import install, test_helpers -from SigProfilerMatrixGenerator.scripts import SigProfilerMatrixGeneratorFunc as mg +from SigProfilerMatrixGenerator import test_helpers +from SigProfilerMatrixGenerator.scripts import ( + SigProfilerMatrixGeneratorFunc as mg, + reference_genome_manager, +) def parse_arguments_test(args: List[str]) -> argparse.Namespace: @@ -42,11 +45,11 @@ def parse_arguments_install(args: List[str]) -> argparse.Namespace: ) parser.add_argument( "-l", - "--local_install_genome", + "--local_genome", help=""" Install an offline reference genome downloaded from the Alexandrov Lab's FTP server. Provide the absolute path to the locally-stored genome file. - For downloads, visit AlexandrovLab's server: + For downloads, visit AlexandrovLab's ftp server: ftp://alexandrovlab-ftp.ucsd.edu/pub/tools/SigProfilerMatrixGenerator/ """, default=None, @@ -129,11 +132,13 @@ def parse_arguments_matrix_generator(args: List[str]) -> argparse.Namespace: class CliController: def dispatch_install(self, user_args: List[str]) -> None: parsed_args = parse_arguments_install(user_args) - install.install( - parsed_args.genome, - offline_files_path=parsed_args.local_install_genome, - volume=parsed_args.volume, - ) + rgm = reference_genome_manager.ReferenceGenomeManager(parsed_args.volume) + # ftp genome installation (default) + if parsed_args.local_genome is None: + rgm.download_genome(parsed_args.genome) + # local genome installation + else: + rgm.install_local_genome(parsed_args.genome, parsed_args.local_genome) def dispatch_test(self, user_args: List[str]) -> None: parsed_args = parse_arguments_test(user_args) diff --git a/SigProfilerMatrixGenerator/scripts/reference_genome_manager.py b/SigProfilerMatrixGenerator/scripts/reference_genome_manager.py index 3d8c79b..288a730 100644 --- a/SigProfilerMatrixGenerator/scripts/reference_genome_manager.py +++ b/SigProfilerMatrixGenerator/scripts/reference_genome_manager.py @@ -7,6 +7,7 @@ import logging import time +from pathlib import Path from SigProfilerMatrixGenerator.scripts import ref_install # Constants @@ -379,6 +380,39 @@ def download_genome(self, genome_name): local_filepath.unlink() logging.info(f"{genome_name} has been successfully installed.") + def install_local_genome(self, genome_name, local_genome_dir): + """ + Install a reference genome originating from the FTP server that is stored locally. + + - genome_name (str): The name of the genome. + - local_genome_dir (Path or str): The local directory path where the genome archive is stored. + """ + + local_genome_dir = Path(local_genome_dir) + archive_file_path = local_genome_dir / f"{genome_name}.tar.gz" + + # Verify that the local genome file exists + if not archive_file_path.exists(): + logging.error(f"Local genome file {archive_file_path} does not exist.") + return + + # Extract the archive + try: + self._unzip_file(archive_file_path) + except tarfile.TarError as e: + logging.error(f"Error extracting the archive: {e}") + return + + # Verify that all necessary files are extracted and have correct checksums + if not self.is_genome_installed(genome_name): + logging.error(f"Installation verification failed for {genome_name}.") + self.print_genome_checksum_verification_report(genome_name) + return + + logging.info( + f"{genome_name} has been successfully installed from the local file." + ) + def is_genome_installed(self, genome_name): """ Verifies whether all files for specified genome is fully and correctly installed. diff --git a/setup.py b/setup.py index 6ca7cf6..c48800a 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup -VERSION = "1.2.21" +VERSION = "1.2.22" # remove the dist folder first if exists if os.path.exists("dist"): @@ -23,7 +23,7 @@ def write_version_py(filename="SigProfilerMatrixGenerator/version.py"): # THIS FILE IS GENERATED FROM SIGPROFILEMATRIXGENERATOR SETUP.PY short_version = '%(version)s' version = '%(version)s' -Update = 'v1.2.21: Add reference_genome_manager and remove site-package benchmarking.' +Update = 'v1.2.22: CLI calls ReferenceGenomeManager to download reference genomes and not install.py' """ fh = open(filename, "w") diff --git a/tests/controllers/test_cli_controller.py b/tests/controllers/test_cli_controller.py index febe0e9..49118af 100644 --- a/tests/controllers/test_cli_controller.py +++ b/tests/controllers/test_cli_controller.py @@ -2,11 +2,26 @@ import pytest -from SigProfilerMatrixGenerator import install, test_helpers +from SigProfilerMatrixGenerator import test_helpers +from SigProfilerMatrixGenerator import install from SigProfilerMatrixGenerator.controllers import cli_controller +from SigProfilerMatrixGenerator.scripts import reference_genome_manager class TestController: + @pytest.fixture + def mock_ref_gen_manager(self, monkeypatch): + """Mock ReferenceGenomeManager for testing.""" + mock_manager = mock.create_autospec( + reference_genome_manager.ReferenceGenomeManager, instance=True + ) + monkeypatch.setattr( + reference_genome_manager, + "ReferenceGenomeManager", + lambda volume: mock_manager, + ) + return mock_manager + @pytest.fixture def mock_install(self, monkeypatch): """Temporarily change install.install with a mock object for testing""" @@ -21,11 +36,16 @@ def mock_test(self, monkeypatch): monkeypatch.setattr(test_helpers, "test_one_genome", mock_test) return mock_test - def test_dispatch_install(self, mock_install): + def test_dispatch_download_ftp_genome(self, mock_ref_gen_manager): + controller = cli_controller.CliController() + controller.dispatch_install(["GRCh37"]) + mock_ref_gen_manager.download_genome.assert_called_with("GRCh37") + + def test_dispatch_install_local_genome(self, mock_ref_gen_manager): controller = cli_controller.CliController() - controller.dispatch_install(["GRCh37", "--local_install_genome", "/somewhere"]) - mock_install.assert_called_with( - "GRCh37", offline_files_path="/somewhere", volume=None + controller.dispatch_install(["yeast", "--local_genome", "/somewhere"]) + mock_ref_gen_manager.install_local_genome.assert_called_with( + "yeast", "/somewhere" ) genome_calls = [