Skip to content

Commit

Permalink
Merge pull request #131 from AlexandrovLab/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
mdbarnesUCSD authored Jun 24, 2024
2 parents 7077caf + a56f325 commit 8bf4694
Show file tree
Hide file tree
Showing 17 changed files with 176 additions and 28 deletions.
8 changes: 6 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ before_install:
fi

install:
- pip install .
- pip install .[tests]

before_script:
- python3 install_genome.py $TRAVIS_BUILD_DIR/src/

script: python3 test.py
script:
# run unit tests
- pytest tests
# run integration tests
- python3 test.py
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.1.7] - 2024-06-21

### Added
- Added CLI boolean handling to improve command-line interface usability.
- Added new pytests for CLI to ensure correct handling of booleans.
- Updated the README to reflect the new pytest additions.
- Updated CI/CD pipelines to accommodate pytest changes.

### Changed
- Improved input_type value check mechanism to use .lower() before checking against values 'vcf' or 'matrix'.
- Updated dependency from PyPDF2 to pypdf to increase compatibility and resolve installation issues on bioconda.


9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,15 @@ Analyze.cosmic_fit(samples=spa.__path__[0]+"/data/tests/txt_input/sample_matrix_
## <a name="denovo"></a> _De novo_ extraction of mutational signatures downstream analysis
Additional functionalities for downstream analysis of _de novo_ extraction of mutational signatures are also available as part of SigProfilerAssignment, including assignment of _de novo_ extracted mutational signatures and decomposition of _de novo_ signatures using a known set of signatures. More information can be found on the wiki page at https://osf.io/mz79v/wiki/5.%20Advanced%20mode/.

## <a name="unit_tests"></a> Unit Tests
Unit tests can be run with the following commands:

```bash
python setup.py sdist
pip install .[tests]
pytest tests
```

## <a name="citation"></a> Citation

Díaz-Gay, M., Vangara, R., Barnes, M., ... & Alexandrov, L. B. (2023). Assigning mutational signatures to individual samples and individual somatic mutations with SigProfilerAssignment, Bioinformatics, 2023-07. doi: [https://doi.org/10.1093/bioinformatics/btad756](https://doi.org/10.1093/bioinformatics/btad756)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
import SigProfilerAssignment as spa_path
from PyPDF2 import PdfWriter, PdfReader
from pypdf import PdfWriter, PdfReader

# imports for saving plots to memory
import io
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
import SigProfilerAssignment as spa_path
from PyPDF2 import PdfWriter, PdfReader
from pypdf import PdfWriter, PdfReader

# imports for saving plots to memory
import io
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
import SigProfilerAssignment as spa_path
from PyPDF2 import PdfWriter, PdfReader
from pypdf import PdfWriter, PdfReader

# imports for saving plots to memory
import io
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
import SigProfilerAssignment as spa_path
from PyPDF2 import PdfWriter, PdfReader
from pypdf import PdfWriter, PdfReader

# imports for saving plots to memory
import io
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
import SigProfilerAssignment as spa_path
from PyPDF2 import PdfWriter, PdfReader
from pypdf import PdfWriter, PdfReader

# imports for saving plots to memory
import io
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
import SigProfilerAssignment as spa_path
from PyPDF2 import PdfWriter, PdfReader
from pypdf import PdfWriter, PdfReader

# imports for saving plots to memory
import io
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase import pdfmetrics
import SigProfilerAssignment as spa_path
from PyPDF2 import PdfWriter, PdfReader
from pypdf import PdfWriter, PdfReader

# imports for saving plots to memory
import io
Expand Down
45 changes: 38 additions & 7 deletions SigProfilerAssignment/controllers/cli_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
from SigProfilerAssignment import decomposition as decomp


def str2bool(v):
if isinstance(v, bool):
return v
if v.lower() in ("yes", "true", "t", "y", "1"):
return True
elif v.lower() in ("no", "false", "f", "n", "0"):
return False
else:
raise argparse.ArgumentTypeError("Boolean value expected.")


def parse_arguments_common(args: List[str], description: str) -> argparse.Namespace:
parser = argparse.ArgumentParser(description=description)

Expand Down Expand Up @@ -43,22 +54,36 @@ def parse_arguments_common(args: List[str], description: str) -> argparse.Namesp
help="COSMIC version (default: 3.4). Valid options: {1, 2, 3, 3.1, 3.2, 3.3, 3.4}.",
)
parser.add_argument(
"--make_plots", type=bool, default=True, help="Generate plots (default: True)."
"--make_plots",
type=str2bool,
nargs="?",
const=True,
default=True,
help="Generate plots (default: True).",
)
parser.add_argument(
"--collapse_to_SBS96",
type=bool,
type=str2bool,
nargs="?",
const=True,
default=True,
help="Collapse to SBS96 (default: True).",
)
parser.add_argument(
"--connected_sigs",
type=bool,
type=str2bool,
nargs="?",
const=True,
default=True,
help="Connected signatures (default: True).",
)
parser.add_argument(
"--verbose", type=bool, default=False, help="Verbose output (default: False)."
"--verbose",
type=str2bool,
nargs="?",
const=True,
default=False,
help="Verbose output (default: False).",
)
parser.add_argument(
"--new_signature_thresh_hold",
Expand All @@ -73,7 +98,9 @@ def parse_arguments_common(args: List[str], description: str) -> argparse.Namesp
)
parser.add_argument(
"--exome",
type=bool,
type=str2bool,
nargs="?",
const=True,
default=False,
help="Use exome renormalized COSMIC signatures (default: False).",
)
Expand All @@ -89,13 +116,17 @@ def parse_arguments_common(args: List[str], description: str) -> argparse.Namesp
)
parser.add_argument(
"--export_probabilities",
type=bool,
type=str2bool,
nargs="?",
const=True,
default=True,
help="Export probabilities matrix per mutational context (default: True).",
)
parser.add_argument(
"--export_probabilities_per_mutation",
type=bool,
type=str2bool,
nargs="?",
const=True,
default=False,
help="Export probabilities matrices per mutation (default: False).",
)
Expand Down
8 changes: 4 additions & 4 deletions SigProfilerAssignment/decompose_subroutines.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@
from sigProfilerPlotting import plotActivity as plot_ac
from sigProfilerPlotting import tmbplot as tmb
import string
import PyPDF2
import pypdf
import scipy

# import SigProfilerAssignment as sspro
from PyPDF2 import PdfMerger
from pypdf import PdfMerger
import SigProfilerAssignment as spa
from SigProfilerAssignment import single_sample as ss
from scipy.spatial.distance import correlation as cor
Expand Down Expand Up @@ -1776,10 +1776,10 @@ def merge_pdf(input_folder, output_file):
pdf2merge.append(filename)

pdf2merge.sort()
pdfWriter = PyPDF2.PdfFileWriter()
pdfWriter = pypdf.PdfFileWriter()
for filename in pdf2merge:
pdfFileObj = open(input_folder + "/" + filename, "rb")
pdfReader = PyPDF2.PdfFileReader(pdfFileObj)
pdfReader = pypdf.PdfFileReader(pdfFileObj)
for pageNum in range(pdfReader.numPages):
pageObj = pdfReader.getPage(pageNum)
pdfWriter.addPage(pageObj)
Expand Down
6 changes: 3 additions & 3 deletions SigProfilerAssignment/decomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from sigProfilerPlotting import sigProfilerPlotting as sigPlot
import sigProfilerPlotting
import os, sys
from PyPDF2 import PdfMerger
from pypdf import PdfMerger
import fitz
import time
from pathlib import Path
Expand Down Expand Up @@ -305,7 +305,7 @@ def spa_analyze(
"If denovo_refit or decompose_fit is True, signatures cannot be empty"
)

if input_type == "vcf":
if input_type.lower() == "vcf":
project_name = "Input_vcffiles"
vcf_context = context_type
data = datadump.SigProfilerMatrixGeneratorFunc(
Expand All @@ -329,7 +329,7 @@ def spa_analyze(
)
genomes = genomes.set_index("MutationType")

elif input_type == "matrix":
elif input_type.lower() == "matrix":
try:
genomes = pd.read_csv(samples, sep="\t", index_col=0)
except:
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ statsmodels
scikit-learn
psutil
reportlab
PyPDF2
pypdf
alive_progress
11 changes: 8 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
if os.path.exists("dist"):
shutil.rmtree("dist")

VERSION = "0.1.6"
VERSION = "0.1.7"


def write_version_py(filename="SigProfilerAssignment/version.py"):
Expand All @@ -15,7 +15,7 @@ def write_version_py(filename="SigProfilerAssignment/version.py"):
# THIS FILE IS GENERATED FROM SigProfilerAssignment SETUP.PY
short_version = '%(version)s'
version = '%(version)s'
Update = 'v0.1.6: Add CLI and volume parameter for template files.'
Update = 'v0.1.7: Update CLI, add pytest, and update pypdf dependency.'
"""
Expand All @@ -42,7 +42,7 @@ def write_version_py(filename="SigProfilerAssignment/version.py"):
"scikit-learn>=0.24.2",
"psutil>=5.6.1",
"reportlab>=3.5.42",
"PyPDF2>=3.0.0",
"pypdf>=3.1.0",
"alive_progress>=2.4.1",
"pdf2image>=1.16.0",
"PyMuPDF>=1.21.0",
Expand All @@ -61,6 +61,11 @@ def write_version_py(filename="SigProfilerAssignment/version.py"):
license="UCSD",
packages=["SigProfilerAssignment"],
install_requires=requirements,
extras_require={
"tests": [
"pytest",
],
},
include_package_data=True,
entry_points={
"console_scripts": [
Expand Down
2 changes: 1 addition & 1 deletion test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import SigProfilerAssignment as spa
from SigProfilerAssignment import Analyzer as Analyze
from SigProfilerAssignment.DecompositionPlots import PlotDecomposition as sp
from PyPDF2 import PdfMerger
from pypdf import PdfMerger
import numpy as np
import pandas as pd
import time
Expand Down
77 changes: 77 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import pytest
import argparse
from SigProfilerAssignment.controllers.cli_controller import (
parse_arguments_common,
str2bool,
)


def test_default_values():
args = parse_arguments_common(
["dummy_sample", "dummy_output"], "Test default values"
)
assert args.make_plots == True
assert args.collapse_to_SBS96 == True
assert args.connected_sigs == True
assert args.verbose == False
assert args.export_probabilities == True
assert args.export_probabilities_per_mutation == False
assert args.exome == False


def test_argument_parsing():
args = parse_arguments_common(
[
"dummy_sample",
"dummy_output",
"--genome_build",
"GRCh38",
"--cosmic_version",
"3.4",
"--make_plots",
"False",
"--collapse_to_SBS96",
"False",
"--connected_sigs",
"False",
"--verbose",
"True",
"--export_probabilities",
"False",
"--export_probabilities_per_mutation",
"True",
"--exome",
"True",
],
"Test argument parsing",
)
assert args.samples == "dummy_sample"
assert args.output == "dummy_output"
assert args.genome_build == "GRCh38"
assert args.cosmic_version == 3.4
assert args.make_plots == False
assert args.collapse_to_SBS96 == False
assert args.connected_sigs == False
assert args.verbose == True
assert args.export_probabilities == False
assert args.export_probabilities_per_mutation == True
assert args.exome == True


def test_boolean_conversion():
assert str2bool("yes") == True
assert str2bool("true") == True
assert str2bool("t") == True
assert str2bool("y") == True
assert str2bool("1") == True
assert str2bool("no") == False
assert str2bool("false") == False
assert str2bool("f") == False
assert str2bool("n") == False
assert str2bool("0") == False
with pytest.raises(argparse.ArgumentTypeError):
str2bool("maybe")


if __name__ == "__main__":
pytest.main()

0 comments on commit 8bf4694

Please sign in to comment.