├── .circleci └── config.yml ├── .dockerignore ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── envs │ └── test_env.yml └── workflows │ ├── .pylintrc │ ├── aws_ecr.yml │ ├── integration_tests.yml │ ├── pylint.yml │ └── pytest.yml ├── .gitignore ├── CRISPResso2 ├── CRISPResso2Align.c ├── CRISPResso2Align.pyx ├── CRISPRessoAggregateCORE.py ├── CRISPRessoBatchCORE.py ├── CRISPRessoCORE.py ├── CRISPRessoCOREResources.c ├── CRISPRessoCOREResources.pyx ├── CRISPRessoCompareCORE.py ├── CRISPRessoMetaCORE.py ├── CRISPRessoMultiProcessing.py ├── CRISPRessoPlot.py ├── CRISPRessoPooledCORE.py ├── CRISPRessoPooledWGSCompareCORE.py ├── CRISPRessoReports │ ├── .gitattributes │ ├── .github │ │ └── workflows │ │ │ ├── .pylintrc │ │ │ └── pylint.yml │ ├── CRISPRessoReport.py │ ├── README.md │ ├── __init__.py │ ├── jinja_partials.py │ └── templates │ │ ├── CRISPResso_justcup.png │ │ ├── batchReport.html │ │ ├── favicon.ico │ │ ├── layout.html │ │ ├── multiReport.html │ │ ├── pooledReport.html │ │ ├── report.html │ │ ├── shared │ │ └── partials │ │ │ ├── failed_runs.html │ │ │ ├── fig_reports.html │ │ │ ├── fig_summaries.html │ │ │ ├── guardrail_warnings.html │ │ │ ├── log_params.html │ │ │ └── report_footer_buttons.html │ │ └── wgsReport.html ├── CRISPRessoShared.py ├── CRISPRessoWGSCORE.py ├── EDNAFULL ├── README ├── __init__.py ├── args.json ├── default_style.json ├── filterFastqs.py ├── setupLocal.py └── setupLocal.sh ├── CRISPResso2_router.py ├── Dockerfile ├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── build.sh ├── crispresso_schematic.png ├── pyproject.toml ├── scripts ├── Load Plots.ipynb ├── countHighQualityBases.py ├── count_sgRNA_specific_edits.py ├── filterReadsOnSequencePresence.py ├── plotAmbiguous.py └── plotCustomAllelePlot.py ├── setup.cfg ├── setup.py └── tests ├── Both.Cas9.fastq ├── Both.Cas9.fastq.hg38.bam ├── Both.Cas9.fastq.hg38.bam.bai ├── Both.Cas9.fastq.smallGenome.bam ├── Both.Cas9.fastq.smallGenome.bam.bai ├── Cas9.amplicons.txt ├── Cas9.regions.txt ├── FANC.Cas9.fastq ├── FANC.Untreated.fastq ├── FANC.batch ├── FANC.local.batch ├── HEK3.Cas9.fastq ├── Makefile ├── expectedResults ├── CRISPRessoBatch_on_FANC │ └── MODIFICATION_FREQUENCY_SUMMARY.txt ├── CRISPRessoCompare_on_Cas9_VS_Untreated │ └── Alleles_frequency_table_around_sgRNA_GGAATCCCTTCTGCAGCACC.txt ├── CRISPRessoPooled_on_Both.Cas9 │ └── SAMPLES_QUANTIFICATION_SUMMARY.txt ├── CRISPRessoWGS_on_Both.Cas9.fastq.smallGenome │ └── SAMPLES_QUANTIFICATION_SUMMARY.txt ├── CRISPResso_on_FANC.Cas9 │ ├── CRISPResso_quantification_of_editing_frequency.txt │ └── Nucleotide_frequency_table.txt └── CRISPResso_on_params │ ├── CRISPResso_quantification_of_editing_frequency.txt │ └── FANC.Nucleotide_frequency_table.txt ├── smallGenome ├── smallGenome.1.bt2 ├── smallGenome.2.bt2 ├── smallGenome.3.bt2 ├── smallGenome.4.bt2 ├── smallGenome.fa ├── smallGenome.fa.fai ├── smallGenome.rev.1.bt2 └── smallGenome.rev.2.bt2 ├── testRelease.sh └── unit_tests ├── README.md ├── test_CRISPResso2Align.py ├── test_CRISPRessoBatchCORE.py ├── test_CRISPRessoCORE.py ├── test_CRISPRessoCOREResources.py ├── test_CRISPRessoCompareCORE.py ├── test_CRISPRessoPooledCORE.py └── test_CRISPRessoShared.py /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Python CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-python/ for more details 4 | # 5 | version: 2 6 | jobs: 7 | build: 8 | docker: 9 | # specify the version you desire here 10 | # use `-browsers` prefix for selenium tests, e.g. `3.6.1-browsers` 11 | - image: pinellolab/crispresso2:v2.3.0 12 | 13 | # Specify service dependencies here if necessary 14 | # CircleCI maintains a library of pre-built images 15 | # documented at https://circleci.com/docs/2.0/circleci-images/ 16 | # - image: circleci/postgres:9.4 17 | 18 | working_directory: ~/repo 19 | 20 | steps: 21 | - checkout 22 | 23 | # Download and cache dependencies 24 | # - restore_cache: 25 | # keys: 26 | # - v1-dependencies-{{ checksum "setup.py" }} 27 | # fallback to using the latest cache if no exact match is found 28 | # - v1-dependencies- 29 | 30 | - run: 31 | name: install dependencies 32 | command: | 33 | rm -rf /opt/conda/bin/CRISPRess* 34 | rm -rf /opt/conda/lib/python*/site-packages/CRISPResso2* 35 | python setup.py install 36 | 37 | - save_cache: 38 | paths: 39 | - /opt/conda/ 40 | key: v1-dependencies-{{ checksum "setup.py" }} 41 | 42 | # run tests! 43 | - run: 44 | name: test-alive 45 | command: | 46 | CRISPResso -h 47 | 48 | - run: 49 | name: test-crispresso 50 | command: | 51 | CRISPResso -r1 tests/FANC.Cas9.fastq -a CGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCGGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -g GGAATCCCTTCTGCAGCACC --debug > test-crispresso.out 2>&1 52 | diff CRISPResso_on_FANC.Cas9/Nucleotide_frequency_table.txt tests/expectedResults/CRISPResso_on_FANC.Cas9/Nucleotide_frequency_table.txt >> test-crispresso.out 2>&1 53 | diff CRISPResso_on_FANC.Cas9/CRISPResso_quantification_of_editing_frequency.txt tests/expectedResults/CRISPResso_on_FANC.Cas9/CRISPResso_quantification_of_editing_frequency.txt >> test-crispresso.out 2>&1 54 | 55 | - run: 56 | name: test-crispresso-with-params 57 | command: | 58 | CRISPResso -r1 tests/FANC.Cas9.fastq -a CGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCGGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -g GGAATCCCTTCTGCAGCACC -e CGGCCGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCTGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -c GGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTT --dump -qwc 20-30_45-50 -q 30 --default_min_aln_score 80 -an FANC -n params --base_edit -fg AGCCTTGCAGTGGGCGCGCTA,CCCACTGAAGGCCC --dsODN GCTAGATTTCCCAAGAAGA -gn hi -fgn dear --debug > test-crispresso-with-params.out 2>&1 59 | diff CRISPResso_on_params/FANC.Nucleotide_frequency_table.txt tests/expectedResults/CRISPResso_on_params/FANC.Nucleotide_frequency_table.txt >> test-crispresso-with-params.out 2>&1 60 | diff CRISPResso_on_params/CRISPResso_quantification_of_editing_frequency.txt tests/expectedResults/CRISPResso_on_params/CRISPResso_quantification_of_editing_frequency.txt >> test-crispresso-with-params.out 2>&1 61 | 62 | - run: 63 | name: test-crispresso-batch 64 | command: | 65 | CRISPRessoBatch -bs tests/FANC.batch -a CGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCGGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -g GGAATCCCTTCTGCAGCACC -p 2 --debug --base_editor --debug > test-crispresso-batch.out 66 | diff CRISPRessoBatch_on_FANC/MODIFICATION_FREQUENCY_SUMMARY.txt tests/expectedResults/CRISPRessoBatch_on_FANC/MODIFICATION_FREQUENCY_SUMMARY.txt >> test-crispresso-batch.out 2>&1 67 | 68 | - run: 69 | name: test-crispresso-pooled 70 | command: | 71 | CRISPRessoPooled -r1 tests/Both.Cas9.fastq -f tests/Cas9.amplicons.txt -p 2 --keep_intermediate --min_reads_to_use_region 100 --debug > test-crispresso-pooled.out 72 | diff CRISPRessoPooled_on_Both.Cas9/SAMPLES_QUANTIFICATION_SUMMARY.txt tests/expectedResults/CRISPRessoPooled_on_Both.Cas9/SAMPLES_QUANTIFICATION_SUMMARY.txt >> test-crispresso-pooled.out 2>&1 73 | 74 | - run: 75 | name: test-crispresso-wgs 76 | command: | 77 | CRISPRessoWGS -b tests/Both.Cas9.fastq.smallGenome.bam -r tests/smallGenome/smallGenome.fa -f tests/Cas9.regions.txt --debug > test-crispresso-wgs.out 2>&1 78 | diff CRISPRessoWGS_on_Both.Cas9.fastq.smallGenome/SAMPLES_QUANTIFICATION_SUMMARY.txt tests/expectedResults/CRISPRessoWGS_on_Both.Cas9.fastq.smallGenome/SAMPLES_QUANTIFICATION_SUMMARY.txt >> test-crispresso-wgs.out 2>&1 79 | - run: 80 | name: test-crispresso-compare 81 | command: | 82 | CRISPRessoCompare CRISPRessoBatch_on_FANC/CRISPResso_on_Cas9/ CRISPRessoBatch_on_FANC/CRISPResso_on_Untreated/ --debug > test-crispresso-compare.out 2>&1 83 | 84 | - store_artifacts: 85 | path: test-crispresso.out 86 | - store_artifacts: 87 | path: test-crispresso-with-params.out 88 | - store_artifacts: 89 | path: test-crispresso-batch.out 90 | - store_artifacts: 91 | path: test-crispresso-pooled.out 92 | - store_artifacts: 93 | path: test-crispresso-wgs.out 94 | - store_artifacts: 95 | path: test-crispresso-compare.out 96 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git* 2 | tests 3 | dist 4 | CRISPResso2/*.c 5 | CRISPResso2.egg-info 6 | build 7 | .git 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.py text eol=lf 2 | *.sh text eol=lf 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **To reproduce** 17 | CRISPResso command to reproduce the behavior. 18 | 19 | **Debug output** 20 | Paste the entire output when you run CRISPResso with the flag `--debug`. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/envs/test_env.yml: -------------------------------------------------------------------------------- 1 | name: test_env 2 | channels: 3 | - conda-forge 4 | - bioconda 5 | - defaults 6 | dependencies: 7 | - pip 8 | - fastp 9 | - numpy<2 10 | - cython 11 | - jinja2 12 | - tbb=2020.2 13 | - pyparsing=2.3.1 14 | - scipy 15 | - matplotlib=3.8.4 16 | - pandas>2 17 | - pytest-check 18 | - pip: 19 | - ydiff 20 | -------------------------------------------------------------------------------- /.github/workflows/.pylintrc: -------------------------------------------------------------------------------- 1 | [FORMAT] 2 | max-line-length=150 3 | max-args=15 4 | max-locals=40 5 | 6 | [MESSAGES CONTROL] 7 | disable = E0401, W0719 8 | -------------------------------------------------------------------------------- /.github/workflows/aws_ecr.yml: -------------------------------------------------------------------------------- 1 | name: Push Docker image to Amazon ECR 2 | 3 | on: 4 | release: 5 | types: 6 | - edited 7 | - released 8 | branches: 9 | - master 10 | 11 | jobs: 12 | build-and-push: 13 | name: Build and Push Docker image 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v2 19 | 20 | - id: get_version 21 | name: Get version 22 | uses: jannemattila/get-version-from-tag@v3 23 | 24 | - name: Configure AWS credentials 25 | uses: aws-actions/configure-aws-credentials@v1 26 | with: 27 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 28 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 29 | aws-region: us-east-1 30 | 31 | - name: Login to Amazon ECR 32 | id: login-ecr 33 | uses: aws-actions/amazon-ecr-login@v1 34 | 35 | - name: Build, tag, and push the image to Amazon ECR 36 | id: build-image 37 | env: 38 | AWS_ACCOUNT: ${{ secrets.AWS_ACCOUNT_ID }} 39 | ECR_REPOSITORY: 'crispresso2' 40 | AWS_REGION: 'us-east-1' 41 | IMAGE_TAG: v${{ steps.get_version.outputs.version }} 42 | run: | 43 | # Build a docker container and push it to ECR 44 | docker build -t $AWS_ACCOUNT.dkr.ecr.$AWS_REGION.amazonaws.com/$ECR_REPOSITORY:$IMAGE_TAG . 45 | echo "Pushing image to ECR..." 46 | docker push $AWS_ACCOUNT.dkr.ecr.$AWS_REGION.amazonaws.com/$ECR_REPOSITORY:$IMAGE_TAG 47 | echo "::set-output name=image::$AWS_ACCOUNT.dkr.ecr.$AWS_REGION.amazonaws.com/$ECR_REPOSITORY:$IMAGE_TAG" 48 | -------------------------------------------------------------------------------- /.github/workflows/integration_tests.yml: -------------------------------------------------------------------------------- 1 | name: Run Integration Tests 2 | 3 | on: 4 | push: 5 | 6 | pull_request: 7 | types: [opened, reopened] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | defaults: 13 | run: 14 | shell: bash -l {0} 15 | env: 16 | CRISPRESSO2_DIR: ${GITHUB_WORKSPACE}/../CRISPResso2_copy 17 | 18 | strategy: 19 | fail-fast: false 20 | 21 | steps: 22 | - uses: actions/checkout@v3 23 | 24 | - name: Setup Conda Env 25 | uses: conda-incubator/setup-miniconda@v3 26 | with: 27 | activate-environment: test_env 28 | channels: conda-forge,bioconda,defaults 29 | auto-activate-base: false 30 | use-mamba: true 31 | 32 | - name: Get Date 33 | run: echo "today=$(/bin/date -u '+%Y%m%d')" >> $GITHUB_OUTPUT 34 | shell: bash 35 | 36 | - name: Cache Conda Env 37 | id: cache-env 38 | uses: actions/cache@v3 39 | env: 40 | # Increase this number to reset the cache if envs/test_env.yml hasn't changed 41 | CACHE_NUMBER: 0 42 | with: 43 | path: /usr/share/miniconda/envs/test_env 44 | key: conda-${{ runner.os }}--${{ runner.arch }}--${{ steps.get-date.outputs.today }}-${{ env.CACHE_NUMBER }}-${{ hashFiles('.github/envs/test_env.yml') }} 45 | 46 | - name: Update Conda Env 47 | run: | 48 | conda env update -n test_env -f .github/envs/test_env.yml 49 | if: steps.cache-env.outputs.cache-hit != 'true' 50 | 51 | - name: Install dependencies 52 | run: | 53 | sudo apt-get update 54 | sudo apt-get install -y gcc g++ bowtie2 samtools libsys-hostname-long-perl 55 | conda list 56 | 57 | - name: Create directory for files 58 | run: | 59 | mkdir ../CRISPResso2_copy 60 | cp -r * ../CRISPResso2_copy 61 | 62 | - name: Copy C2_tests repo 63 | uses: actions/checkout@v3 64 | with: 65 | repository: edilytics/CRISPResso2_tests 66 | # ref: '' # update to specific branch 67 | 68 | - name: Run Basic 69 | run: | 70 | make basic test print 71 | 72 | - name: Run Params 73 | if: success() || failure() 74 | run: | 75 | make params test print 76 | 77 | - name: Run Prime Editor 78 | if: success() || failure() 79 | run: | 80 | make prime-editor test print 81 | 82 | - name: Run Native Merging 83 | if: success() || failure() 84 | run: | 85 | make nhej_native_merge test print 86 | 87 | - name: Run BAM Input 88 | if: success() || failure() 89 | run: | 90 | make bam test print 91 | 92 | - name: Run BAM Output 93 | if: success() || failure() 94 | run: | 95 | make bam-out test print 96 | 97 | - name: Run BAM Genome Output 98 | if: success() || failure() 99 | run: | 100 | make bam-out-genome test print 101 | 102 | - name: Run Batch 103 | if: success() || failure() 104 | run: | 105 | make batch test print 106 | 107 | - name: Run Pooled 108 | if: success() || failure() 109 | run: | 110 | make pooled test print 111 | 112 | - name: Run Pooled Mixed Mode 113 | if: success() || failure() 114 | run: | 115 | make pooled-mixed-mode test print 116 | 117 | - name: Run Pooled Mixed Mode Demux 118 | if: success() || failure() 119 | run: | 120 | make pooled-mixed-mode-genome-demux test print 121 | 122 | - name: Run Pooled Paired Sim 123 | if: success() || failure() 124 | run: | 125 | make pooled-paired-sim test print 126 | 127 | - name: Run WGS 128 | if: success() || failure() 129 | run: | 130 | make wgs test print 131 | 132 | - name: Run Compare 133 | if: success() || failure() 134 | run: | 135 | make compare test print 136 | 137 | - name: Run Aggregate 138 | if: success() || failure() 139 | run: | 140 | make aggregate test print 141 | 142 | - name: Run Asym Allele Plot Left 143 | if: success() || failure() 144 | run: | 145 | make asym-left test print 146 | 147 | - name: Run Asym Allele Plot Right 148 | if: success() || failure() 149 | run: | 150 | make asym-right test print 151 | 152 | - name: Run Asym Allele Plot Both 153 | if: success() || failure() 154 | run: | 155 | make asym-both test print 156 | -------------------------------------------------------------------------------- /.github/workflows/pylint.yml: -------------------------------------------------------------------------------- 1 | name: Pylint 2 | 3 | on: 4 | push: 5 | 6 | pull_request: 7 | types: [opened, reopened] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | python-version: ["3.10"] 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Set up Python ${{ matrix.python-version }} 18 | uses: actions/setup-python@v3 19 | with: 20 | python-version: ${{ matrix.python-version }} 21 | - name: Install dependencies 22 | run: | 23 | python -m pip install --upgrade pip 24 | pip install pylint 25 | - name: Analysing the code with pylint 26 | run: | 27 | pylint --fail-under=6.2 $(git ls-files '*.py') --rcfile=/home/runner/work/CRISPResso2/CRISPResso2/.github/workflows/.pylintrc 28 | -------------------------------------------------------------------------------- /.github/workflows/pytest.yml: -------------------------------------------------------------------------------- 1 | name: Run Pytest 2 | 3 | on: 4 | push: 5 | 6 | pull_request: 7 | types: [opened, reopened] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | defaults: 13 | run: 14 | shell: bash -l {0} 15 | 16 | strategy: 17 | fail-fast: false 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | 22 | - name: Set up Conda 23 | uses: conda-incubator/setup-miniconda@v3 24 | with: 25 | channels: conda-forge,bioconda,defaults 26 | auto-activate-base: false 27 | activate-environment: test_env 28 | environment-file: .github/envs/test_env.yml 29 | 30 | - name: Install apt dependencies 31 | run: | 32 | sudo apt-get update 33 | sudo apt-get install -y gcc g++ bowtie2 samtools libsys-hostname-long-perl 34 | 35 | - name: Install Pytest 36 | run: | 37 | pip install pytest pytest-cov 38 | 39 | - name: Install CRISPResso 40 | run: | 41 | pip install -e . 42 | 43 | - name: Run Pytest 44 | run: | 45 | pytest tests --cov CRISPResso2 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | .mypy_cache 3 | __pycache__ 4 | *.pyc 5 | *.so 6 | CRISPResso2.egg-info 7 | dist 8 | tests/CRISPResso* -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoCOREResources.pyx: -------------------------------------------------------------------------------- 1 | import cython 2 | import numpy as np 3 | cimport numpy as np 4 | import re 5 | 6 | cdef extern from "stdlib.h": 7 | ctypedef unsigned int size_t 8 | size_t strlen(char* s) 9 | 10 | cdef extern from "Python.h": 11 | ctypedef void PyObject 12 | int _PyBytes_Resize(PyObject **, size_t) 13 | char * PyBytes_AS_STRING(PyObject *) 14 | 15 | 16 | re_find_indels = re.compile("(-*-)") 17 | 18 | class ResultsSlotsDict(): 19 | __slots__ = ( 20 | 'all_insertion_positions', 21 | 'all_insertion_left_positions', 22 | 'insertion_positions', 23 | 'insertion_coordinates', 24 | 'insertion_sizes', 25 | 'insertion_n', 26 | 'all_deletion_positions', 27 | 'all_deletion_coordinates', 28 | 'deletion_positions', 29 | 'deletion_coordinates', 30 | 'deletion_sizes', 31 | 'deletion_n', 32 | 'all_substitution_positions', 33 | 'substitution_positions', 34 | 'all_substitution_values', 35 | 'substitution_values', 36 | 'substitution_n', 37 | 'ref_positions', 38 | 'ref_name', 39 | 'aln_scores', 40 | 'classification', 41 | 'aln_seq', 42 | 'aln_ref', 43 | 'aln_strand', 44 | 'irregular_ends', 45 | 'insertions_outside_window', 46 | 'deletions_outside_window', 47 | 'substitutions_outside_window', 48 | 'total_mods', 49 | 'mods_in_window', 50 | 'mods_outside_window', 51 | ) 52 | 53 | def __init__(self, **kwargs): 54 | for key, value in kwargs.items(): 55 | setattr(self, key, value) 56 | 57 | def __getitem__(self, key): 58 | return getattr(self, key) 59 | 60 | def __setitem__(self, key, value): 61 | setattr(self, key, value) 62 | 63 | @property 64 | def __dict__(self): 65 | return {key: getattr(self, key) for key in self.__slots__ if hasattr(self, key)} 66 | 67 | 68 | @cython.boundscheck(False) 69 | @cython.nonecheck(False) 70 | @cython.wraparound(False) 71 | def find_indels_substitutions(read_seq_al, ref_seq_al, _include_indx): 72 | 73 | #ref_positions holds the indices for which positions map back to the original reference 74 | # for example, 75 | # 1 2 3 4 5 6 7 8 76 | # ref A A T T G G C C 77 | # 78 | # and for a given alignment 79 | # ref A A T T - G G C C 80 | # aln A - T T T G G C C 81 | # 1 2 3 4-4 5 6 7 8 0 and start_insertion == -1: # this is the first index of an insertion 135 | start_insertion = idx - 1 136 | current_insertion_size += 1 137 | 138 | if read_seq_al[idx_c] == '-' and start_deletion == -1: # this is the first part of a deletion 139 | if idx_c - 1 > 0: 140 | start_deletion = ref_positions[idx_c] 141 | else: 142 | start_deletion = 0 143 | elif read_seq_al[idx_c] != '-' and start_deletion != -1: # this is the end of a deletion 144 | end_deletion = ref_positions[idx_c] 145 | all_deletion_positions.extend(range(start_deletion, end_deletion)) 146 | all_deletion_coordinates.append((start_deletion, end_deletion)) 147 | if include_indx_set.intersection(range(start_deletion, end_deletion)): 148 | deletion_positions.extend(range(start_deletion, end_deletion)) 149 | deletion_coordinates.append((start_deletion, end_deletion)) 150 | deletion_sizes.append(end_deletion - start_deletion) 151 | start_deletion = -1 152 | 153 | if start_deletion != -1: 154 | end_deletion = ref_positions[seq_len - 1] 155 | all_deletion_positions.extend(range(start_deletion, end_deletion)) 156 | all_deletion_coordinates.append((start_deletion, end_deletion)) 157 | if include_indx_set.intersection(range(start_deletion, end_deletion)): 158 | deletion_positions.extend(range(start_deletion, end_deletion)) 159 | deletion_coordinates.append((start_deletion, end_deletion)) 160 | deletion_sizes.append(end_deletion - start_deletion) 161 | 162 | cdef size_t substitution_n = len(substitution_positions) 163 | cdef size_t deletion_n = sum(deletion_sizes) 164 | cdef size_t insertion_n = sum(insertion_sizes) 165 | 166 | return ResultsSlotsDict( 167 | all_insertion_positions=all_insertion_positions, 168 | all_insertion_left_positions=all_insertion_left_positions, 169 | insertion_positions=insertion_positions, 170 | insertion_coordinates=insertion_coordinates, 171 | insertion_sizes=insertion_sizes, 172 | insertion_n=insertion_n, 173 | 174 | all_deletion_positions=all_deletion_positions, 175 | all_deletion_coordinates=all_deletion_coordinates, 176 | deletion_positions=deletion_positions, 177 | deletion_coordinates=deletion_coordinates, 178 | deletion_sizes=deletion_sizes, 179 | deletion_n=deletion_n, 180 | 181 | all_substitution_positions=all_substitution_positions, 182 | substitution_positions=substitution_positions, 183 | all_substitution_values=np.array(all_substitution_values), 184 | substitution_values=np.array(substitution_values), 185 | substitution_n=substitution_n, 186 | 187 | ref_positions=ref_positions, 188 | ) 189 | 190 | 191 | @cython.boundscheck(False) 192 | @cython.nonecheck(False) 193 | @cython.wraparound(False) 194 | def find_indels_substitutions_legacy(read_seq_al, ref_seq_al, _include_indx): 195 | 196 | cdef char* sub_seq='' 197 | 198 | cdef int st 199 | cdef int en 200 | 201 | cdef int idx_c 202 | cdef int idx 203 | 204 | #ref_positions holds the indices for which positions map back to the original reference 205 | # for example, 206 | # 1 2 3 4 5 6 7 8 207 | # ref A A T T G G C C 208 | # 209 | # and for a given alignment 210 | # ref A A T T - G G C C 211 | # aln A - T T T G G C C 212 | # 1 2 3 4-4 5 6 7 8 0: 258 | ref_st = ref_positions[st] 259 | ref_en = idx-1 260 | if en < len(ref_positions): 261 | ref_en = ref_positions[en] 262 | all_deletion_positions.extend(range(ref_st,ref_en)) 263 | all_deletion_coordinates.append((ref_st,ref_en)) 264 | inc_del_pos = include_indx_set.intersection(range(ref_st,ref_en)) 265 | if(len(inc_del_pos)>0): 266 | deletion_positions.extend(range(ref_st,ref_en)) 267 | deletion_coordinates.append((ref_st,ref_en)) 268 | deletion_sizes.append(en-st) 269 | 270 | deletion_n = np.sum(deletion_sizes) 271 | 272 | for p in re_find_indels.finditer(ref_seq_al): 273 | st,en=p.span() 274 | #sometimes insertions run off the end of the reference 275 | if st == 0: # if insertion happened before ref 276 | continue 277 | if en == len(ref_seq_al): # if insertion happened after ref 278 | continue 279 | ref_st = ref_positions[st-1] 280 | ref_en = ref_positions[en] 281 | 282 | all_insertion_left_positions.append(ref_st) 283 | all_insertion_positions.append(ref_st) 284 | all_insertion_positions.append(ref_en) 285 | if(ref_st in _include_indx or ref_en in _include_indx): 286 | insertion_coordinates.append((ref_st,ref_en)) 287 | insertion_positions.append(ref_st) 288 | insertion_positions.append(ref_en) 289 | insertion_sizes.append(en-st) 290 | 291 | insertion_n = np.sum(insertion_sizes) 292 | 293 | retDict = { 294 | 'all_insertion_positions':all_insertion_positions, 295 | 'all_insertion_left_positions':all_insertion_left_positions, 296 | 'insertion_positions':insertion_positions, 297 | 'insertion_coordinates':insertion_coordinates, 298 | 'insertion_sizes':insertion_sizes, 299 | 'insertion_n':insertion_n, 300 | 'all_deletion_positions':all_deletion_positions, 301 | 302 | 'deletion_positions':deletion_positions, 303 | 'deletion_coordinates':deletion_coordinates, 304 | 'all_deletion_coordinates':all_deletion_coordinates, 305 | 'deletion_sizes':deletion_sizes, 306 | 'deletion_n':deletion_n, 307 | 308 | 'all_substitution_positions':all_substitution_positions, 309 | 'substitution_positions':substitution_positions, 310 | 'all_substitution_values':np.array(all_substitution_values), 311 | 'substitution_values':np.array(substitution_values), 312 | 'substitution_n':substitution_n, 313 | 314 | 'ref_positions':ref_positions, 315 | } 316 | return retDict 317 | 318 | 319 | def calculate_homology(a, b): 320 | cdef char *al = a 321 | cdef char *bl = b 322 | cdef size_t l = strlen(al) 323 | cdef float score = 0.0 324 | 325 | for i in range(l): 326 | if al[i] == bl[i]: 327 | score+=1 328 | return score/l 329 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/.gitattributes: -------------------------------------------------------------------------------- 1 | *.html text eol=lf 2 | *.md text eol=lf 3 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/.github/workflows/.pylintrc: -------------------------------------------------------------------------------- 1 | [FORMAT] 2 | max-line-length=150 3 | max-args=15 4 | max-locals=40 5 | 6 | [MESSAGES CONTROL] 7 | disable = E0401, W0719 8 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/.github/workflows/pylint.yml: -------------------------------------------------------------------------------- 1 | name: Pylint 2 | 3 | on: 4 | push: 5 | 6 | pull_request: 7 | types: [opened, reopened] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | python-version: ["3.10"] 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Set up Python ${{ matrix.python-version }} 18 | uses: actions/setup-python@v3 19 | with: 20 | python-version: ${{ matrix.python-version }} 21 | - name: Install dependencies 22 | run: | 23 | python -m pip install --upgrade pip 24 | pip install pylint 25 | - name: Analysing the code with pylint 26 | run: | 27 | pylint --fail-under=9 $(git ls-files '*.py') --rcfile=/home/runner/work/CRISPRessoReports/CRISPRessoReports/.github/workflows/.pylintrc 28 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/README.md: -------------------------------------------------------------------------------- 1 | # CRISPRessoReports 2 | 3 | This repo holds the shared reports code and HTML templates that are used by the CLI and web projects. 4 | 5 | Take care when committing into these files as not to mix unrelated git histories. 6 | 7 | ## How do I work with this repo? 8 | 9 | Step 1 only needs to be done once per cloned repo, the other steps will need to be done more frequently. 10 | 11 | 1. Add the remote to this repo to the "parent" repo (i.e. `CRISPResso2` or `C2Web`). **You should only have to do this once.** 12 | 13 | ``` shell 14 | git remote add reports https://github.com/edilytics/CRISPRessoReports.git 15 | ``` 16 | 17 | *Note:* you can change the `reports` above to whatever you would like, just don't forget to replace `reports` with it in the other steps. 18 | 19 | 2. In the parent repo, fetch the latest changes from `CRISPRessoReports`. 20 | 21 | ``` shell 22 | git fetch reports 23 | ``` 24 | 25 | 3. Checkout a `CRISPRessoReports` branch. 26 | 27 | ``` shell 28 | git checkout -b master-reports reports/master 29 | ``` 30 | 31 | *Note:* you can obviously change the names of these branches (or select a branch other than `master`). I would recommend naming all branches from `CRISPRessoReports` with the same prefix or suffix (i.e. `*-reports`) because it can get confusing to keep all of the branches straight... 32 | 33 | 4. Read `CRISPRessoReports` into the parent repo as a subtree. This is when the code in `CRISPRessoReports` will finally be added to the parent repo. 34 | 35 | **Very important**, switch to the branch in the parent repo where you want the code to be added! For example: 36 | 37 | ``` shell 38 | git checkout 39 | ``` 40 | 41 | Then, you will read the commits into wherever `CRISPRessoReports` are stored for that repo. **Note:** you should only have to do this if `CRISPRessoReports` has not been added to the parent repo, if it is already there, do not repeat this step. 42 | 43 | ``` shell 44 | git read-tree --prefix=CRISPResso2/CRISPRessoReports -u master-reports 45 | ``` 46 | 47 | Run `git status` and you should see the files added! 48 | 49 | 5. Stage and commit your files as you normally would. 50 | 51 | ### How do I pull commits that are in `CRISPRessoReports` into the parent repo? 52 | 53 | 1. In the parent repo, switch to the `-reports` branch. 54 | 55 | ``` shell 56 | git checkout -reports 57 | ``` 58 | 59 | 2. Pull the changes from `CRISPRessoReports`. 60 | 61 | ``` shell 62 | git pull 63 | ``` 64 | 65 | You should see the updates that you are looking for. 66 | 67 | 3. **Very important**, switch back to whichever branch you are working on in the parent repo. 68 | 69 | ``` shell 70 | git checkout 71 | ``` 72 | 73 | 4. Merge the changes in and resolve any merge conflicts. 74 | 75 | ``` shell 76 | git merge --squash -Xsubtree="CRISPResso2/CRISPRessoReports" --no-commit --allow-unrelated-histories -reports 77 | ``` 78 | 79 | *Note:* You may need to change the value of the `-Xsubtree` parameter to match where `CRISPRessoReports` is located in the parent repo. 80 | 81 | 5. Commit your changes and resolve merge conflicts. 82 | 83 | Also, note that the default commit message may have a summary of all commits, please shorten it to be descriptive of the most recent changes. 84 | 85 | ### How do I push commits that are in my parent repo's `CRISPRessoReports` into the shared `CRISPRessoReports` repo? 86 | 87 | 1. In the parent repo, switch to (or create) the branch on `CRISPRessoReports` that will have the changes you push. 88 | 89 | If you are creating a new branch based off of `CRISPRessoReports` master, run this to switch to the reports master branch: 90 | 91 | ``` shell 92 | git checkout reports/master 93 | ``` 94 | 95 | Then, run to actually create (and switch to) the branch that you will be working with: 96 | 97 | ``` shell 98 | git checkout -b -reports 99 | ``` 100 | 101 | Or if you would like to push to an existing branch on `CRISPRessoReports`, run this: 102 | 103 | ``` shell 104 | git checkout -reports 105 | ``` 106 | 107 | 2. Merge the changes in and resove any merge conflicts. 108 | 109 | ``` shell 110 | git merge --squash -Xsubtree="CRISPResso2/CRISPRessoReports" --no-commit --allow-unrelated-histories 111 | ``` 112 | 113 | *Note:* `` is the branch of the parent repo that contains the changes inside the `CRISPRessoReports` sub-directory. 114 | 115 | 3. Push to `CRISPRessoReports`. 116 | 117 | ``` shell 118 | git push 119 | ``` 120 | 121 | 4. Switch back to your branch on `CRISPResso` or `C2Web`. 122 | 123 | ``` shell 124 | git checkout 125 | ``` 126 | 127 | ### I am working on a feature that requires changing `CRISPRessoReports`, what do I do? 128 | 129 | If a feature that you are working on requires changes to CRISPRessoReports, you will need to perform a few steps to get setup. 130 | 131 | 1. Create a feature branch in the parent repo, based on the parent repo master. 132 | 133 | ``` shell 134 | git checkout -b origin/master 135 | ``` 136 | 137 | 2. Create a feature branch on `CRISPRessoReports`. 138 | 139 | Checkout your local `CRISPRessoReports` master branch. 140 | 141 | ``` shell 142 | git checkout master-reports 143 | ``` 144 | 145 | Pull in the latest changes. 146 | 147 | ``` shell 148 | git pull 149 | ``` 150 | 151 | Create the `CRISPRessoReports` feature branch based on `reports/master`. 152 | 153 | ``` shell 154 | git checkout -b -reports reports/master 155 | ``` 156 | 157 | *Note:* if your branch is named `cool-feature` in the parent repo, then follow the convention of naming the corresponding `CRISPRessoReports` branch `cool-feature-reports`. 158 | 159 | If you run `git status` at this point you should see any directories in the parent repo as untracked files, this is normal and expected. 160 | 161 | 3. Switch back to the feature-branch in the parent repo, and develop your changes. 162 | 163 | ``` shell 164 | git checkout 165 | ``` 166 | 167 | *Note:* you can mingle your changes in `CRISPRessoReports` and the parent repo in the same commits. 168 | 169 | 4. Merge and push your changes up to `CRISPRessoReports`. 170 | 171 | Switch to the `-reports` branch. 172 | 173 | ``` shell 174 | git checkout -reports 175 | ``` 176 | 177 | Merge the changes from the parent repo into the `-reports` branch. 178 | 179 | ``` shell 180 | git merge --squash -Xsubtree="CRISPResso2/CRISPRessoReports" --no-commit --allow-unrelated-histories 181 | ``` 182 | 183 | # FAQ 184 | 185 | ## There are lots of merge conflicts, how do I just accept all of the incoming changes? 186 | 187 | If you want to blindly accept all of the incoming changes, you can add the parameter `-Xtheirs` to the `git merge...` command and anything that was a merge conflict before, should now be overwritten by the incoming change. 188 | 189 | ## I tired of typing `git merge --squash ...`, what can I do?! 190 | 191 | Typing out the `git merge...` command is long and is a big pain. Here are some shortcuts to add to your `.git/config` file in order to make this easier to type. 192 | 193 | ``` git-config 194 | [alias] 195 | # merge in branch and resolve merge conflicts 196 | m = "!f() { git merge --squash -Xsubtree='CRISPResso2/CRISPRessoReports' --no-commit --allow-unrelated-histories $1; }; f" 197 | # merge in branch and accept all of the incoming changes 198 | mt = "!f() { git merge --squash -Xtheirs -Xsubtree='CRISPResso2/CRISPRessoReports' --no-commit --allow-unrelated-histories $1; }; f" 199 | ``` 200 | 201 | Now you can just run `git m ` to merge `` into your current branch. Or run `git mt ` to accept all of the incoming changes. 202 | 203 | # Sources and helpful links 204 | 205 | - This method was heavily based off of what was described in [this blog post](http://johnatten.com/2013/03/16/git-subtree-merge-the-quick-version/) 206 | - If you want to know more about git merging, the manual is [very helpful](https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging) 207 | - If you messed up (merging the wrong branch), you can undo it using `git reset --hard `. **Beware:** this can cause you to lose work, so use with care. [Learn more here](https://stackoverflow.com/a/8888015/1947159). 208 | - If you need to rewrite git history, try using [git-filter-repo](https://github.com/newren/git-filter-repo) 209 | - After rewriting git history (from a mirror repo), if you can't push to GitHub, [try this](https://stackoverflow.com/a/34266401/1947159) 210 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/CRISPResso2/CRISPRessoReports/__init__.py -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/jinja_partials.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This file is derived from https://github.com/mikeckennedy/jinja_partials and is subject to the following license: 3 | 4 | MIT License 5 | 6 | Copyright (c) 2021 Michael Kennedy 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | ''' 26 | 27 | from functools import partial 28 | 29 | from markupsafe import Markup 30 | 31 | try: 32 | import flask 33 | except ImportError: 34 | flask = None 35 | 36 | 37 | def render_partial(template_name, renderer=None, markup=True, **data): 38 | """ 39 | Renders a partial template and returns the result. If `markup` is True, the result is wrapped in a `Markup` object. 40 | """ 41 | if renderer is None: 42 | if flask is None: 43 | raise PartialsException('No renderer specified') 44 | renderer = flask.render_template 45 | 46 | if markup: 47 | return Markup(renderer(template_name, **data)) 48 | 49 | return renderer(template_name, **data) 50 | 51 | 52 | def generate_render_partial(renderer, markup=True): 53 | """ 54 | Returns a partial function that renders a template using the specified renderer. 55 | """ 56 | return partial(render_partial, renderer=renderer, markup=markup) 57 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/CRISPResso_justcup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/CRISPResso2/CRISPRessoReports/templates/CRISPResso_justcup.png -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/batchReport.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block head %} 3 | {% if C2PRO_INSTALLED %} 4 | 5 | {% endif %} 6 | 46 | 47 | {% endblock %} 48 | 49 | {% block content %} 50 |
51 |
52 |
53 | 54 |
55 |
56 | 57 | {% if run_names|length > 0 %} 58 |
59 |
60 |
{{report_name}}
61 |
62 |
63 |
64 | {% for run_name in run_names %} 65 | {{run_name}} 66 | {% endfor %} 67 |
68 |
69 |
70 | {% endif %} 71 | 72 | {{render_partial('shared/partials/failed_runs.html', failed_runs=failed_runs, failed_runs_desc=failed_runs_desc)}} 73 | 74 | {% if window_nuc_pct_quilts|length > 0 %} 75 |
76 |
77 |
Nucleotide percentages around guides
78 |
79 |
80 | {% for plot_name in window_nuc_pct_quilts %} 81 |
{{report_data['titles'][plot_name]}}
82 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 83 | {% endfor %} 84 |
85 |
86 | {% endif %} 87 | 88 | {% if nuc_pct_quilts|length > 0 %} 89 |
90 |
91 |
Nucleotide percentages in the entire amplicon
92 |
93 |
94 | {% for plot_name in nuc_pct_quilts %} 95 |
{{report_data['titles'][plot_name] if plot_name in report_data['titles'] else ''}}
96 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 97 | {% endfor %} 98 |
99 |
100 | {% endif %} 101 | 102 | {% if window_nuc_conv_plots|length > 0 %} 103 |
104 |
105 |
Conversion of target bases around guides
106 |
107 |
108 | {% for plot_name in window_nuc_conv_plots %} 109 |
{{report_data['titles'][plot_name] if plot_name in report_data['titles'] else ''}}
110 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 111 | {% endfor %} 112 |
113 |
114 | {% endif %} 115 | 116 | {% if nuc_conv_plots|length > 0 %} 117 |
118 |
119 |
Conversion of target bases in the entire amplicon
120 |
121 |
122 | {% for plot_name in nuc_conv_plots %} 123 |
{{report_data['titles'][plot_name] if plot_name in report_data['titles'] else ''}}
124 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 125 | {% endfor %} 126 |
127 |
128 | {% endif %} 129 | 130 | {% if report_data['names']|length > 0 %} 131 | {% for plot_name in report_data['names'] %} 132 |
133 |
134 |
{{report_data['titles'][plot_name] if plot_name in report_data['titles'] else ''}}
135 |
136 |
137 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 138 |
139 |
140 | {% endfor %} 141 | {% endif %} 142 | 143 | {% if allele_modification_heatmap_plot_names|length > 0 %} 144 | {% for heatmap_plot_name in allele_modification_heatmap_plot_names %} 145 | {% set line_plot_name = allele_modification_line_plot_names[loop.index - 1] %} 146 | {% set modification_type = heatmap_plot_name.split('_')[3] %} 147 |
148 |
149 |
{{allele_modification_heatmap_plot_titles[heatmap_plot_name]}}
150 | 159 |
160 |
161 |
162 |
163 | {{allele_modification_heatmap_plot_htmls[heatmap_plot_name] | safe}} 164 | 165 | {% for (data_label, data_path) in allele_modification_heatmap_plot_datas[heatmap_plot_name] %} 166 |

Data: {{data_label}}

167 | {% endfor %} 168 |
169 |
170 | {{allele_modification_line_plot_htmls[line_plot_name] | safe}} 171 | 172 | {% for (data_label, data_path) in allele_modification_line_plot_datas[line_plot_name] %} 173 |

Data: {{data_label}}

174 | {% endfor %} 175 |
176 |
177 |
178 |
179 | 194 | {% endfor %} 195 | {% endif %} 196 | 197 |
198 | 199 |
200 | 201 | 202 | {{render_partial('shared/partials/report_footer_buttons.html', report_zip_filename=report_zip_filename, report_path=report_path)}} 203 | 204 |
205 |
206 |
207 | {% endblock %} 208 | 209 | {% block foot %} 210 | {% if C2PRO_INSTALLED %} 211 | 212 | {{ render_partial('partials/batch_d3.html', nucleotide_quilt_slugs=(window_nuc_pct_quilts + nuc_pct_quilts))}} 213 | {% endif %} 214 | {% endblock %} 215 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/CRISPResso2/CRISPRessoReports/templates/favicon.ico -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CRISPResso2 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 56 | 57 | 58 | 60 | 61 | 62 | 63 | {% if is_web %} 64 | 65 | 66 | 67 | 68 | {% else %} 69 | 70 | {% endif %} 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | {% block head %}{% endblock %} 81 | 82 | 83 | 84 | 85 | {% if is_web %} 86 |
87 | {{ self.help_block() }} 88 |
89 | 90 | {% with messages = get_flashed_messages(with_categories=true) %} 91 | {% if messages %} 92 | {% for category, message in messages %} 93 | {% if category == "error" %} 94 | 98 | {% else %} 99 | 103 | {% endif %} 104 | {% endfor %} 105 | {% endif %} 106 | {% endwith %} 107 | {% endif %} 108 | 109 | {# if default user (normal crispresso mode) #} 110 | {% if not is_web or is_default_user %} 111 |
112 |
113 |
114 | {% if is_web %} 115 |
116 | {% else %} 117 |
118 | {% endif %} 119 |
120 |
121 |

CRISPResso2

122 |

Analysis of genome editing outcomes from deep sequencing data

123 |
124 |
125 |
126 |
127 | 128 | 129 | {% else %} 130 | {# if doing user sessions #} 131 | 173 |
174 | {% endif %} 175 | 176 |
177 |
178 |
179 |
180 | {% block help_block %} {% endblock %} 181 |
182 |
183 |
184 |
185 | 186 | {% block content %}{% endblock %} 187 | 188 | {% if not is_web or is_default_user %} 189 |
190 |
191 | 207 |
208 |
209 | {% else %} 210 |
211 |
212 | 215 |
216 |
217 | {% endif %} 218 |
219 | {% block foot %}{% endblock %} 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/multiReport.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block head %} 3 | 4 | 5 | 45 | 46 | {% endblock %} 47 | 48 | {% block content %} 49 |
50 |
51 |
52 | 53 |
54 |
55 | 56 | {% if run_names|length > 0 %} 57 |
58 |
59 |
{{report_name}}
60 |
61 |
62 |
63 | {% for run_name in run_names %} 64 | {{run_name}} 65 | {% endfor %} 66 |
67 |
68 |
69 | {% endif %} 70 | 71 | {{render_partial('shared/partials/failed_runs.html', failed_runs=failed_runs, failed_runs_desc=failed_runs_desc)}} 72 | 73 | {% if window_nuc_pct_quilts|length > 0 %} 74 |
75 |
76 |
Nucleotide percentages around guides
77 |
78 |
79 | {% for plot_name in window_nuc_pct_quilts %} 80 |
{{report_data['titles'][plot_name]}}
81 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 82 | {% endfor %} 83 |
84 |
85 | {% endif %} 86 | 87 | {% if nuc_pct_quilts|length > 0 %} 88 |
89 |
90 |
Nucleotide percentages in the entire amplicon
91 |
92 |
93 | {% for plot_name in nuc_pct_quilts %} 94 |
{{report_data['titles'][plot_name]}}
95 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 96 | {% endfor %} 97 |
98 |
99 | {% endif %} 100 | 101 | {% if window_nuc_conv_plots|length > 0 %} 102 |
103 |
104 |
Conversion of target bases around guides
105 |
106 |
107 | {% for plot_name in window_nuc_conv_plots %} 108 |
{{report_data['titles'][plot_name]}}
109 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 110 | {% endfor %} 111 |
112 |
113 | {% endif %} 114 | 115 | {% if nuc_conv_plots|length > 0 %} 116 |
117 |
118 |
Conversion of target bases in the entire amplicon
119 |
120 |
121 | {% for plot_name in nuc_conv_plots %} 122 |
{{report_data['titles'][plot_name]}}
123 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 124 | {% endfor %} 125 |
126 |
127 | {% endif %} 128 | 129 | {% if report_data['names']|length > 0 %} 130 | {% for plot_name in report_data['names'] %} 131 |
132 |
133 |
{{report_data['titles'][plot_name]}}
134 |
135 |
136 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 137 |
138 |
139 | {% endfor %} 140 | {% endif %} 141 | 142 | {% if compact_plots_to_show|length > 0 %} 143 |
144 |
145 |
Summary Plots
146 |
147 |
148 |
149 | {% for compact_plot in compact_plots_to_show %} 150 | 151 | {% endfor %} 152 |
153 |
154 |
155 | {% endif %} 156 | 157 | {{render_partial('shared/partials/report_footer_buttons.html', report_zip_filename=report_zip_filename, report_path=report_path)}} 158 | 159 |
{# jumbotron_content #} 160 |
{# jumbrotron #} 161 | 162 |
{# column #} 163 | 164 |
165 |
166 | {% endblock %} 167 | 168 | {% block foot %} 169 | {% endblock %} 170 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/pooledReport.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block head %} 3 | 43 | 44 | {% if C2PRO_INSTALLED %} 45 | 46 | {% endif %} 47 | 48 | {% endblock %} 49 | 50 | {% block content %} 51 |
52 |
53 |
54 | 55 |
56 |
57 | 58 | {% if run_names|length > 0 %} 59 |
60 |
61 |
{{report_name}}
62 |
63 |
64 |
65 | {% for region_name in run_names %} 66 | {{region_name}} 67 | {% endfor %} 68 |
69 |
70 |
71 | {% endif %} 72 | 73 | {{render_partial('shared/partials/failed_runs.html', failed_runs=failed_runs, failed_runs_desc=failed_runs_desc)}} 74 | 75 | {% if report_data['names']|length > 0 %} 76 | {% for plot_name in report_data['names'] %} 77 |
78 |
79 |
{{report_data['titles'][plot_name]}}
80 |
81 |
82 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 83 |
84 |
85 | {% endfor %} 86 | {% endif %} 87 | 88 | {{render_partial('shared/partials/report_footer_buttons.html', report_zip_filename=report_zip_filename, report_path=report_path)}} 89 | 90 |
{# jumbotron_content #} 91 |
{# jumbrotron #} 92 | 93 |
{# column #} 94 | 95 |
96 |
97 | {% endblock %} 98 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/shared/partials/failed_runs.html: -------------------------------------------------------------------------------- 1 | {% if failed_runs|length > 0 %} 2 |
3 |
4 | 5 |
Failed Runs
6 | 9 |
10 | 11 |
12 |
13 | {% for failed_run in failed_runs %} 14 | {# Toggle the description visibility on click #} 15 | 17 | {{failed_run}} 18 | 19 | {# Initially hide the description and add a light background with dark text for readability #} 20 | 23 | {% endfor %} 24 |
25 |
26 |
27 | 28 | 65 | {% endif %} 66 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/shared/partials/fig_reports.html: -------------------------------------------------------------------------------- 1 |
2 | {# Set the width based on the plot #} 3 | {%- if fig_name in ['plot_1a', 'plot_1b', 'plot_1c', 'plot_1d', 'plot_3a', 'plot_4a', 'plot_4b', 'plot_4c', 'plot_4e', 'plot_4f', 'plot_5a', 'plot_7', 'plot_8', 'plot_8a', 'plot_11c'] -%} 4 | {% set width = '40%' %} 5 | {%- elif fig_name in ['plot_10b', 'plot_10c'] -%} 6 | {% set width = '35%' %} 7 | {%- elif fig_name in ['plot_10a'] -%} 8 | {% set width = '70%' %} 9 | {%- else -%} 10 | {% set width = '100%' %} 11 | {%- endif -%} 12 | 13 | {%- if amplicon_name is defined -%} 14 | {%- if 'htmls' in report_data['figures'] and fig_name in report_data['figures']['htmls'][amplicon_name] -%} 15 | {{report_data['figures']['htmls'][amplicon_name][fig_name]|safe}} 16 | {%- elif fig_name in report_data['figures']['locs'][amplicon_name] -%} 17 | 18 | {% endif -%} 19 | 20 | {%- for (data_label,data_path) in report_data['figures']['datas'][amplicon_name][fig_name] %} 21 |

Data: {{data_label}}

22 | {%- endfor -%} 23 | {%- else %} 24 | {%- if 'htmls' in report_data['figures'] and fig_name in report_data['figures']['htmls'] -%} 25 | {{report_data['figures']['htmls'][fig_name]|safe}} 26 | {%- elif fig_name in report_data['figures']['locs'] -%} 27 | 28 | {% endif -%} 29 | {% if fig_name in report_data['figures']['captions'] and fig_name in report_data['figures']['datas'] %} 30 | 31 | {%- for (data_label,data_path) in report_data['figures']['datas'][fig_name] %} 32 |

Data: {{data_label}}

33 | {%- endfor -%} 34 | {%- endif %} 35 | {%- endif %} 36 |
37 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/shared/partials/fig_summaries.html: -------------------------------------------------------------------------------- 1 |
2 | {% if 'htmls' in report_data and plot_name in report_data['htmls']%} 3 | {{report_data['htmls'][plot_name]|safe}} 4 | {% else %} 5 | {% if plot_name in ['Nucleotide_conversion_map', 'Nucleotide_percentage_quilt'] %} 6 | 7 | {% else %} 8 | 9 | {% endif %} 10 | {% endif %} 11 | 12 | {% for (data_label,data_path) in report_data['datas'][plot_name] %} 13 |

Data: {{data_label}}

14 | {% endfor %} 15 |
16 |
17 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/shared/partials/guardrail_warnings.html: -------------------------------------------------------------------------------- 1 | {% if 'guardrails_htmls' in report_data['run_data']['results'] and report_data['run_data']['results']['guardrails_htmls']|length > 0 %} 2 | {% for message in report_data['run_data']['results']['guardrails_htmls'] %} 3 | {{message | safe}} 4 | {% endfor %} 5 | {% endif %} -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/shared/partials/log_params.html: -------------------------------------------------------------------------------- 1 |
2 |

CRISPResso version: {{report_data['run_data']['running_info']['version']}}

3 |

Run completed: {{report_data['run_data']['running_info']['end_time_string']}}

4 |

Amplicon sequence:

{{report_data['run_data']['running_info']['args']['amplicon_seq']}}

5 | {% if report_data['run_data']['running_info']['args']['guide_seq'] != '' %} 6 |

Guide sequence:

{{report_data['run_data']['running_info']['args']['guide_seq']}}

7 | {% endif %} 8 |

Command used:

{{report_data['run_data']['running_info']['command_used']}}

9 |

Parameters:

{{report_data['run_data']['running_info']['args_string']}}

10 | {% if is_web and 'metadata' in report_data and report_data['metadata'].keys() %} 11 |

Metadata:

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {% for key in report_data['metadata'].keys() %} 21 | 22 | 23 | 24 | 25 | {% endfor %} 26 | 27 |
KeyValue
{{key}}{{report_data['metadata'][key]}}
28 | {% endif %} 29 |

Running log

30 |
31 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/shared/partials/report_footer_buttons.html: -------------------------------------------------------------------------------- 1 |
2 | {% if is_web -%} 3 | {%- if report_zip_filename -%} 4 | Download report 5 | {% endif %} 6 | Link to report 7 | {% endif %} 8 | 9 |
10 | -------------------------------------------------------------------------------- /CRISPResso2/CRISPRessoReports/templates/wgsReport.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% block head %} 3 | 4 | 44 | 45 | {% endblock %} 46 | 47 | {% block content %} 48 |
49 |
50 |
51 | 52 |
53 |
54 | 55 |
56 |
57 |
{{report_name}}
58 |
59 |
60 |
61 | {% for region_name in run_names %} 62 | {{region_name}} 63 | {% endfor %} 64 |
65 |
66 |
67 | 68 | {{render_partial('shared/partials/failed_runs.html', failed_runs=failed_runs, failed_runs_desc=failed_runs_desc)}} 69 | 70 | {% if report_data['names']|length > 0 %} 71 | {% for plot_name in report_data['names'] %} 72 |
73 |
74 |
{{report_data['titles'][plot_name]}}
75 |
76 |
77 | {{ render_partial('shared/partials/fig_summaries.html', report_data=report_data, plot_name=plot_name) }} 78 |
79 |
80 | {% endfor %} 81 | {% endif %} 82 | 83 | {{render_partial('shared/partials/report_footer_buttons.html', report_zip_filename=report_zip_filename, report_path=report_path)}} 84 |
{# jumbotron_content #} 85 |
{# jumbrotron #} 86 | 87 |
{# column #} 88 | 89 |
90 |
91 | {% endblock %} 92 | 93 | {% block foot %} 94 | {% endblock %} 95 | -------------------------------------------------------------------------------- /CRISPResso2/EDNAFULL: -------------------------------------------------------------------------------- 1 | # 2 | # This matrix was created by Todd Lowe 12/10/92 3 | # 4 | # Uses ambiguous nucleotide codes, probabilities rounded to 5 | # nearest integer 6 | # 7 | # Lowest score = -4, Highest score = 5 8 | # 9 | A T G C S W R Y K M B V H D N U 10 | A 5 -4 -4 -4 -4 1 1 -4 -4 1 -4 -1 -1 -1 -2 -4 11 | T -4 5 -4 -4 -4 1 -4 1 1 -4 -1 -4 -1 -1 -2 5 12 | G -4 -4 5 -4 1 -4 1 -4 1 -4 -1 -1 -4 -1 -2 -4 13 | C -4 -4 -4 5 1 -4 -4 1 -4 1 -1 -1 -1 -4 -2 -4 14 | S -4 -4 1 1 -1 -4 -2 -2 -2 -2 -1 -1 -3 -3 -1 -4 15 | W 1 1 -4 -4 -4 -1 -2 -2 -2 -2 -3 -3 -1 -1 -1 1 16 | R 1 -4 1 -4 -2 -2 -1 -4 -2 -2 -3 -1 -3 -1 -1 -4 17 | Y -4 1 -4 1 -2 -2 -4 -1 -2 -2 -1 -3 -1 -3 -1 1 18 | K -4 1 1 -4 -2 -2 -2 -2 -1 -4 -1 -3 -3 -1 -1 1 19 | M 1 -4 -4 1 -2 -2 -2 -2 -4 -1 -3 -1 -1 -3 -1 -4 20 | B -4 -1 -1 -1 -1 -3 -3 -1 -1 -3 -1 -2 -2 -2 -1 -1 21 | V -1 -4 -1 -1 -1 -3 -1 -3 -3 -1 -2 -1 -2 -2 -1 -4 22 | H -1 -1 -4 -1 -3 -1 -3 -1 -3 -1 -2 -2 -1 -2 -1 -1 23 | D -1 -1 -1 -4 -3 -1 -1 -3 -1 -3 -2 -2 -2 -1 -1 -1 24 | N -2 -2 -2 -2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -2 25 | U -4 5 -4 -4 -4 1 -4 1 1 -4 -1 -4 -1 -1 -2 5 26 | -------------------------------------------------------------------------------- /CRISPResso2/README: -------------------------------------------------------------------------------- 1 | run setup.sh to compile cython code 2 | after running setup.sh, it puts that .so file in a CRISPResso folder.. move that .so file to this folder and delete the new CRISPResso file 3 | -------------------------------------------------------------------------------- /CRISPResso2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/CRISPResso2/__init__.py -------------------------------------------------------------------------------- /CRISPResso2/default_style.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors": { 3 | "Substitution": "#0000FF", 4 | "Insertion": "#008000", 5 | "Deletion": "#FF0000", 6 | "A": "#7FC97F", 7 | "T": "#BEAED4", 8 | "C": "#FDC086", 9 | "G": "#FFFF99", 10 | "N": "#C8C8C8", 11 | "-": "#C1C1C1" 12 | } 13 | } -------------------------------------------------------------------------------- /CRISPResso2/setupLocal.py: -------------------------------------------------------------------------------- 1 | ''' 2 | CRISPResso2 - Kendell Clement and Luca Pinello 2018 3 | Software pipeline for the analysis of genome editing outcomes from deep sequencing data 4 | (c) 2018 The General Hospital Corporation. All Rights Reserved. 5 | ''' 6 | from distutils.core import setup 7 | from Cython.Build import cythonize 8 | import numpy 9 | 10 | setup( 11 | ext_modules=cythonize("*.pyx"), 12 | include_dirs=[numpy.get_include()] 13 | ) 14 | -------------------------------------------------------------------------------- /CRISPResso2/setupLocal.sh: -------------------------------------------------------------------------------- 1 | python setupLocal.py build_ext --inplace 2 | mv CRISPResso2/*.so . 3 | rmdir CRISPResso2/ 4 | -------------------------------------------------------------------------------- /CRISPResso2_router.py: -------------------------------------------------------------------------------- 1 | #/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | ''' 4 | CRISPResso2 - Kendell Clement and Luca Pinello 2018 5 | Software pipeline for the analysis of genome editing outcomes from deep sequencing data 6 | (c) 2018 The General Hospital Corporation. All Rights Reserved. 7 | ''' 8 | 9 | import os 10 | import subprocess as sb 11 | import sys 12 | usage = '\n- CRISPResso2 Docker Container -\n\t- Possible commands: \n\t CRISPResso\n\t CRISPRessoBatch\n\t CRISPRessoPooled\n\t CRISPRessoWGS\n\t CRISPRessoCompare\n\t CRISPRessoPooledWGSCompare\n\t CRISPRessoAggregate\n\t License\n\t- this docker version should be run like this:\n\tdocker run -v ${PWD}:/DATA -w /DATA -i pinellolab/crispresso2 CRISPResso -r1 fastq1.fq -a AAAATTT \n' 13 | 14 | if len(sys.argv)==1: 15 | 16 | print(usage) 17 | sys.exit(1) 18 | 19 | if sys.argv[1]=='CRISPResso': 20 | sb.call(["CRISPResso"]+ sys.argv[2:]) 21 | elif sys.argv[1]=='CRISPRessoBatch': 22 | sb.call(["CRISPRessoBatch"]+ sys.argv[2:]) 23 | elif sys.argv[1]=='CRISPRessoCompare': 24 | sb.call(["CRISPRessoCompare"]+ sys.argv[2:]) 25 | elif sys.argv[1]=='CRISPRessoPooled': 26 | sb.call(["CRISPRessoPooled"]+ sys.argv[2:]) 27 | elif sys.argv[1]=='CRISPRessoWGS': 28 | sb.call(["CRISPRessoWGS"]+ sys.argv[2:]) 29 | elif sys.argv[1]=='CRISPRessoPooledWGSCompare': 30 | sb.call(["CRISPRessoPooledWGSCompare"]+ sys.argv[2:]) 31 | elif sys.argv[1]=='CRISPRessoAggregate': 32 | sb.call(["CRISPRessoAggregate"]+ sys.argv[2:]) 33 | elif sys.argv[1]=='License': 34 | with open("LICENSE.txt", 'r') as fin: 35 | print(fin.read()) 36 | else: 37 | print(usage) 38 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ############################################################ 2 | # Dockerfile to build CRISPResso2 3 | ############################################################ 4 | 5 | #FROM continuumio/miniconda3 6 | FROM mambaorg/micromamba:0.13.1 7 | 8 | # File Author / Maintainer 9 | MAINTAINER Kendell Clement 10 | RUN apt-get update && apt-get install gcc g++ bowtie2 samtools libsys-hostname-long-perl \ 11 | -y --no-install-recommends \ 12 | && apt-get clean \ 13 | && apt-get autoremove -y \ 14 | && rm -rf /var/lib/apt/lists/* \ 15 | && rm -rf /usr/share/man/* \ 16 | && rm -rf /usr/share/doc/* \ 17 | && conda install -c defaults -c conda-forge -c bioconda -y -n base --debug fastp numpy cython jinja2 tbb=2020.2 pyparsing=2.3.1 scipy matplotlib-base pandas plotly\ 18 | && conda clean --all --yes 19 | 20 | #install ms fonts 21 | RUN echo "deb http://httpredir.debian.org/debian buster main contrib" > /etc/apt/sources.list \ 22 | && echo "deb http://security.debian.org/ buster/updates main contrib" >> /etc/apt/sources.list \ 23 | && echo "ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true" | debconf-set-selections \ 24 | && apt-get update \ 25 | && apt-get install -y ttf-mscorefonts-installer \ 26 | && apt-get clean \ 27 | && apt-get autoremove -y \ 28 | && rm -rf /var/lib/apt/lists/* \ 29 | && rm -rf /usr/share/man/* \ 30 | && rm -rf /usr/share/doc/* \ 31 | && rm -rf /usr/share/zoneinfo 32 | 33 | # install crispresso 34 | COPY . /CRISPResso2 35 | WORKDIR /CRISPResso2 36 | RUN python setup.py install \ 37 | && CRISPResso -h \ 38 | && CRISPRessoBatch -h \ 39 | && CRISPRessoPooled -h \ 40 | && CRISPRessoWGS -h \ 41 | && CRISPRessoCompare -h 42 | 43 | 44 | ENTRYPOINT ["python","/CRISPResso2/CRISPResso2_router.py"] -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | CRISPResso2 is made available for free to academic researchers under this limited license for non-commercial use. 2 | 3 | IMPORTANT: If you plan to use the CRISPResso2 for-profit, you will need to purchase a license. Please contact licensing@edilytics.com for more information. 4 | 5 | CRISPResso2 6 | END USER LICENSE AGREEMENT 7 | 8 | BEFORE PROCEEDING, PLEASE READ THE END USER LICENSE AGREEMENT BELOW. 9 | 10 | BY USING THIS SOFTWARE TOOL YOU ATTEST TO (I) BEING AN ACADEMIC RESEARCHER, (II) USING IT SOLELY FOR RESEARCH PURPOSES AND (III) YOUR ACCEPTANCE OF THE END USER LICENSE AGREEMENT. 11 | 12 | 1. General. 13 | As used herein, the term “you” or “your” means any individual or entity accessing this site or using the software tool “CRISPResso2” (the “Software Tool”) pursuant to this End-User License Agreement (“EULA”). 14 | 15 | 2. License to Use. 16 | The Software Tool is free for your use subject to the terms and conditions set forth below. The General Hospital Corporation, dba Massachusetts General Hospital (“MGH”) reserves the right to change, from time to time and at its sole discretion, this EULA. Your continued use of the Software Tool after any such modification constitutes your agreement and acceptance of such changes. 17 | 18 | MGH owns all right, title and interest in the Software Tool. MGH grants to you, the “Licensee,” a royalty-free, non-exclusive, non-transferable, revocable license to use the Software Tool for non-commercial research or academic purposes only; it is NOT made available here as a free tool or download for any commercial or clinical use. You may not copy or distribute the Software Tool in any form. This license is limited to the individual that accesses the Software Tool. No right to sublicense or assign this EULA is granted herein. 19 | 20 | The Software Tool optionally makes calls to unmodified versions of 21 | fastp software, which is covered under its own license (MIT). 22 | 23 | By using this Software Tool, you agree to allow MGH the right to collect data and statistics (i) on system usage patterns and (ii) to improve this Software Tool. 24 | 25 | 3. Limitations on Use. 26 | THE SOFTWARE TOOL HAS NOT BEEN REGISTERED OR APPROVED BY THE U.S. FOOD AND DRUG AGENCY, OR ANY OTHER GOVERNMENTAL AGENCY. THE SOFTWARE TOOL MAY BE USED ONLY AS A REFERENCE TOOL AND FOR CLINICAL EDUCATION, SIMILAR TO THE USE OF A TEXTBOOK OR A JOURNAL ARTICLE. THE SOFTWARE TOOL SHALL NOT BE USED AS A DIAGNOSTIC DECISION MAKING SYSTEM AND MUST NOT BE USED TO MAKE A CLINICAL DIAGNOSIS OR REPLACE OR OVERRULE A LICENSED HEALTH CARE PROFESSIONAL'S JUDGMENT OR CLINICAL DIAGNOSIS. 27 | 28 | 4. Disclaimer of Warranties. 29 | TO THE FULLEST EXTENT PERMITTED BY LAW, MGH PROVIDES THE SOFTWARE TOOL "AS IS" AND “AS AVAILABLE” WITH ALL FAULTS, ERRORS AND DEFECTS, AND NEITHER MGH NOR ANY OF ITS PERSONNEL NOR ANY OF ITS AFFILIATES IS RESPONSIBLE FOR ENSURING THAT ANY USE OF SOFTWARE TOOL WILL BE CLINICALLY SOUND, WITHOUT ERROR, UNINTERRUPTED OR OTHERWISE SUCCESSFUL. THE RIGHTS GRANTED IN THIS EULA ARE MADE AVAILABLE WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. 30 | 31 | 5. Limitation of Liability. 32 | TO THE FULLEST EXTENT PERMITTED BY LAW, MGH SHALL NOT BE LIABLE TO YOU FOR ANY INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT WITHOUT LIMITATION, ANY DAMAGES RESULTING FROM LOSS OF USE OR LOST BUSINESS, REVENUE, PROFITS, DATA OR GOODWILL) ARISING IN CONNECTION WITH YOUR USE OF THE SOFTWARE TOOL OR OTHERWISE, WHETHER IN AN ACTION IN CONTRACT, TORT, STRICT LIABILITY, NEGLIGENCE OR OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 33 | 34 | 6. Indemnification. 35 | You agree to defend, indemnify and hold harmless MGH and its affiliates, trustees, officers, employees, staff members, agents or contractors from and against any claim, charge, demand, action or suit, whether in contract, tort, strict liability, negligence or otherwise, for any and all losses, costs, charges, claims, demands, fees, expenses or damages of any nature or kind arising out of, connected with or resulting from (i) the use of the Software Tool by you, your affiliates, employees, staff, faculty, students, agents or (ii) relating in any way to this EULA. 36 | 37 | In consideration of MGH providing access to the Software Tool free of charge, you agree not to bring any claim, lawsuit, or action (“Claim”) for any damages, costs, liabilities, settlement amounts and/or expenses (including attorneys’ fees) against MGH or its affiliates, trustees, officers, employees, staff members, agents or contractors arising out of or related to your use of the Software Tool. 38 | 39 | 7. No Other Rights. 40 | You do not have the right to use the name, trademark, service mark, logo or other identifying characteristics of MGH or any of its affiliates or employees. All rights not expressly granted herein are reserved by MGH. 41 | 42 | MGH may terminate your access to and use of the Software Tool at any time, with or without notice, for any reason or for no reason at all. 43 | 44 | 8. Governing Law. 45 | The construction and performance of this EULA will be governed by the laws of the Commonwealth of Massachusetts, without regard to conflicts of laws principles. 46 | 47 | 9. Entire Agreement. 48 | This EULA sets forth all of the covenants, provisions, agreements, conditions, and understandings between the parties regarding the subject matter herein, and there are no covenants, promises, agreements, conditions, or understandings, either oral or written, between them other than those set forth herein. 49 | 50 | Should you have any concerns regarding this EULA contact us at licensing@edilytics.com. 51 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include CRISPResso2/EDNAFULL 2 | include CRISPResso2/args.json 3 | recursive-include CRISPResso2/CRISPRessoReports/templates * 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Docker Image Version (tag)](https://img.shields.io/docker/v/pinellolab/crispresso2/latest?logo=docker&label=Docker)](https://hub.docker.com/r/pinellolab/crispresso2/tags) 2 | [![CircleCI branch](https://img.shields.io/circleci/project/github/pinellolab/CRISPResso2/master.svg)](https://circleci.com/gh/pinellolab/CRISPResso2) 3 | [![install with bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg?style=flat)](http://bioconda.github.io/recipes/crispresso2/README.html) 4 | [![Documentation](https://img.shields.io/badge/docs-latest-blue)](https://docs.crispresso.com) 5 | 6 | # CRISPResso2 7 | 8 | CRISPResso2 is a software pipeline designed to enable rapid and intuitive interpretation of genome editing experiments. A limited web implementation is available at: https://crispresso2.pinellolab.org/. 9 | 10 | Briefly, CRISPResso2: 11 | 12 | - aligns sequencing reads to a reference sequence 13 | - quantifies insertions, mutations and deletions to determine whether a read is modified or unmodified by genome editing 14 | - summarizes editing results in intuitive plots and datasets 15 | 16 | Access the full documentation at . 17 | 18 | In addition, CRISPResso can be run as part of a larger tool suite: 19 | 20 | - [CRISPRessoBatch](https://docs.crispresso.com/suite/batch/tool.html) - for analyzing and comparing multiple experimental conditions at the same site 21 | - [CRISPRessoPooled](https://docs.crispresso.com/suite/pooled/tool.html) - for analyzing multiple amplicons from a pooled amplicon sequencing experiment 22 | - [CRISPRessoWGS](https://docs.crispresso.com/suite/wgs/tool.html) - for analyzing specific sites in whole-genome sequencing samples 23 | - [CRISPRessoCompare](https://docs.crispresso.com/suite/compare/tool.html) - for comparing editing between two samples (e.g., treated vs control) 24 | - [CRISPRessoAggregate](https://docs.crispresso.com/suite/aggregate/tool.html) - for aggregating results from previously-run CRISPResso analyses 25 | 26 | ![CRISPResso2 Schematic](https://raw.githubusercontent.com/pinellolab/CRISPResso2/master/crispresso_schematic.png "CRISPResso2 Schematic") 27 | 28 | ## Installation 29 | 30 | CRISPResso2 can be [installed](https://docs.crispresso.com/installation.html) in the following ways: 31 | 32 | - [Bioconda](https://docs.crispresso.com/installation.html#bioconda) 33 | - [Bioconda on Apple Silicon](https://docs.crispresso.com/installation.html#bioconda-for-apple-silicon) 34 | - [Docker](https://docs.crispresso.com/installation.html#docker) 35 | 36 | ## Examples 37 | 38 | - [CRISPResso example runs](https://docs.crispresso.com/suite/core/examples.html) 39 | - [CRISPRessoBatch example runs](https://docs.crispresso.com/suite/batch/examples.html) 40 | - [CRISPRessoPooled example runs](https://docs.crispresso.com/suite/pooled/examples.html) 41 | - [CRISPRessoWGS example runs](https://docs.crispresso.com/suite/wgs/examples.html) 42 | - [CRISPRessoCompare example runs](https://docs.crispresso.com/suite/compare/examples.html) 43 | - [CRISPRessoPooledWGCompare example runs](https://docs.crispresso.com/suite/pooledwgscompare/examples.html) 44 | - [CRISPRessoAggregate example runs](https://docs.crispresso.com/suite/aggregate/examples.html) 45 | 46 | ## Troubleshooting 47 | 48 | If you run into any issues, check out the [Troubleshooting page](https://docs.crispresso.com/troubleshooting.html) or submit a [new discussion](https://github.com/pinellolab/CRISPResso2/discussions/new?category=troubleshooting). 49 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | $PYTHON setup.py install --single-version-externally-managed --record=record.txt # Python command to install the script. 2 | -------------------------------------------------------------------------------- /crispresso_schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/crispresso_schematic.png -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "wheel", "cython", "numpy"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "CRISPResso2" 7 | version = "2.1.3" 8 | dependencies = [ 9 | "pandas", 10 | "matplotlib", 11 | "seaborn", 12 | "jinja2", 13 | "scipy", 14 | "numpy" 15 | ] 16 | description = "Software pipeline for the analysis of genome editing outcomes from deep sequencing data" 17 | authors = [ 18 | { name = "Edilytics, Inc.", email = "support@edilytics.com" } 19 | ] 20 | license = { file = "LICENSE" } 21 | readme = "README.md" 22 | classifiers = [ 23 | "Development Status :: 4 - Beta", 24 | "Environment :: Console", 25 | "Intended Audience :: Developers", 26 | "Intended Audience :: Science/Research", 27 | "License :: Other/Proprietary License", 28 | "Operating System :: POSIX", 29 | "Topic :: Scientific/Engineering :: Bio-Informatics", 30 | "Programming Language :: Python :: 3 :: Only", 31 | "Programming Language :: Cython", 32 | ] 33 | 34 | [project.optional-dependencies] 35 | dev = ["cython"] 36 | 37 | [project.scripts] 38 | CRISPResso = "CRISPResso2.CRISPRessoCORE:main" 39 | CRISPRessoBatch = "CRISPResso2.CRISPRessoBatchCORE:main" 40 | CRISPRessoPooled = "CRISPResso2.CRISPRessoPooledCORE:main" 41 | CRISPRessoWGS = "CRISPResso2.CRISPRessoWGSCORE:main" 42 | CRISPRessoCompare = "CRISPResso2.CRISPRessoCompareCORE:main" 43 | CRISPRessoPooledWGSCompare = "CRISPResso2.CRISPRessoPooledWGSCompareCORE:main" 44 | CRISPRessoAggregate = "CRISPResso2.CRISPRessoAggregateCORE:main" 45 | 46 | [project.urls] 47 | Homepage = "https://github.com/pinellolab/CRISPResso2" 48 | 49 | [tool.setuptools] 50 | package-dir = {"" = "CRISPResso2"} 51 | packages = ["CRISPResso2", "CRISPResso2.CRISPRessoReports"] 52 | include-package-data = true 53 | -------------------------------------------------------------------------------- /scripts/countHighQualityBases.py: -------------------------------------------------------------------------------- 1 | import gzip 2 | import argparse 3 | 4 | def get_dict_from_plus_line(plus_line): 5 | """ Create a dictionary from the 3rd line (plus line) of a CRISPResso-annotated fastq file 6 | 7 | Args: 8 | plus_line (str): The 3rd line of a CRISPResso-annotated fastq file 9 | 10 | Returns: 11 | dict: dictionary of CRISPResso annotations > values 12 | """ 13 | equals_line_els = plus_line.split(" ") 14 | equals_dict = {} 15 | for el in equals_line_els: 16 | el_els = el.split("=") 17 | if len(el_els) > 1: 18 | equals_dict[el_els[0]] = el_els[1] 19 | else: 20 | equals_dict[el_els[0]] = None 21 | return equals_dict 22 | 23 | def get_ref_details_from_aln_details(aln_details): 24 | """ Get the reference details from the 'ALN_DETAILS' element of the 3rd line (plus line) of a CRISPResso-annotated fastq file 25 | 26 | Args: 27 | aln_details (str): The ALN_DETAILS element consisting of the reference name, read sequence alignment, reference sequence alignment, and alignment score for each reference 28 | 29 | Returns: 30 | dict: dictionary of ref_name > read_seq_alignment, ref_seq_alignment, aln_score 31 | """ 32 | ref_details = {} 33 | ref_els = aln_details.split("&") 34 | for el in ref_els: 35 | el_els = el.split(",") 36 | if len(el_els) != 4: 37 | raise Exception("got unexpected number of elements in ALN_DETAILS: " + str(el_els)) 38 | (ref_name, read_seq, ref_seq, aln_score) = el.split(",") 39 | ref_details[ref_name] = (read_seq, ref_seq, aln_score) 40 | return ref_details 41 | 42 | def get_ref_coordinates_from_aln(read_aln, ref_aln): 43 | """ Get the reference coordinates from the read and reference alignments 44 | So if we want to check the base at the 5th base in the reference, we would go to the ref_pos_in_aln[5]th position in the alignment 45 | If we want to get the base in the read corresponding to the 5th base in the reference, we would go to the ref_pos_in_read[5]th position in the read 46 | 47 | Args: 48 | read_aln (str): read alignment 49 | ref_aln (str): reference alignment 50 | 51 | Returns: 52 | arr(int): array of reference positions in the alignment 53 | arr(int): array of reference positions in the read 54 | """ 55 | read_pos = -1 56 | ref_pos_in_aln = [] #list of reference positions in the alignment 57 | ref_pos_in_read = [] #list of reference positions in the read 58 | for i in range(len(read_aln)): 59 | if read_aln[i] != "-": 60 | read_pos += 1 61 | if ref_aln[i] != "-": 62 | ref_pos_in_aln.append(i) 63 | ref_pos_in_read.append(read_pos) 64 | 65 | return (ref_pos_in_aln, ref_pos_in_read) 66 | 67 | 68 | def count_high_quality_bases(file, ref_name, base_pos_in_ref, original_base, target_base, quality_cutoff): 69 | """Counts high-quality bases at a certain position in the reference 70 | 71 | Args: 72 | file (str): CRISPResso_output.fastq.gz file to analyze 73 | ref (str): Reference name 74 | base_pos_in_ref (int): 0-based position in the reference to check 75 | original_base (char): original base to check 76 | target_base (char): target base to check 77 | quality_cutoff (int): quality cutoff for high-quality bases 78 | 79 | """ 80 | # file = "CRISPResso_output.fastq.gz" 81 | # ref_name = "Reference" 82 | # base_pos_in_ref = 100 83 | # original_base = "A" 84 | # target_base = "T" 85 | # quality_cutoff = 30 86 | 87 | count_total_reads = 0 88 | count_unaligned = 0 # also includes reads not aligned to specified ref_name 89 | 90 | count_original_base_highQual = 0 91 | count_original_base_lowQual = 0 92 | 93 | count_target_base_highQual = 0 94 | count_target_base_lowQual = 0 95 | 96 | count_base_deletion = 0 97 | 98 | count_other_base_highQual = 0 99 | count_other_base_lowQual = 0 100 | 101 | with gzip.open(file, 'rt') as f: 102 | while True: 103 | id_line = f.readline() 104 | seq_line = f.readline() 105 | plus_line = f.readline() 106 | qual_line = f.readline() 107 | 108 | if not id_line: 109 | break 110 | 111 | count_total_reads += 1 112 | 113 | plus_line_dict = get_dict_from_plus_line(plus_line) 114 | if 'ALN' not in plus_line_dict: 115 | raise Exception("ALN not in plus line: " + plus_line) 116 | if plus_line_dict['ALN'] != ref_name: 117 | count_unaligned += 1 118 | else: 119 | ref_details = get_ref_details_from_aln_details(plus_line_dict['ALN_DETAILS']) 120 | if ref_name in ref_details: 121 | read_aln = ref_details[ref_name][0] # sequence of read aligned to ref (includes gaps) 122 | ref_aln = ref_details[ref_name][1] # sequence of ref aligned to read (includes gaps) 123 | ref_coordinates_in_aln, ref_coordinates_in_read = get_ref_coordinates_from_aln(read_aln,ref_aln) 124 | base_in_read = read_aln[ref_coordinates_in_aln[base_pos_in_ref]] 125 | quality_in_read = qual_line[ref_coordinates_in_read[base_pos_in_ref]] 126 | 127 | if base_in_read == original_base: 128 | if ord(quality_in_read) - 33 >= quality_cutoff: 129 | count_original_base_highQual += 1 130 | else: 131 | count_original_base_lowQual += 1 132 | elif base_in_read == target_base: 133 | if ord(quality_in_read) - 33 >= quality_cutoff: 134 | count_target_base_highQual += 1 135 | else: 136 | count_target_base_lowQual += 1 137 | elif base_in_read == "-": 138 | count_base_deletion += 1 139 | else: 140 | if ord(quality_in_read) - 33 >= quality_cutoff: 141 | count_other_base_highQual += 1 142 | else: 143 | count_other_base_lowQual += 1 144 | 145 | print("Total reads read: " + str(count_total_reads)) 146 | print("Unaligned reads: " + str(count_unaligned)) 147 | print("Original base high quality: " + str(count_original_base_highQual)) 148 | print("Original base low quality: " + str(count_original_base_lowQual)) 149 | print("Target base high quality: " + str(count_target_base_highQual)) 150 | print("Target base low quality: " + str(count_target_base_lowQual)) 151 | print("Base deletion: " + str(count_base_deletion)) 152 | print("Other base high quality: " + str(count_other_base_highQual)) 153 | print("Other base low quality: " + str(count_other_base_lowQual)) 154 | 155 | if __name__ == "__main__": 156 | parser = argparse.ArgumentParser() 157 | parser.add_argument("-f", "--file", help="CRISPResso_output.fastq.gz file to analyze", required=True) 158 | parser.add_argument("-r", "--ref_name", help="Reference name", default="Reference") 159 | parser.add_argument("-p", "--pos", type=int, help="0-based position in the reference to check", required=True) 160 | parser.add_argument("-o", "--original", help="original base to check", required=True) 161 | parser.add_argument("-t", "--target", help="target base to check", required=True) 162 | parser.add_argument("-q", "--quality", type=int, help="quality cutoff for high-quality bases", default=30) 163 | args = parser.parse_args() 164 | 165 | count_high_quality_bases(args.file, args.ref_name, args.pos, args.original, args.target, args.quality) 166 | -------------------------------------------------------------------------------- /scripts/count_sgRNA_specific_edits.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import pandas as pd 4 | import zipfile 5 | 6 | from collections import defaultdict 7 | from CRISPResso2 import CRISPRessoShared 8 | 9 | def count_sgRNA_specific_edits(crispresso_output_folder): 10 | crispresso2_info = CRISPRessoShared.load_crispresso_info(crispresso_output_folder) 11 | 12 | run_version = crispresso2_info['running_info']['version'] 13 | version_parts = run_version.split('.') 14 | if int(version_parts[0]) != 2 or int(version_parts[1]) < 2 or int(version_parts[2]) < 15: 15 | raise Exception('CRISPResso run must be run with CRISPResso2 v2.2.15 or later (this run was run with version v' + str(run_version) + ')') 16 | 17 | if not crispresso2_info['running_info']['args'].write_detailed_allele_table: 18 | raise Exception('CRISPResso run must be run with the parameter --write_detailed_allele_table') 19 | 20 | include_idxs = {} # ref_name > guide_name > idxs 21 | all_reference_guides = {} # order of guides for each reference 22 | modified_counts_by_amplicon = {} # ref_name > category > count 23 | for reference_name in crispresso2_info['results']['ref_names']: 24 | include_idxs[reference_name] = {} 25 | all_reference_guides[reference_name] = [] 26 | modified_counts_by_amplicon[reference_name] = defaultdict(int) 27 | for idx, guide_name in enumerate(crispresso2_info['results']['refs'][reference_name]['sgRNA_names']): 28 | this_guide_name = guide_name 29 | if this_guide_name == '': 30 | this_guide_name = crispresso2_info['results']['refs'][reference_name]['sgRNA_orig_sequences'][idx] 31 | if this_guide_name in include_idxs[reference_name]: 32 | this_guide_name = this_guide_name + '_' + str(crispresso2_info['results']['refs'][reference_name]['sgRNA_intervals'][idx][0]) 33 | include_idxs[reference_name][this_guide_name] = crispresso2_info['results']['refs'][reference_name]['sgRNA_include_idxs'][idx] 34 | all_reference_guides[reference_name].append(this_guide_name) 35 | 36 | 37 | z = zipfile.ZipFile(os.path.join(crispresso_output_folder, crispresso2_info['running_info']['allele_frequency_table_zip_filename'])) 38 | zf = z.open(crispresso2_info['running_info']['allele_frequency_table_filename']) 39 | df_alleles = pd.read_csv(zf,sep="\t") 40 | 41 | read_alleles_count = 0 # all alleles read 42 | reference_count = defaultdict(int) # counts of modification at reference level 43 | reference_modified_count = defaultdict(int) 44 | total_counts = defaultdict(int) 45 | modified_counts = defaultdict(int) 46 | for idx, row in df_alleles.iterrows(): 47 | read_alleles_count += row['#Reads'] 48 | this_reference_name = row['Reference_Name'] 49 | if this_reference_name in include_idxs: # sometimes (e.g. AMBIGUOUS) reads aren't assigned to a reference, so exclude them here.. 50 | reference_count[this_reference_name] += row['#Reads'] 51 | 52 | this_allele_modified_guide_names = [] 53 | ref_is_modified = False 54 | row_insertion_positions = [int(x) for x in row['insertion_positions'][1:-1].split(",")] if row['insertion_positions'] != '[]' else [] 55 | row_deletion_positions = [int(x) for x in row['deletion_positions'][1:-1].split(",")] if row['deletion_positions'] != '[]' else [] 56 | row_substitution_positions = [int(x) for x in row['substitution_positions'][1:-1].split(",")] if row['substitution_positions'] != '[]' else [] 57 | for guide_name in all_reference_guides[this_reference_name]: 58 | is_modified = False 59 | for ind in include_idxs[this_reference_name][guide_name]: 60 | if ind in row_insertion_positions: 61 | is_modified = True 62 | if ind in row_deletion_positions: 63 | is_modified = True 64 | if ind in row_substitution_positions: 65 | is_modified = True 66 | if is_modified: 67 | this_allele_modified_guide_names.append(guide_name) 68 | ref_is_modified = True 69 | 70 | this_category = 'UNMODIFIED' 71 | if ref_is_modified: 72 | reference_modified_count[this_reference_name] += row['#Reads'] 73 | this_category = 'MODIFIED ' + ' + '.join(this_allele_modified_guide_names) 74 | modified_counts_by_amplicon[this_reference_name][this_category] += row['#Reads'] 75 | 76 | 77 | print('Processed ' + str(read_alleles_count) + ' alleles') 78 | for reference_name in crispresso2_info['results']['ref_names']: 79 | print ('Reference: ' + reference_name + ' (' + str(reference_modified_count[reference_name]) + '/' + str(reference_count[reference_name]) + ' modified reads)') 80 | for category in modified_counts_by_amplicon[reference_name]: 81 | print("\t" + category + ": " + str(modified_counts_by_amplicon[reference_name][category])) 82 | 83 | 84 | 85 | if __name__ == "__main__": 86 | parser = argparse.ArgumentParser(description='Count sgRNA-specific edits') 87 | parser.add_argument("-f", "--folder", help="CRISPResso output folder", required=True) 88 | args = parser.parse_args() 89 | 90 | count_sgRNA_specific_edits(args.folder) 91 | -------------------------------------------------------------------------------- /scripts/filterReadsOnSequencePresence.py: -------------------------------------------------------------------------------- 1 | import gzip 2 | import argparse 3 | from collections import defaultdict 4 | 5 | def main(): 6 | parser = argparse.ArgumentParser(description="Filter reads based on sequence presence") 7 | parser.add_argument("--fastq_r1",type=str,help="Fastq R1 to filter",required=True) 8 | parser.add_argument("--fastq_r2",type=str,help="Fastq R2 to filter",default=None) 9 | parser.add_argument("--fastq_r1_out",type=str,help="Fastq R1 output file to contain filtered reads",default=None) 10 | parser.add_argument("--fastq_r2_out",type=str,help="Fastq R2 output file to contain filtered reads",default=None) 11 | parser.add_argument("--include_seq",type=str,help="Sequence that must be present in every read. Reads without this sequence will be filtered out. " + \ 12 | "This argument may be specified multiple times, and reads must contain at least one of these sequences",default=[],action='append') 13 | parser.add_argument("--exclude_seq",type=str,help="Sequence that must NOT be present in every read. Reads with this sequence will be filtered out. "+ \ 14 | "This argument may be specified multiple times, and read must not contain any of these sequences",default=[],action='append') 15 | 16 | args = parser.parse_args() 17 | 18 | if not args.include_seq and not args.exclude_seq: 19 | raise ValueError("You must specify either --include_seq or --exclude_seq") 20 | 21 | fastq_r1_out = args.fastq_r1_out 22 | if fastq_r1_out is None: 23 | fastq_r1_out = args.fastq_r1.replace('.fastq', '').replace('.fq','').replace('.gz', '')+".filtered.fq" 24 | if args.fastq_r1.endswith('.gz'): 25 | fastq_r1_out += ".gz" 26 | 27 | fastq_r2_out = args.fastq_r2_out 28 | if args.fastq_r2 is not None and fastq_r2_out is None: 29 | fastq_r2_out = args.fastq_r2.replace('.fastq', '').replace('.fq','').replace('.gz', '')+".filtered.fq" 30 | if args.fastq_r2.endswith('.gz'): 31 | fastq_r2_out += ".gz" 32 | 33 | 34 | ##CREATION OF FILEHANDLES## 35 | if args.fastq_r1.endswith('.gz'): 36 | f1_in = gzip.open(args.fastq_r1, 'rt') 37 | else: 38 | f1_in = open(args.fastq_r1, 'rt') 39 | if fastq_r1_out.endswith('.gz'): 40 | f1_out = gzip.open(fastq_r1_out, 'wt') 41 | else: 42 | f1_out = open(fastq_r1_out, 'w') 43 | 44 | if args.fastq_r2: 45 | if args.fastq_r2.endswith('.gz'): 46 | f2_in = gzip.open(args.fastq_r2, 'rt') 47 | else: 48 | f2_in = open(args.fastq_r2, 'rt') 49 | if fastq_r2_out.endswith('.gz'): 50 | f2_out = gzip.open(fastq_r2_out, 'wt') 51 | else: 52 | f2_out = open(fastq_r2_out, 'w') 53 | ###END CREATION OF FILEHANDLES## 54 | 55 | print('Fastq R1: %s' % args.fastq_r1) 56 | print('Fastq R2: %s' % args.fastq_r2) 57 | print('Fastq R1 out: %s' % fastq_r1_out) 58 | print('Fastq R2 out: %s' % fastq_r2_out) 59 | 60 | print('Include seq: %s' % args.include_seq) 61 | print('Exclude seq: %s' % args.exclude_seq) 62 | 63 | 64 | read_read_count = 0 65 | read_written_count = 0 66 | read_include_count = defaultdict(int) 67 | read_exclude_count = defaultdict(int) 68 | if args.fastq_r2: 69 | while True: 70 | r1_id_line = f1_in.readline().rstrip() 71 | r1_seq_line = f1_in.readline().rstrip() 72 | r1_plus_line = f1_in.readline().rstrip() 73 | r1_qual_line = f1_in.readline().rstrip() 74 | 75 | r2_id_line = f2_in.readline().rstrip() 76 | r2_seq_line = f2_in.readline().rstrip() 77 | r2_plus_line = f2_in.readline().rstrip() 78 | r2_qual_line = f2_in.readline().rstrip() 79 | 80 | if not r1_id_line: 81 | break 82 | read_read_count += 1 83 | 84 | include_read = True 85 | if args.include_seq != []: 86 | include_read = False 87 | for include_seq in args.include_seq: 88 | if include_seq in r1_seq_line or include_seq in r2_seq_line: 89 | include_read = True 90 | read_include_count[include_seq] += 1 91 | 92 | exclude_read = False 93 | if args.exclude_seq != []: 94 | for exclude_seq in args.exclude_seq: 95 | if exclude_seq in r1_seq_line or exclude_seq in r2_seq_line: 96 | exclude_read = True 97 | read_exclude_count[exclude_seq] += 1 98 | 99 | if include_read and not exclude_read: 100 | read_written_count += 1 101 | f1_out.write("%s\n%s\n%s\n%s\n" % (r1_id_line,r1_seq_line,r1_plus_line,r1_qual_line)) 102 | f2_out.write("%s\n%s\n%s\n%s\n" % (r2_id_line,r2_seq_line,r2_plus_line,r2_qual_line)) 103 | 104 | print('Printed %s/%s reads to %s and %s' % (read_written_count,read_read_count,fastq_r1_out,fastq_r2_out)) 105 | 106 | else: 107 | while True: 108 | r1_id_line = f1_in.readline().rstrip() 109 | r1_seq_line = f1_in.readline().rstrip() 110 | r1_plus_line = f1_in.readline().rstrip() 111 | r1_qual_line = f1_in.readline().rstrip() 112 | 113 | if not r1_id_line: 114 | break 115 | read_read_count += 1 116 | 117 | include_read = True 118 | if args.include_seq != []: 119 | include_read = False 120 | for include_seq in args.include_seq: 121 | if include_seq in r1_seq_line: 122 | include_read = True 123 | read_include_count[include_seq] += 1 124 | 125 | exclude_read = False 126 | if args.exclude_seq != []: 127 | for exclude_seq in args.exclude_seq: 128 | if exclude_seq in r1_seq_line: 129 | exclude_read = True 130 | read_exclude_count[exclude_seq] += 1 131 | 132 | if include_read and not exclude_read: 133 | read_written_count += 1 134 | f1_out.write("%s\n%s\n%s\n%s" % (r1_id_line,r1_seq_line,r1_plus_line,r1_qual_line)) 135 | print('Printed %s/%s reads to %s' % (read_written_count,read_read_count,fastq_r1_out)) 136 | 137 | for seq in args.include_seq: 138 | print('Reads containing included sequence %s: %s' % (seq,read_include_count[seq])) 139 | for seq in args.exclude_seq: 140 | print('Reads containing excluded sequence %s: %s' % (seq,read_exclude_count[seq])) 141 | 142 | if __name__ == "__main__": 143 | main() 144 | -------------------------------------------------------------------------------- /scripts/plotAmbiguous.py: -------------------------------------------------------------------------------- 1 | ''' 2 | CRISPResso2 - Kendell Clement and Luca Pinello 2020 3 | Software pipeline for the analysis of genome editing outcomes from deep sequencing data 4 | (c) 2020 The General Hospital Corporation. All Rights Reserved. 5 | ''' 6 | 7 | import argparse 8 | import os 9 | import numpy as np 10 | import pandas as pd 11 | import zipfile 12 | 13 | from CRISPResso2 import CRISPRessoShared 14 | 15 | def main(): 16 | parser = argparse.ArgumentParser(description="Plot ambiguous reads") 17 | parser.add_argument("-f","--CRISPResso2_folder",type=str,help="CRISPResso output folder to plot ambiguous reads for",required=True) 18 | parser.add_argument("-o","--output_root",type=str,help="Plot output root (should not include '.pdf' or '.png')",required=True) 19 | parser.add_argument("--min_freq","--min_frequency_alleles_around_cut_to_plot",type=float,help="Minimum frequency of alleles to plot") 20 | parser.add_argument("--max_rows","--max_rows_alleles_around_cut_to_plot",type=float,help="Maximum number of rows to plot") 21 | parser.add_argument("--plot_cut_point",help="If set, a line at the cut point will be plotted.",action="store_true") 22 | parser.add_argument("--save_png",help="If set, pngs will also be produced (as well as pdfs).",action="store_true") 23 | 24 | #CRISPRessoPro params 25 | parser.add_argument('--use_matplotlib', action='store_true', 26 | help='Use matplotlib for plotting instead of plotly/d3 when CRISPRessoPro is installed') 27 | 28 | args = parser.parse_args() 29 | 30 | if args.use_matplotlib or not CRISPRessoShared.is_C2Pro_installed(): 31 | from CRISPResso2 import CRISPRessoPlot 32 | else: 33 | from CRISPRessoPro import plot as CRISPRessoPlot 34 | 35 | plot_ambiguous_alleles_tables_from_folder(args.CRISPResso2_folder,args.output_root,MIN_FREQUENCY=args.min_freq,MAX_N_ROWS=args.max_rows,SAVE_ALSO_PNG=args.save_png,plot_cut_point=args.plot_cut_point) 36 | 37 | def arrStr_to_arr(val): 38 | return [int(x) for x in val[1:-1].split(",")] 39 | 40 | def plot_ambiguous_alleles_tables_from_folder(crispresso_output_folder,fig_filename_root,MIN_FREQUENCY=None,MAX_N_ROWS=None,SAVE_ALSO_PNG=False,custom_colors=None,plot_cut_point=True,sgRNA_intervals=None,sgRNA_names=None,sgRNA_mismatches=None): 41 | """ 42 | Plots an allele table plot of ambiguous alleles from a completed CRISPResso run 43 | This function is only used for one-off plotting purposes and not for the general CRISPResso analysis 44 | Important: The run must have been run with the --write_detailed_allele_table parameter 45 | Ambiguous reads align to multiple reference amplicons with the same score 46 | In this function, ambiguous reads are filtered from the allele tables and the allele plots for these ambiguous reads are plotted 47 | Note that each ambiguous read is assigned to a reference (usually the first one) and mutations/indels are plotted in relation to this reference sequence. 48 | crispresso_output_folder: completed analysis crispresso2 output folder 49 | fig_filename_root: figure filename to plot (not including '.pdf' or '.png') 50 | MIN_FREQUENCY: sum of alleles % must add to this to be plotted 51 | MAX_N_ROWS: max rows to plot 52 | SAVE_ALSO_PNG: whether to write png file as well 53 | plot_cut_point: if false, won't draw 'predicted cleavage' line 54 | example: 55 | """ 56 | crispresso2_info = CRISPRessoShared.load_crispresso_info(crispresso_output_folder) 57 | 58 | if not crispresso2_info['running_info']['args'].write_detailed_allele_table: 59 | raise Exception('CRISPResso run must be run with the parameter --write_detailed_allele_table') 60 | 61 | if MIN_FREQUENCY is None: 62 | MIN_FREQUENCY = crispresso2_info['running_info']['args'].min_frequency_alleles_around_cut_to_plot 63 | if MAX_N_ROWS is None: 64 | MAX_N_ROWS = crispresso2_info['running_info']['args'].max_rows_alleles_around_cut_to_plot 65 | 66 | plot_count = 0 67 | 68 | z = zipfile.ZipFile(os.path.join(crispresso_output_folder, crispresso2_info['running_info']['allele_frequency_table_zip_filename'])) 69 | zf = z.open(crispresso2_info['running_info']['allele_frequency_table_filename']) 70 | df_alleles = pd.read_csv(zf,sep="\t") 71 | full_len = df_alleles['#Reads'].sum() 72 | df_alleles['ref_positions'] = df_alleles['ref_positions'].apply(arrStr_to_arr) 73 | 74 | #pd.set_option('display.max_columns', None) 75 | #print(df_alleles.head()) 76 | df_ambiguous = df_alleles[df_alleles['Reference_Name'].str.contains('AMBIGUOUS')] 77 | ambig_len = df_ambiguous['#Reads'].sum() 78 | 79 | print("Filtered to " + str(ambig_len) + "/" + str(full_len) + " ambiguous reads") 80 | 81 | ref_names = crispresso2_info['results']['ref_names'] 82 | refs = crispresso2_info['results']['refs'] 83 | print("Ambiguous alleles will be plotted against to the sequence of the first reference sequence ("+ref_names[0]+")") 84 | for ref_name in ref_names: 85 | sgRNA_sequences = refs[ref_name]['sgRNA_sequences'] 86 | sgRNA_cut_points = refs[ref_name]['sgRNA_cut_points'] 87 | sgRNA_plot_cut_points = refs[ref_name]['sgRNA_plot_cut_points'] 88 | sgRNA_intervals = refs[ref_name]['sgRNA_intervals'] 89 | sgRNA_names = refs[ref_name]['sgRNA_names'] 90 | sgRNA_mismatches = refs[ref_name]['sgRNA_mismatches'] 91 | sgRNA_plot_idxs = refs[ref_name]['sgRNA_plot_idxs'] 92 | 93 | reference_seq = refs[ref_name]['sequence'] 94 | 95 | for ind,sgRNA in enumerate(sgRNA_sequences): 96 | sgRNA_label = sgRNA # for file names 97 | if sgRNA_names[ind] != "": 98 | sgRNA_label = sgRNA_names[ind] 99 | 100 | cut_point = sgRNA_cut_points[ind] 101 | plot_cut_point = sgRNA_plot_cut_points[ind] 102 | plot_idxs = sgRNA_plot_idxs[ind] 103 | plot_half_window = max(1,crispresso2_info['running_info']['args'].plot_window_size) 104 | ref_seq_around_cut=refs[ref_name]['sequence'][cut_point-plot_half_window+1:cut_point+plot_half_window+1] 105 | 106 | ambiguous_ref_name = "AMBIGUOUS_"+ref_name 107 | df_alleles_around_cut=CRISPRessoShared.get_dataframe_around_cut_asymmetrical(df_alleles.loc[df_alleles['Reference_Name'] == ambiguous_ref_name],cut_point,plot_half_window, plot_half_window) 108 | this_ambig_allele_count = len(df_alleles_around_cut.index) 109 | if this_ambig_allele_count < 1: 110 | print('No ambiguous reads found for ' + ref_name) 111 | continue 112 | this_ambig_count = df_alleles_around_cut['#Reads'].sum() 113 | print('Plotting ' + str(this_ambig_count) + ' ambiguous reads for ' + ref_name) 114 | 115 | new_sgRNA_intervals = [] 116 | #adjust coordinates of sgRNAs 117 | new_sel_cols_start = cut_point - plot_half_window 118 | for (int_start, int_end) in refs[ref_name]['sgRNA_intervals']: 119 | new_sgRNA_intervals += [(int_start - new_sel_cols_start - 1,int_end - new_sel_cols_start - 1)] 120 | fig_filename_root = fig_filename_root+"_"+ref_name+"_"+sgRNA_label 121 | CRISPRessoPlot.plot_alleles_table(ref_seq_around_cut,df_alleles=df_alleles_around_cut,fig_filename_root=fig_filename_root,custom_colors=custom_colors,MIN_FREQUENCY=MIN_FREQUENCY,MAX_N_ROWS=MAX_N_ROWS,SAVE_ALSO_PNG=SAVE_ALSO_PNG,plot_cut_point=plot_cut_point,sgRNA_intervals=new_sgRNA_intervals,sgRNA_names=sgRNA_names,sgRNA_mismatches=sgRNA_mismatches,annotate_wildtype_allele=crispresso2_info['running_info']['args'].annotate_wildtype_allele) 122 | 123 | plot_count += 1 124 | print('Plotted ' + str(plot_count) + ' plots') 125 | 126 | if __name__ == "__main__": 127 | # execute only if run as a script 128 | main() 129 | -------------------------------------------------------------------------------- /scripts/plotCustomAllelePlot.py: -------------------------------------------------------------------------------- 1 | ''' 2 | CRISPResso2 - Kendell Clement and Luca Pinello 2020 3 | Software pipeline for the analysis of genome editing outcomes from deep sequencing data 4 | (c) 2020 The General Hospital Corporation. All Rights Reserved. 5 | ''' 6 | 7 | import argparse 8 | import os 9 | import numpy as np 10 | import pandas as pd 11 | import zipfile 12 | from CRISPResso2 import CRISPRessoShared 13 | import seaborn as sns 14 | import matplotlib 15 | import matplotlib.pyplot as plt 16 | import matplotlib.gridspec as gridspec 17 | from matplotlib import colors as colors_mpl 18 | import matplotlib.patches as patches 19 | 20 | def main(): 21 | parser = argparse.ArgumentParser(description="Plot custom allele plots") 22 | parser.add_argument("-f","--CRISPResso2_folder",type=str,help="CRISPResso output folder containing finished analysis",required=True) 23 | parser.add_argument("-o","--output_root",type=str,help="Plot output root (should not include '.pdf' or '.png')",required=True) 24 | parser.add_argument("--min_freq","--min_frequency_alleles_around_cut_to_plot",type=float,help="Minimum frequency of alleles to plot") 25 | parser.add_argument("--max_rows","--max_rows_alleles_around_cut_to_plot",type=int,help="Maximum number of rows to plot") 26 | parser.add_argument("--plot_cut_point",help="If set, a line at the cut point will be plotted.",action="store_true") 27 | parser.add_argument("--save_png",help="If set, pngs will also be produced (as well as pdfs).",action="store_true") 28 | parser.add_argument("--plot_left",help="Number of bases to plot to the left of the cut site",type=int,default=20) 29 | parser.add_argument("--plot_right",help="Number of bases to plot to the right of the cut site",type=int,default=20) 30 | parser.add_argument("--plot_center",help="Center of plot. If set, plots for guide RNAs will not be generated -- only a plot centered at this position will be plotted.",type=int,default=None) 31 | 32 | # CRISPRessoPro params 33 | parser.add_argument('--use_matplotlib', action='store_true', 34 | help='Use matplotlib for plotting instead of plotly/d3 when CRISPRessoPro is installed') 35 | 36 | args = parser.parse_args() 37 | if args.use_matplotlib or not CRISPRessoShared.is_C2Pro_installed(): 38 | from CRISPResso2 import CRISPRessoPlot 39 | else: 40 | from CRISPRessoPro import plot as CRISPRessoPlot 41 | 42 | plot_alleles_tables_from_folder(args.CRISPResso2_folder,args.output_root,MIN_FREQUENCY=args.min_freq,MAX_N_ROWS=args.max_rows,SAVE_ALSO_PNG=args.save_png,plot_cut_point=args.plot_cut_point,plot_left=args.plot_left,plot_right=args.plot_right,plot_center=args.plot_center) 43 | 44 | def arrStr_to_arr(val): 45 | return [int(x) for x in val[1:-1].split(",")] 46 | 47 | def get_row_around_cut_asymmetrical(row,cut_point,plot_left,plot_right): 48 | cut_idx=row['ref_positions'].index(cut_point) 49 | return row['Aligned_Sequence'][cut_idx-plot_left+1:cut_idx+plot_right+1],row['Reference_Sequence'][cut_idx-plot_left+1:cut_idx+plot_right+1],row['Read_Status']=='UNMODIFIED',row['n_deleted'],row['n_inserted'],row['n_mutated'],row['#Reads'], row['%Reads'] 50 | 51 | def get_dataframe_around_cut_asymmetrical(df_alleles, cut_point,plot_left,plot_right,collapse_by_sequence=True): 52 | if df_alleles.shape[0] == 0: 53 | return df_alleles 54 | ref1 = df_alleles['Reference_Sequence'].iloc[0] 55 | ref1 = ref1.replace('-','') 56 | if (cut_point + plot_right + 1 > len(ref1)): 57 | raise(CRISPRessoShared.BadParameterException('The plotting window cannot extend past the end of the amplicon. Amplicon length is ' + str(len(ref1)) + ' but plot extends to ' + str(cut_point+plot_right+1))) 58 | 59 | df_alleles_around_cut=pd.DataFrame(list(df_alleles.apply(lambda row: get_row_around_cut_asymmetrical(row,cut_point,plot_left,plot_right),axis=1).values), 60 | columns=['Aligned_Sequence','Reference_Sequence','Unedited','n_deleted','n_inserted','n_mutated','#Reads','%Reads']) 61 | 62 | df_alleles_around_cut=df_alleles_around_cut.groupby(['Aligned_Sequence','Reference_Sequence','Unedited','n_deleted','n_inserted','n_mutated']).sum().reset_index().set_index('Aligned_Sequence') 63 | 64 | df_alleles_around_cut.sort_values(by=['#Reads', 'Aligned_Sequence', 'Reference_Sequence'], inplace=True, ascending=[False, True, True]) 65 | df_alleles_around_cut['Unedited']=df_alleles_around_cut['Unedited']>0 66 | return df_alleles_around_cut 67 | 68 | def plot_alleles_tables_from_folder(crispresso_output_folder,fig_filename_root,plot_left=20,plot_right=20,plot_center=None,MIN_FREQUENCY=None,MAX_N_ROWS=None,SAVE_ALSO_PNG=False,custom_colors=None,plot_cut_point=True,sgRNA_intervals=None,sgRNA_names=None,sgRNA_mismatches=None): 69 | """ 70 | Plots an allele table plot from a completed CRISPResso run but plots a specified number of bases left and right from the cut site 71 | This function is only used for one-off plotting purposes and not for the general CRISPResso analysis 72 | Important: The run must have been run with the --write_detailed_allele_table parameter 73 | crispresso_output_folder: completed analysis crispresso2 output folder 74 | fig_filename_root: figure filename to plot (not including '.pdf' or '.png') 75 | MIN_FREQUENCY: sum of alleles % must add to this to be plotted 76 | MAX_N_ROWS: max rows to plot 77 | SAVE_ALSO_PNG: whether to write png file as well 78 | plot_cut_point: if false, won't draw 'predicted cleavage' line 79 | plot_left: number of bases left to plot from cut point 80 | plot_right: number of bases right to plot from cut point 81 | """ 82 | crispresso2_info = CRISPRessoShared.load_crispresso_info(crispresso_output_folder) 83 | 84 | if not crispresso2_info['running_info']['args'].write_detailed_allele_table: 85 | raise Exception('CRISPResso run must be run with the parameter --write_detailed_allele_table') 86 | 87 | 88 | if MIN_FREQUENCY is None: 89 | MIN_FREQUENCY = crispresso2_info['running_info']['args'].min_frequency_alleles_around_cut_to_plot 90 | if MAX_N_ROWS is None: 91 | MAX_N_ROWS = crispresso2_info['running_info']['args'].max_rows_alleles_around_cut_to_plot 92 | 93 | plot_count = 0 94 | 95 | z = zipfile.ZipFile(os.path.join(crispresso_output_folder,crispresso2_info['running_info']['allele_frequency_table_zip_filename'])) 96 | zf = z.open(crispresso2_info['running_info']['allele_frequency_table_filename']) 97 | df_alleles = pd.read_csv(zf,sep="\t") 98 | full_len = df_alleles['#Reads'].sum() 99 | df_alleles['ref_positions'] = df_alleles['ref_positions'].apply(arrStr_to_arr) 100 | 101 | ref_names = crispresso2_info['results']['ref_names'] 102 | refs = crispresso2_info['results']['refs'] 103 | for ref_name in ref_names: 104 | sgRNA_sequences = refs[ref_name]['sgRNA_sequences'] 105 | sgRNA_cut_points = refs[ref_name]['sgRNA_cut_points'] 106 | sgRNA_plot_cut_points = refs[ref_name]['sgRNA_plot_cut_points'] 107 | sgRNA_intervals = refs[ref_name]['sgRNA_intervals'] 108 | sgRNA_names = refs[ref_name]['sgRNA_names'] 109 | sgRNA_mismatches = refs[ref_name]['sgRNA_mismatches'] 110 | sgRNA_plot_idxs = refs[ref_name]['sgRNA_plot_idxs'] 111 | 112 | reference_seq = refs[ref_name]['sequence'] 113 | 114 | if plot_center is not None: 115 | sgRNA_label = 'custom' 116 | 117 | cut_point = plot_center 118 | plot_cut_point = plot_center 119 | ref_seq_around_cut=refs[ref_name]['sequence'][cut_point-plot_left+1:cut_point+plot_right+1] 120 | 121 | df_alleles_around_cut=get_dataframe_around_cut_asymmetrical(df_alleles, cut_point, plot_left, plot_right) 122 | this_allele_count = len(df_alleles_around_cut.index) 123 | if this_allele_count < 1: 124 | print('No reads found for ' + ref_name) 125 | continue 126 | this_reads_count = df_alleles_around_cut['#Reads'].sum() 127 | print('Plotting ' + str(this_reads_count) + ' reads for ' + ref_name) 128 | 129 | new_sgRNA_intervals = [] 130 | #adjust coordinates of sgRNAs 131 | new_sel_cols_start = cut_point - plot_left 132 | for (int_start, int_end) in refs[ref_name]['sgRNA_intervals']: 133 | new_sgRNA_intervals += [(int_start - new_sel_cols_start - 1,int_end - new_sel_cols_start - 1)] 134 | 135 | fig_filename_root = fig_filename_root+"_"+ref_name+"_"+sgRNA_label 136 | CRISPRessoPlot.plot_alleles_table(ref_seq_around_cut, 137 | df_alleles=df_alleles_around_cut, 138 | fig_filename_root=fig_filename_root, 139 | cut_point_ind=cut_point-new_sel_cols_start, 140 | custom_colors=custom_colors, 141 | MIN_FREQUENCY=MIN_FREQUENCY, 142 | MAX_N_ROWS=MAX_N_ROWS, 143 | SAVE_ALSO_PNG=SAVE_ALSO_PNG, 144 | plot_cut_point=plot_cut_point, 145 | sgRNA_intervals=new_sgRNA_intervals, 146 | sgRNA_names=sgRNA_names, 147 | sgRNA_mismatches=sgRNA_mismatches, 148 | annotate_wildtype_allele=crispresso2_info['running_info']['args'].annotate_wildtype_allele) 149 | 150 | plot_count += 1 151 | else: 152 | for ind,sgRNA in enumerate(sgRNA_sequences): 153 | sgRNA_label = sgRNA # for file names 154 | if sgRNA_names[ind] != "": 155 | sgRNA_label = sgRNA_names[ind] 156 | 157 | cut_point = sgRNA_cut_points[ind] 158 | plot_cut_point = sgRNA_plot_cut_points[ind] 159 | plot_idxs = sgRNA_plot_idxs[ind] 160 | ref_seq_around_cut=refs[ref_name]['sequence'][cut_point-plot_left+1:cut_point+plot_right+1] 161 | 162 | df_alleles_around_cut=get_dataframe_around_cut_asymmetrical(df_alleles, cut_point, plot_left, plot_right) 163 | this_allele_count = len(df_alleles_around_cut.index) 164 | if this_allele_count < 1: 165 | print('No reads found for ' + ref_name) 166 | continue 167 | this_reads_count = df_alleles_around_cut['#Reads'].sum() 168 | print('Plotting ' + str(this_reads_count) + ' reads for ' + ref_name) 169 | 170 | new_sgRNA_intervals = [] 171 | #adjust coordinates of sgRNAs 172 | new_sel_cols_start = cut_point - plot_left 173 | for (int_start, int_end) in refs[ref_name]['sgRNA_intervals']: 174 | new_sgRNA_intervals += [(int_start - new_sel_cols_start - 1,int_end - new_sel_cols_start - 1)] 175 | 176 | fig_filename_root = fig_filename_root+"_"+ref_name+"_"+sgRNA_label 177 | CRISPRessoPlot.plot_alleles_table(ref_seq_around_cut, 178 | df_alleles=df_alleles_around_cut, 179 | fig_filename_root=fig_filename_root, 180 | cut_point_ind=cut_point-new_sel_cols_start, 181 | custom_colors=custom_colors, 182 | MIN_FREQUENCY=MIN_FREQUENCY, 183 | MAX_N_ROWS=MAX_N_ROWS, 184 | SAVE_ALSO_PNG=SAVE_ALSO_PNG, 185 | plot_cut_point=plot_cut_point, 186 | sgRNA_intervals=new_sgRNA_intervals, 187 | sgRNA_names=sgRNA_names, 188 | sgRNA_mismatches=sgRNA_mismatches, 189 | annotate_wildtype_allele=crispresso2_info['running_info']['args'].annotate_wildtype_allele) 190 | 191 | plot_count += 1 192 | print('Plotted ' + str(plot_count) + ' plots') 193 | 194 | if __name__ == "__main__": 195 | # execute only if run as a script 196 | main() 197 | 198 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [global] 2 | zip_ok = False 3 | no-use-wheel = true 4 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Description: 3 | Setup script for CRISPResso2 -- Software pipeline for the analysis of genome editing outcomes from deep sequencing data 4 | @status: beta 5 | @version: $Revision$ 6 | @author: edilytics 7 | @contact: contact@edilytics.com 8 | 9 | CRISPResso2 - Kendell Clement and Luca Pinello 2020 10 | Software pipeline for the analysis of genome editing outcomes from deep sequencing data 11 | (c) 2020 The General Hospital Corporation. All Rights Reserved. 12 | """ 13 | 14 | from setuptools import setup, Extension 15 | from io import open 16 | 17 | # Use build_ext from Cython if found 18 | command_classes = {} 19 | try: 20 | import Cython.Distutils 21 | command_classes['build_ext'] = Cython.Distutils.build_ext 22 | has_cython = True 23 | except: 24 | has_cython = False 25 | 26 | ext = '.pyx' if has_cython else '.c' 27 | 28 | from numpy import get_include as numpy_get_include 29 | numpy_include_dir = [numpy_get_include()] 30 | 31 | import sys 32 | import re 33 | 34 | def main(): 35 | version = re.search( 36 | r'^__version__\s*=\s*"(.*)"', 37 | open('CRISPResso2/CRISPRessoShared.py').read(), 38 | re.M 39 | ).group(1) 40 | 41 | ext_modules = [ 42 | Extension("CRISPResso2.CRISPRessoCOREResources", ["CRISPResso2/CRISPRessoCOREResources" + ext], include_dirs=numpy_include_dir, extra_compile_args=['-w','-Ofast'] ), 43 | Extension("CRISPResso2.CRISPResso2Align", ["CRISPResso2/CRISPResso2Align" + ext], include_dirs=numpy_include_dir, extra_compile_args=['-w','-Ofast'] ), 44 | ] 45 | if has_cython: 46 | from Cython.Build import cythonize 47 | ext_modules = cythonize(ext_modules, language_level="3") 48 | 49 | 50 | call_root = "CRISPResso" 51 | if "--no_clash_crispresso1" in sys.argv: 52 | sys.argv.remove("--no_clash_crispresso1") 53 | call_root = "CRISPResso2" 54 | 55 | entry_points = { 56 | "console_scripts": [call_root+' = CRISPResso2.CRISPRessoCORE:main', 57 | call_root+'Batch = CRISPResso2.CRISPRessoBatchCORE:main', 58 | call_root+'Pooled = CRISPResso2.CRISPRessoPooledCORE:main', 59 | call_root+'WGS = CRISPResso2.CRISPRessoWGSCORE:main', 60 | call_root+'Compare = CRISPResso2.CRISPRessoCompareCORE:main', 61 | call_root+'PooledWGSCompare = CRISPResso2.CRISPRessoPooledWGSCompareCORE:main', 62 | call_root+'Aggregate = CRISPResso2.CRISPRessoAggregateCORE:main', 63 | ] 64 | } 65 | 66 | setup(name="CRISPResso2", 67 | version=version, 68 | author='Edilytics, Inc.', 69 | author_email='support@edilytics.com', 70 | url='http://github.com/pinellolab/CRISPResso2', 71 | package_dir={'CRISPResso2' : 'CRISPResso2'}, 72 | include_package_data = True, 73 | packages=['CRISPResso2', 'CRISPResso2.CRISPRessoReports'], 74 | entry_points=entry_points, 75 | description="Software pipeline for the analysis of genome editing outcomes from deep sequencing data", 76 | classifiers=[ 77 | 'Development Status :: 4 - Beta', 78 | 'Environment :: Console', 79 | 'Intended Audience :: Developers', 80 | 'Intended Audience :: Science/Research', 81 | 'License :: Other/Proprietary License', 82 | 'Operating System :: POSIX', 83 | 'Topic :: Scientific/Engineering :: Bio-Informatics', 84 | 'Programming Language :: Python :: 3 :: Only', 85 | 'Programming Language :: Cython', 86 | ], 87 | install_requires=[ 88 | 'pandas', # '>=0.15,<=0.24', 89 | 'matplotlib', # '>=1.3.1,<=2.2.3', 90 | 'seaborn', # '>0.7.1,<0.10', 91 | 'jinja2', 92 | 'scipy', 93 | 'numpy', 94 | ], 95 | cmdclass = command_classes, 96 | ext_modules = ext_modules 97 | ) 98 | 99 | if __name__ == '__main__': 100 | main() 101 | -------------------------------------------------------------------------------- /tests/Both.Cas9.fastq.hg38.bam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/tests/Both.Cas9.fastq.hg38.bam -------------------------------------------------------------------------------- /tests/Both.Cas9.fastq.hg38.bam.bai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/tests/Both.Cas9.fastq.hg38.bam.bai -------------------------------------------------------------------------------- /tests/Both.Cas9.fastq.smallGenome.bam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/tests/Both.Cas9.fastq.smallGenome.bam -------------------------------------------------------------------------------- /tests/Both.Cas9.fastq.smallGenome.bam.bai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/tests/Both.Cas9.fastq.smallGenome.bam.bai -------------------------------------------------------------------------------- /tests/Cas9.amplicons.txt: -------------------------------------------------------------------------------- 1 | FANC CGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCGGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG GGAATCCCTTCTGCAGCACC NA NA 2 | HEK3 GGAAACGCCCATGCAATTAGTCTATTTCTGCTGCAAGTAAGCATGCATTTGTAGGCTTGATGCTTTTTTTCTGCTTCTCCAGCCCTGGCCTGGGTCAATCCTTGGGGCCCAGACTGAGCACGTGATGGCAGAGGAAAGGAAGCCCTGCTTCCTCCAGAGGGCGTCGCAGGACAGCTTTTCCTAGACAGGGGCTAGTATGTGCAGCTCCTGCACCGGGATACTGGTTGACAAG GGCCCAGACTGAGCACGTGA NA NA 3 | -------------------------------------------------------------------------------- /tests/Cas9.regions.txt: -------------------------------------------------------------------------------- 1 | chr9 962 1198 HEK3 2 | chr11 1024 1274 FANCF 3 | -------------------------------------------------------------------------------- /tests/FANC.batch: -------------------------------------------------------------------------------- 1 | n r1 2 | Untreated tests/FANC.Untreated.fastq 3 | Cas9 tests/FANC.Cas9.fastq 4 | -------------------------------------------------------------------------------- /tests/FANC.local.batch: -------------------------------------------------------------------------------- 1 | n r1 2 | Untreated FANC.Untreated.fastq 3 | Cas9 FANC.Cas9.fastq 4 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all install test 2 | 3 | SOURCES := $(wildcard ../CRISPResso2/*.py*) 4 | 5 | all: install 6 | 7 | install: $(SOURCES) 8 | cd .. && pip install -e . 9 | 10 | test: CRISPResso_on_FANC.Cas9 CRISPResso_on_params CRISPRessoBatch_on_FANC \ 11 | CRISPRessoPooled_on_Both.Cas9 CRISPRessoWGS_on_Both.Cas9.fastq.smallGenome \ 12 | CRISPRessoCompare_on_Cas9_VS_Untreated 13 | 14 | clean: 15 | rm -rf CRISPResso_on_FANC.Cas9* CRISPResso_on_params* CRISPRessoBatch_on_FANC* \ 16 | CRISPRessoPooled_on_Both.Cas9* CRISPRessoWGS_on_Both.Cas9.fastq.smallGenome* \ 17 | CRISPRessoCompare_on_Cas9_VS_Untreated* 18 | 19 | CRISPResso_on_FANC.Cas9: install 20 | time CRISPResso -r1 FANC.Cas9.fastq -a CGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCGGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -g GGAATCCCTTCTGCAGCACC --debug 21 | 22 | CRISPResso_on_params: install 23 | time CRISPResso -r1 FANC.Cas9.fastq -a CGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCGGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -g GGAATCCCTTCTGCAGCACC -e CGGCCGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCTGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -c GGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTT --dump -qwc 20-30_45-50 -q 30 --default_min_aln_score 80 -an FANC -n params --base_edit -fg AGCCTTGCAGTGGGCGCGCTA,CCCACTGAAGGCCC --dsODN GCTAGATTTCCCAAGAAGA -gn hi -fgn dear --debug 24 | 25 | CRISPRessoBatch_on_FANC: install 26 | time CRISPRessoBatch -bs FANC.batch -a CGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCGGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -g GGAATCCCTTCTGCAGCACC --debug --base_editor 27 | 28 | CRISPRessoPooled_on_Both.Cas9: install 29 | time CRISPRessoPooled -r1 Both.Cas9.fastq -f Cas9.amplicons.txt --keep_intermediate --min_reads_to_use_region 100 -p 4 --debug 30 | 31 | CRISPRessoWGS_on_Both.Cas9.fastq.smallGenome: install 32 | time CRISPRessoWGS -b Both.Cas9.fastq.smallGenome.bam -r smallGenome/smallGenome.fa -f Cas9.regions.txt --debug 33 | 34 | CRISPRessoCompare_on_Cas9_VS_Untreated: install 35 | time CRISPRessoCompare CRISPRessoBatch_on_FANC/CRISPResso_on_Cas9/ CRISPRessoBatch_on_FANC/CRISPResso_on_Untreated/ --debug 36 | -------------------------------------------------------------------------------- /tests/expectedResults/CRISPRessoBatch_on_FANC/MODIFICATION_FREQUENCY_SUMMARY.txt: -------------------------------------------------------------------------------- 1 | Batch Modification C G G A T G T T C C A A T C A G T A C G C A G A G A G T C G C C G T C T C C A A G G T G A A A G C G G A A G T A G G G C C T T C G C G C A C C T C A T G G A A T C C C T T C T G C A G C A C C T G G A T C G C T T T T C C G A G C T T C T G G C G G T C T C A A G C A C T A C C T A C G T C A G C A C C T G G G A C C C C G C C A C C G T G C G C C G G G C C T T G C A G T G G G C G C G C T A C C T G C G C C A C A T C C A T C G G C G C T T T G G T C G G 2 | Untreated Insertions 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3 | Untreated Insertions_Left 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 4 | Untreated Deletions 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 5 | Untreated Substitutions 0.0 0.0 0.0 1.0 0.0 0.0 2.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 3.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 2.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3.0 0.0 1.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 1.0 0.0 6 | Untreated All_modifications 1.0 1.0 0.0 1.0 0.0 0.0 2.0 0.0 1.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 3.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 2.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3.0 0.0 1.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 3.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2.0 0.0 0.0 1.0 0.0 7 | Cas9 Insertions 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8.0 8.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8 | Cas9 Insertions_Left 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 9 | Cas9 Deletions 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 2.0 4.0 5.0 6.0 6.0 6.0 7.0 7.0 8.0 10.0 12.0 12.0 13.0 13.0 15.0 17.0 23.0 25.0 35.0 34.0 44.0 33.0 30.0 29.0 25.0 19.0 16.0 15.0 13.0 13.0 13.0 9.0 8.0 6.0 5.0 5.0 3.0 3.0 3.0 3.0 3.0 2.0 1.0 1.0 2.0 2.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 2.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 2.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 10 | Cas9 Substitutions 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 2.0 6.0 4.0 5.0 0.0 3.0 0.0 1.0 2.0 0.0 2.0 3.0 1.0 2.0 2.0 0.0 2.0 1.0 1.0 1.0 1.0 1.0 2.0 1.0 0.0 3.0 2.0 2.0 0.0 1.0 1.0 3.0 2.0 1.0 2.0 4.0 1.0 2.0 2.0 1.0 1.0 1.0 0.0 2.0 2.0 1.0 0.0 1.0 0.0 1.0 2.0 1.0 2.0 2.0 1.0 1.0 1.0 2.0 2.0 3.0 3.0 5.0 2.0 2.0 2.0 0.0 1.0 2.0 2.0 4.0 4.0 2.0 1.0 0.0 2.0 3.0 2.0 1.0 1.0 2.0 3.0 5.0 4.0 2.0 2.0 3.0 1.0 1.0 2.0 2.0 5.0 3.0 3.0 2.0 5.0 1.0 2.0 3.0 1.0 1.0 2.0 6.0 1.0 2.0 1.0 3.0 1.0 2.0 1.0 1.0 3.0 1.0 4.0 2.0 1.0 2.0 2.0 1.0 3.0 3.0 4.0 2.0 3.0 1.0 1.0 3.0 2.0 3.0 3.0 8.0 1.0 3.0 2.0 11 | Cas9 All_modifications 2.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 2.0 1.0 1.0 1.0 2.0 3.0 4.0 5.0 6.0 6.0 6.0 7.0 7.0 8.0 11.0 12.0 12.0 13.0 14.0 15.0 17.0 24.0 25.0 37.0 48.0 56.0 38.0 30.0 32.0 25.0 20.0 18.0 15.0 15.0 16.0 15.0 12.0 10.0 6.0 7.0 6.0 4.0 4.0 4.0 4.0 5.0 3.0 1.0 4.0 4.0 4.0 1.0 2.0 2.0 4.0 3.0 2.0 2.0 4.0 2.0 3.0 2.0 1.0 1.0 1.0 1.0 3.0 3.0 2.0 2.0 2.0 1.0 1.0 2.0 1.0 2.0 2.0 2.0 2.0 1.0 2.0 2.0 3.0 3.0 5.0 2.0 2.0 2.0 0.0 1.0 2.0 2.0 4.0 4.0 3.0 2.0 1.0 2.0 3.0 3.0 2.0 1.0 2.0 3.0 5.0 4.0 3.0 3.0 3.0 1.0 2.0 2.0 2.0 5.0 3.0 3.0 2.0 5.0 1.0 2.0 3.0 1.0 1.0 2.0 7.0 2.0 3.0 2.0 4.0 2.0 4.0 2.0 2.0 4.0 2.0 5.0 3.0 2.0 3.0 3.0 2.0 4.0 4.0 6.0 4.0 4.0 2.0 2.0 4.0 3.0 4.0 4.0 9.0 2.0 4.0 2.0 12 | -------------------------------------------------------------------------------- /tests/expectedResults/CRISPRessoCompare_on_Cas9_VS_Untreated/Alleles_frequency_table_around_sgRNA_GGAATCCCTTCTGCAGCACC.txt: -------------------------------------------------------------------------------- 1 | index Reference_Sequence Unedited n_deleted n_inserted n_mutated #Reads_Cas9 %Reads_Cas9 #Reads_Untreated %Reads_Untreated each_LFC 2 | 0 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG True 0 0 0 170.0 72.34042553191485 241.0 97.57085020242958 -0.4311330340580488 3 | 1 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 3 0 0 9.0 3.829787234042554 0.0 0.0 5.296379299304801 4 | 2 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 9 0 0 4.0 1.702127659574468 0.0 0.0 4.171629307654562 5 | 3 CATGGAATCCCTTCTGCAGC-ACCTGGATCGCTTTTCCGA False 0 1 0 3.0 1.2765957446808511 0.0 0.0 3.78303305031487 6 | 4 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 11 0 0 2.0 0.851063829787234 0.0 0.0 3.2495421695056805 7 | 5 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 6 0 0 2.0 0.851063829787234 0.0 0.0 3.2495421695056805 8 | 6 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 12 0 0 2.0 0.851063829787234 0.0 0.0 3.2495421695056805 9 | 7 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 4 0 0 2.0 0.851063829787234 0.0 0.0 3.2495421695056805 10 | 8 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 2 0 0 2.0 0.851063829787234 0.0 0.0 3.2495421695056805 11 | 9 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 32 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 12 | 10 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 3 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 13 | 11 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 8 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 14 | 12 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 7 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 15 | 13 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 5 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 16 | 14 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 5 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 17 | 15 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 1 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 18 | 16 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 16 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 19 | 17 CATGGAATCCCTTCTGCAGC-ACCTGGATCGCTTTTCCGA False 0 1 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 20 | 18 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG True 0 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 21 | 19 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG True 0 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 22 | 20 CATGGAATCCCTTCTGCAGC-------------------- False 0 54 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 23 | 21 CATGGAATCCCTTCTGCAGC-ACCTGGATCGCTTTTCCGA False 0 1 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 24 | 22 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 0 0 1 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 25 | 23 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 0 0 2 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 26 | 24 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 0 0 2 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 27 | 25 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 14 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 28 | 26 CATGGAATCCCTTCTGCAGC-------------------- False 0 22 1 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 29 | 27 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 21 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 30 | 28 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 21 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 31 | 29 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 21 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 32 | 30 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 19 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 33 | 31 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 25 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 34 | 32 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 23 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 35 | 33 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 34 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 36 | 34 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 43 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 37 | 35 CATGGAATCCCTTCTGCAGCACCTGGATCGC----TTTTC False 0 0 1 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 38 | 36 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 13 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 39 | 37 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 22 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 40 | 38 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 40 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 41 | 39 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 6 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 42 | 40 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 5 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 43 | 41 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG True 0 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 44 | 42 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 14 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 45 | 43 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 5 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 46 | 44 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 2 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 47 | 45 CATGGAATCCCTTCTGCAGC------------ACCTGGAT False 0 12 2 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 48 | 46 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 0 0 1 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 49 | 47 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG False 21 0 0 1.0 0.425531914893617 0.0 0.0 2.3937783799070402 50 | 48 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG True 0 0 0 0.0 0.0 1.0 0.4048582995951417 -2.3358785182449924 51 | 49 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG True 0 0 0 0.0 0.0 1.0 0.4048582995951417 -2.3358785182449924 52 | 50 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG True 0 0 0 0.0 0.0 1.0 0.4048582995951417 -2.3358785182449924 53 | 51 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG True 0 0 0 0.0 0.0 1.0 0.4048582995951417 -2.3358785182449924 54 | 52 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG True 0 0 0 0.0 0.0 1.0 0.4048582995951417 -2.3358785182449924 55 | 53 CATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAG True 0 0 0 0.0 0.0 1.0 0.4048582995951417 -2.3358785182449924 56 | -------------------------------------------------------------------------------- /tests/expectedResults/CRISPRessoPooled_on_Both.Cas9/SAMPLES_QUANTIFICATION_SUMMARY.txt: -------------------------------------------------------------------------------- 1 | Name Unmodified% Modified% Reads_total Reads_aligned Unmodified Modified Discarded Insertions Deletions Substitutions Only Insertions Only Deletions Only Substitutions Insertions and Deletions Insertions and Substitutions Deletions and Substitutions Insertions Deletions and Substitutions 2 | FANC 73.61702128 26.38297872 242 235 173 62 0 8 49 7 6 49 5 0 2 0 0 3 | HEK3 65.57377049 34.42622951 250 244 160 84 0 18 65 5 15 64 1 0 3 1 0 4 | -------------------------------------------------------------------------------- /tests/expectedResults/CRISPRessoWGS_on_Both.Cas9.fastq.smallGenome/SAMPLES_QUANTIFICATION_SUMMARY.txt: -------------------------------------------------------------------------------- 1 | Name Unmodified% Modified% Reads_total Reads_aligned Unmodified Modified Discarded Insertions Deletions Substitutions Only Insertions Only Deletions Only Substitutions Insertions and Deletions Insertions and Substitutions Deletions and Substitutions Insertions Deletions and Substitutions 2 | HEK3 NA NA 2 NA NA NA NA NA NA NA NA NA NA NA NA NA NA 3 | FANCF 73.91304348 26.08695652 23 23.0 17.0 6.0 0.0 0.0 5.0 1.0 0.0 5.0 1.0 0.0 0.0 0.0 0.0 4 | -------------------------------------------------------------------------------- /tests/expectedResults/CRISPResso_on_FANC.Cas9/CRISPResso_quantification_of_editing_frequency.txt: -------------------------------------------------------------------------------- 1 | Amplicon Unmodified% Modified% Reads_in_input Reads_aligned_all_amplicons Reads_aligned Unmodified Modified Discarded Insertions Deletions Substitutions Only Insertions Only Deletions Only Substitutions Insertions and Deletions Insertions and Substitutions Deletions and Substitutions Insertions Deletions and Substitutions 2 | Reference 73.61702128 26.38297872 250 235 235 173 62 0 8 49 7 6 49 5 0 2 0 0 3 | -------------------------------------------------------------------------------- /tests/expectedResults/CRISPResso_on_FANC.Cas9/Nucleotide_frequency_table.txt: -------------------------------------------------------------------------------- 1 | C G G A T G T T C C A A T C A G T A C G C A G A G A G T C G C C G T C T C C A A G G T G A A A G C G G A A G T A G G G C C T T C G C G C A C C T C A T G G A A T C C C T T C T G C A G C A C C T G G A T C G C T T T T C C G A G C T T C T G G C G G T C T C A A G C A C T A C C T A C G T C A G C A C C T G G G A C C C C G C C A C C G T G C G C C G G G C C T T G C A G T G G G C G C G C T A C C T G C G C C A C A T C C A T C G G C G C T T T G G T C G G 2 | A 0.0 0.0 0.0 235.0 0.0 0.0 0.0 0.0 0.0 0.0 235.0 235.0 0.0 0.0 235.0 0.0 0.0 235.0 0.0 1.0 0.0 235.0 0.0 235.0 0.0 234.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 235.0 235.0 0.0 0.0 0.0 0.0 235.0 235.0 235.0 0.0 0.0 0.0 0.0 235.0 235.0 0.0 0.0 235.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 234.0 0.0 0.0 0.0 0.0 231.0 0.0 0.0 0.0 229.0 228.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 210.0 1.0 3.0 187.0 0.0 0.0 0.0 0.0 0.0 217.0 0.0 0.0 3.0 0.0 1.0 0.0 0.0 2.0 0.0 0.0 0.0 231.0 1.0 2.0 0.0 0.0 3.0 0.0 2.0 0.0 0.0 1.0 1.0 2.0 0.0 1.0 1.0 234.0 233.0 0.0 1.0 234.0 0.0 0.0 232.0 1.0 1.0 0.0 233.0 0.0 0.0 1.0 0.0 233.0 0.0 1.0 234.0 0.0 0.0 0.0 0.0 1.0 2.0 233.0 0.0 1.0 0.0 0.0 0.0 1.0 1.0 231.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 2.0 1.0 2.0 1.0 1.0 2.0 2.0 1.0 0.0 2.0 233.0 3.0 2.0 1.0 2.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 228.0 1.0 0.0 0.0 1.0 0.0 0.0 1.0 1.0 231.0 0.0 230.0 1.0 0.0 0.0 232.0 0.0 0.0 1.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 2.0 0.0 1.0 0.0 3 | C 233.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 235.0 235.0 0.0 0.0 0.0 235.0 0.0 0.0 0.0 0.0 235.0 0.0 235.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 234.0 0.0 235.0 235.0 0.0 0.0 235.0 0.0 235.0 235.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 235.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 234.0 234.0 0.0 0.0 234.0 0.0 234.0 0.0 233.0 0.0 234.0 234.0 1.0 232.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 227.0 224.0 223.0 0.0 0.0 221.0 0.0 0.0 211.0 0.0 0.0 195.0 0.0 197.0 205.0 0.0 0.0 0.0 0.0 0.0 220.0 0.0 221.0 1.0 0.0 0.0 0.0 229.0 231.0 0.0 0.0 0.0 230.0 0.0 0.0 231.0 1.0 0.0 0.0 233.0 0.0 2.0 0.0 233.0 0.0 231.0 1.0 0.0 2.0 234.0 0.0 234.0 0.0 2.0 232.0 233.0 0.0 0.0 234.0 0.0 0.0 234.0 1.0 1.0 234.0 1.0 234.0 233.0 2.0 2.0 1.0 1.0 0.0 233.0 233.0 235.0 234.0 1.0 233.0 231.0 1.0 233.0 234.0 0.0 2.0 1.0 233.0 1.0 234.0 233.0 1.0 2.0 2.0 233.0 233.0 1.0 0.0 0.0 233.0 1.0 0.0 0.0 1.0 0.0 2.0 234.0 1.0 232.0 0.0 234.0 2.0 4.0 233.0 232.0 1.0 1.0 233.0 2.0 233.0 233.0 1.0 233.0 3.0 1.0 233.0 232.0 2.0 1.0 231.0 2.0 4.0 232.0 3.0 233.0 1.0 3.0 2.0 0.0 1.0 4.0 233.0 1.0 2.0 4 | G 0.0 235.0 235.0 0.0 0.0 235.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 235.0 0.0 0.0 0.0 234.0 0.0 0.0 235.0 0.0 235.0 0.0 235.0 0.0 0.0 235.0 0.0 0.0 234.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 234.0 235.0 0.0 235.0 0.0 0.0 0.0 235.0 0.0 234.0 235.0 0.0 0.0 235.0 0.0 0.0 235.0 235.0 234.0 0.0 0.0 0.0 0.0 0.0 234.0 0.0 234.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 229.0 229.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 218.0 1.0 0.0 198.0 1.0 1.0 3.0 0.0 3.0 210.0 215.0 2.0 0.0 0.0 219.0 1.0 0.0 2.0 0.0 0.0 1.0 0.0 231.0 1.0 231.0 0.0 1.0 0.0 0.0 1.0 231.0 234.0 1.0 233.0 231.0 0.0 1.0 1.0 0.0 0.0 0.0 233.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 234.0 1.0 0.0 0.0 233.0 0.0 0.0 0.0 0.0 0.0 232.0 232.0 230.0 0.0 1.0 1.0 0.0 1.0 233.0 0.0 1.0 1.0 0.0 0.0 234.0 0.0 232.0 0.0 234.0 0.0 0.0 232.0 230.0 231.0 0.0 0.0 0.0 0.0 233.0 0.0 0.0 230.0 1.0 232.0 233.0 230.0 0.0 233.0 1.0 234.0 1.0 0.0 0.0 0.0 1.0 0.0 231.0 0.0 231.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 0.0 231.0 230.0 0.0 231.0 1.0 0.0 0.0 0.0 231.0 231.0 2.0 1.0 231.0 232.0 5 | T 2.0 0.0 0.0 0.0 235.0 0.0 235.0 235.0 0.0 0.0 0.0 0.0 235.0 0.0 0.0 0.0 235.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 235.0 1.0 0.0 0.0 0.0 0.0 235.0 0.0 235.0 0.0 0.0 0.0 0.0 1.0 0.0 235.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 235.0 0.0 0.0 0.0 0.0 0.0 0.0 234.0 234.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 233.0 1.0 0.0 230.0 0.0 0.0 0.0 0.0 228.0 0.0 0.0 0.0 223.0 222.0 0.0 220.0 0.0 0.0 0.0 1.0 2.0 3.0 2.0 0.0 203.0 0.0 1.0 0.0 220.0 2.0 0.0 0.0 224.0 225.0 229.0 228.0 0.0 1.0 1.0 0.0 0.0 0.0 232.0 234.0 0.0 231.0 0.0 0.0 0.0 0.0 0.0 232.0 0.0 233.0 3.0 0.0 2.0 0.0 0.0 1.0 0.0 234.0 0.0 1.0 0.0 233.0 0.0 0.0 1.0 233.0 1.0 1.0 1.0 0.0 0.0 1.0 2.0 233.0 1.0 1.0 2.0 2.0 1.0 0.0 0.0 0.0 1.0 1.0 2.0 2.0 2.0 1.0 0.0 233.0 1.0 2.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 0.0 232.0 234.0 1.0 0.0 1.0 2.0 232.0 1.0 0.0 2.0 0.0 0.0 1.0 0.0 0.0 233.0 2.0 0.0 1.0 233.0 1.0 1.0 0.0 0.0 0.0 2.0 1.0 0.0 232.0 1.0 1.0 0.0 233.0 3.0 0.0 0.0 1.0 0.0 0.0 233.0 231.0 232.0 2.0 2.0 226.0 0.0 1.0 0.0 6 | N 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7 | - 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 2.0 4.0 5.0 6.0 6.0 6.0 7.0 7.0 8.0 10.0 12.0 12.0 13.0 13.0 15.0 17.0 23.0 25.0 35.0 34.0 44.0 33.0 30.0 29.0 25.0 19.0 16.0 15.0 13.0 13.0 13.0 9.0 8.0 6.0 5.0 5.0 3.0 3.0 3.0 3.0 3.0 2.0 1.0 1.0 2.0 2.0 1.0 1.0 1.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 2.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 1.0 1.0 1.0 2.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 8 | -------------------------------------------------------------------------------- /tests/expectedResults/CRISPResso_on_params/CRISPResso_quantification_of_editing_frequency.txt: -------------------------------------------------------------------------------- 1 | Amplicon Unmodified% Modified% Reads_in_input Reads_aligned_all_amplicons Reads_aligned Unmodified Modified Discarded Insertions Deletions Substitutions Only Insertions Only Deletions Only Substitutions Insertions and Deletions Insertions and Substitutions Deletions and Substitutions Insertions Deletions and Substitutions 2 | FANC 100.0 0.0 250 208 192 192 0 0 0 0 0 0 0 0 0 0 0 0 3 | HDR 6.25 93.75 250 208 16 1 15 0 0 0 15 0 0 15 0 0 0 0 4 | -------------------------------------------------------------------------------- /tests/expectedResults/CRISPResso_on_params/FANC.Nucleotide_frequency_table.txt: -------------------------------------------------------------------------------- 1 | C G G A T G T T C C A A T C A G T A C G C A G A G A G T C G C C G T C T C C A A G G T G A A A G C G G A A G T A G G G C C T T C G C G C A C C T C A T G G A A T C C C T T C T G C A G C A C C T G G A T C G C T T T T C C G A G C T T C T G G C G G T C T C A A G C A C T A C C T A C G T C A G C A C C T G G G A C C C C G C C A C C G T G C G C C G G G C C T T G C A G T G G G C G C G C T A C C T G C G C C A C A T C C A T C G G C G C T T T G G T C G G 2 | A 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 192.0 0.0 0.0 192.0 0.0 1.0 0.0 192.0 0.0 192.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 0.0 0.0 192.0 192.0 192.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 186.0 0.0 3.0 178.0 0.0 0.0 0.0 0.0 0.0 191.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 191.0 0.0 0.0 192.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 1.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 191.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 191.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 3 | C 191.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 192.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 192.0 192.0 0.0 0.0 192.0 0.0 192.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 192.0 0.0 192.0 0.0 191.0 0.0 192.0 192.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 191.0 191.0 0.0 0.0 191.0 0.0 0.0 186.0 0.0 0.0 175.0 0.0 183.0 188.0 0.0 0.0 0.0 0.0 0.0 191.0 0.0 192.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 0.0 192.0 0.0 0.0 192.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 192.0 0.0 191.0 0.0 0.0 1.0 192.0 0.0 192.0 0.0 0.0 191.0 192.0 0.0 0.0 192.0 0.0 0.0 191.0 0.0 0.0 192.0 0.0 192.0 192.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 192.0 192.0 0.0 192.0 192.0 0.0 192.0 192.0 0.0 0.0 0.0 192.0 0.0 192.0 192.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 191.0 0.0 192.0 0.0 1.0 192.0 191.0 0.0 0.0 192.0 0.0 192.0 192.0 0.0 192.0 1.0 0.0 192.0 192.0 0.0 1.0 191.0 0.0 1.0 192.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 1.0 192.0 0.0 0.0 4 | G 0.0 192.0 192.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 191.0 0.0 0.0 192.0 0.0 192.0 0.0 192.0 0.0 0.0 192.0 0.0 0.0 191.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 191.0 192.0 0.0 192.0 0.0 0.0 0.0 192.0 0.0 192.0 192.0 0.0 0.0 192.0 0.0 0.0 192.0 192.0 192.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 189.0 1.0 0.0 176.0 0.0 0.0 2.0 0.0 0.0 190.0 190.0 0.0 0.0 0.0 191.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 192.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 191.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 190.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 192.0 0.0 192.0 0.0 0.0 192.0 192.0 192.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 191.0 0.0 192.0 192.0 191.0 0.0 192.0 1.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 191.0 0.0 192.0 0.0 0.0 0.0 0.0 192.0 191.0 1.0 0.0 192.0 192.0 5 | T 1.0 0.0 0.0 0.0 192.0 0.0 192.0 192.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 192.0 0.0 0.0 0.0 0.0 1.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 192.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 191.0 192.0 0.0 191.0 0.0 0.0 0.0 1.0 0.0 1.0 2.0 0.0 188.0 0.0 1.0 0.0 191.0 1.0 0.0 0.0 192.0 192.0 192.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 192.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 192.0 0.0 1.0 0.0 192.0 0.0 0.0 0.0 192.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 1.0 192.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 192.0 0.0 0.0 0.0 191.0 1.0 0.0 0.0 0.0 0.0 0.0 192.0 192.0 192.0 0.0 1.0 190.0 0.0 0.0 0.0 6 | N 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 7 | - 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 1.0 1.0 0.0 0.0 1.0 3.0 5.0 6.0 15.0 14.0 13.0 5.0 4.0 4.0 2.0 1.0 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 8 | -------------------------------------------------------------------------------- /tests/smallGenome/smallGenome.1.bt2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/tests/smallGenome/smallGenome.1.bt2 -------------------------------------------------------------------------------- /tests/smallGenome/smallGenome.2.bt2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/tests/smallGenome/smallGenome.2.bt2 -------------------------------------------------------------------------------- /tests/smallGenome/smallGenome.3.bt2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/tests/smallGenome/smallGenome.3.bt2 -------------------------------------------------------------------------------- /tests/smallGenome/smallGenome.4.bt2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/tests/smallGenome/smallGenome.4.bt2 -------------------------------------------------------------------------------- /tests/smallGenome/smallGenome.fa: -------------------------------------------------------------------------------- 1 | >chr9 2 | AGGCGGATCACCTGAGGTCAGGAGTTTGAGACCAGCCTGACCAACATGGA 3 | GAAACCCCATCTCTACTAAAAATACAAAATTAGTCGGGCGTGGTGGTGCA 4 | TGCCTGAAATCCCAGCTCCTCGGGAGGCTGAGGCAGGAGAATCGCTTGAA 5 | CCCAGGAGGTGGAGGTTGCAGTGAGCTGAGACTGTGCCACCAGACTCTAG 6 | CCTGGACAACAAGAGTGAAACTCCGTCTCAAAAAATAAAAAAATAAAAGA 7 | AGAAGAAGAAGAAGAAAAGAAAAAGCTTCCAAAGTGGCTCCTGAAATGTC 8 | TGTCACAGGACTCAGCCAGGCAAGGGGGAGGGAGTGAAGGGTGAGGAGGA 9 | AAGAGAGGACATTCAGAACAGGCGAACTGCAGGTGCAAAGGCCCGGAATC 10 | TAGGGAAAGCAGAGTCTGTGGGAGGAACAGCCAGTGTTTCAGGATGGCTA 11 | AAGCAGAGGTTGTGAAGGGCAGGGACGACTTTAGACCTTAGAGGCCCCAG 12 | GCACTGTTATTTTCCAAGGCCCCACCCCCACACTATACCATGCTTATTAA 13 | AATTCACCCACATCACACAGGAAATATGAGTTATATATGGCTACCTAAGG 14 | TTGAGGCCAGTTGCAAAGACAATTGACATGTTACATTTTGTAGACATTTA 15 | ATTACATATTTATCAATTACAACTTGACGGCTTTCTTGTTTTATCAGTTT 16 | TGGAGGATGTACATAAATATATAGAATGAGAGTCTCAAAACTAATCTTGT 17 | AGCTACGCCTGTGATGGGCTAATTGATGAATCAGTGCTGGAGAATGGGTC 18 | ACAGTGGCAAATGAGGCTGGAGAGGCCCGTGAGCTGCTGTCCCAGAGGGC 19 | CTGGGATGTCCTGCAGGGAGCTTGGCATGAGAAACCTTGGAGAGTTTTAA 20 | GCAAGGGCTGATGTGGGCTGCCTAGAAAGGCATGGATGAGAGAAGCCTGG 21 | AGACAGGGATCCCAGGGAAACGCCCATGCAATTAGTCTATTTCTGCTGCA 22 | AGTAAGCATGCATTTGTAGGCTTGATGCTTTTTTTCTGCTTCTCCAGCCC 23 | TGGCCTGGGTCAATCCTTGGGGCCCAGACTGAGCACGTGATGGCAGAGGA 24 | AAGGAAGCCCTGCTTCCTCCAGAGGGCGTCGCAGGACAGCTTTTCCTAGA 25 | CAGGGGCTAGTATGTGCAGCTCCTGCACCGGGATACTGGTTGACAAGTTT 26 | GGCTGGGCTGGAAGCCAGCACCTAGGGAGGTCCCTGGAAGGGGCCAGCCT 27 | CACCAGGAGAGGAGGGACCTGGCCCTTCAGGGTCGAGCTCAACAGAGGAA 28 | AAGATCTCAGGGCACCCAGAGCCCAGTGGCTTTCAGCACCTGCATGAAAA 29 | TCAGAGATCAACCAGATTACCCCATATTGCCCAAGAGAAAACTGAGGCCA 30 | GAAAGTGATGGAGCTTGCCCAGGACCCCAGAGGGTGTTAGAGGCAGGCCA 31 | GAACCAGAGGACAGCTCTGTCCCAGCACTTGCCCTCCTTTAATTAGGTGG 32 | GTGGTCATATCGCAGTGGTCAGAGACATTGCAAACAATAATAATAAATAT 33 | TGAGCACTTGTTACACGCAGGGCACTATGCTAAGCACCTTGTATTTGTTA 34 | TGTCCTTTCATCCTAGCAACTTCTCTGGAAGTGGAGTAATATCTCCCCCA 35 | TGTCCTACATAAGACAATGGATACACTGGAGGGTTAAAGCCATGCCTTGC 36 | CTAAAGTTACACAGCTGTGCTTAACAGCTGGAAAACCCCAAAGGGTCCCT 37 | CTGACTCAGCCCCTGTGTGCTCAGTTTTAATTTTGGGAGGGAAATAACAA 38 | TGCCACCTTATAATACTTTCTAAGAATGAGAATTTTGTTCAGTGAAGTGG 39 | CCTTCTAGAGCTGGAAAATGAATTCATATACTCTTCATATTTTTAACAAG 40 | GATGTCGTAGTTAATTGATCCGTAGCCAGGAAGTTAGATTAACCAGGACA 41 | CTTCTGGCCCCAAGCACTCTAGCTAGTTGATTAATGGAGACATTGCCATG 42 | CCAGCTAAGTGGCTTTGGAGTGCAAAATAGGATGAATTGCTCTTAGCAGA 43 | GACCTAAATCCTAAACTCAAATCCTCACATTTGGGCAGGTGATCAATGCT 44 | TAGGGAGCATCTCCTGCCCAAATGCGAGGATTTGAGAGGGACAGTCGCCT 45 | ATACAGGTTC 46 | >chr11 47 | TTTGGTGAGAACATTGTAATTTTCATTTTGTAAACTATATATTCTATATT 48 | CAAGTAATAACACAGCATTGCCTATACAGAACTGAGGCCTGCGCTGAGAC 49 | CCAAAACTTGTCTTTTCCTAAATGCACCACTACGAAGAGCTAATAAGAGG 50 | TCTGTCCAGATGCTAAGACCAGGTACTTCAAAATCTCCATCCTGCGCTTT 51 | ACAGGTCTCCAGGGCAGTTAGAACTTTATCTTTCAGAGGTGGAGGGGCCT 52 | GACAGAGGCTTTGAAACCTATTGTGCAACTCCTCCCAGGGCACATCTTGG 53 | GACTCAGTTCCAACCCAAATGCCTTTCTGAAGGTCATAGTGCAAACGTTG 54 | ACCCCAGTCTGTTAGCAGACCCAGATAGACAGGAGACAGCGCTGGGTGGC 55 | GGCTAGTCACTAAAGTCAAAAGCCCGGCTGGGAGGGCGCGACAAAAGGCA 56 | GCAAAGACTTCCGAATTCCCCAGAAGCCAGTGGACTAGCACTTGGCTCCC 57 | CTCTCCAGGTGATTTGTGGATGCCGGGTTCCAACTCTTCTTGGGGCCGAC 58 | GAGACAAAGGCGGCTGCAACAGCGCCACCGCTATCACCTTCAGGAAGTTG 59 | TTCTGAGGCAAGCGCTCCCACAGGCTGCTGAGAAACCTGGCGGGACGCTC 60 | CGCTTCGGCCTTCCCCACCTCCTGCAGACGCTCCAGCAGCAGCTCCGCCT 61 | GGGTCTTCATCAGAGAGTCCTCCTGGAGATTTGGGTTCTCTCTATAGCCA 62 | TTGAAGCGCAGCATGTGCACCGCAGACCGCCGGCGGGCAAGGCGGGCCAG 63 | GCTCTCTTGGAGTGTCTCCTCATCGGCGTCCCGGACGCCCGGGCCGGGAA 64 | AGAGTTGCTGCACCAGGTGGTAACGAGCTGCATCCCCGAGGGCCCGGTTC 65 | TCCAGCAGGCGCAGAGAGAGCAGGACGTCACAGTGACCGAGGGCCTGGAA 66 | GTTCGCTAATCCCGGAACTGGACCCCGCCCAAAGCCGCCCTCTTGCCTCC 67 | ACTGGTTGTGCAGCCGCCGCTCCAGAGCCGTGCGAATGGGGCCATGCCGA 68 | CCAAAGCGCCGATGGATGTGGCGCAGGTAGCGCGCCCACTGCAAGGCCCG 69 | GCGCACGGTGGCGGGGTCCCAGGTGCTGACGTAGGTAGTGCTTGAGACCG 70 | CCAGAAGCTCGGAAAAGCGATCCAGGTGCTGCAGAAGGGATTCCATGAGG 71 | TGCGCGAAGGCCCTACTTCCGCTTTCACCTTGGAGACGGCGACTCTCTGC 72 | GTACTGATTGGAACATCCGCGAAATGATACGCCTCTCTGCAATGCTATTG 73 | GTCGAAATGCATGTCAATCTCCCAGCGTCTTTATCCGTGTTCCTTGACTC 74 | TGGGCAACTTAAAAGCCCTAATACTTTTACTTTCGCCACACAAAGAGGTT 75 | CTTCTTAGTGGAGGGAGAGCAGATGTAGGGCATCCTACCGAGAATTTCCG 76 | GAACCACGTGCGAGATGATGCCAGTCATGAACGTCTCCGCGCTTCCTTTC 77 | GCTTTGGAAATATCCTTAAGTAGAAATTTTCTGAGCTTTGCCTAAAACTA 78 | GAATCTGTGTTGAGGTTTTTCAAAATTAAGTAACGCCAGAGACATACTGT 79 | GACGTGAGGAAACGCTCTTAAATGAAATTTTAAGATCTATTTGAGAAACA 80 | TGTACTAAAAATGTACTGACCTCCTATTAATGCCAGGCGCTATGCTGAAT 81 | TCTGGGCCTTCACATTGTCCTTCCATTATTAGAACTGAAGCCCAGATTAT 82 | TTGAAACAAAAAATAAACTTCAATAATTTATTAAAATTTGCAAAGGAACA 83 | AAATTTTACTTCACAATTGTACATTTCGTTTTCGTAATTTTTAGGACAAA 84 | ATAGCTTAATTGACTCTTCTGTCATACAAATAATCAGCTGAAGGAAATGG 85 | CATTTAAGAGCATCGAACAATAATAAATGTTTGATTAAATAAAAACCGTG 86 | ACAAGAGAGTAGGGAGGAGAAGGTCCTATGTCGCTCACTGATGCACTTAA 87 | CAAACATTTGTCAACTCCTAGGAGTTGCATTCTGTACAAAATGCACAACA 88 | ATTCTTACTTAAGTTCATAATATAGTAATTCATTTGAGCTGAATTTCCTT 89 | CCAGTCCTAAAGACACAGCCAAAACTATTCGAAAAGTGGGGGAAGGTGTT 90 | TTGTTTTGTACTTTAACAAAAAGGGGAAGAGAAACAAATTTAAAAGAGGG 91 | GAAGAGTCATTTTTCATTTATTAAAATAAGCATTCCTACACCTTTTAGAA 92 | AGTAAAGCAGTGATGTGCATGCTGTTAATTCAGATTTATGCATTTATTTA 93 | -------------------------------------------------------------------------------- /tests/smallGenome/smallGenome.fa.fai: -------------------------------------------------------------------------------- 1 | chr9 2160 6 50 51 2 | chr11 2300 2217 50 51 3 | -------------------------------------------------------------------------------- /tests/smallGenome/smallGenome.rev.1.bt2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/tests/smallGenome/smallGenome.rev.1.bt2 -------------------------------------------------------------------------------- /tests/smallGenome/smallGenome.rev.2.bt2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinellolab/CRISPResso2/207b20748cf022dd15377bce63f8309a55d242ed/tests/smallGenome/smallGenome.rev.2.bt2 -------------------------------------------------------------------------------- /tests/testRelease.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | echo Running CRISPResso 3 | CRISPResso -r1 FANC.Cas9.fastq -a CGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCGGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -g GGAATCCCTTCTGCAGCACC --debug &> CRISPResso_on_FANC.Cas9.log 4 | 5 | echo Running CRISPResso with parameters 6 | CRISPResso -r1 FANC.Cas9.fastq -a CGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCGGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -g GGAATCCCTTCTGCAGCACC -e CGGCCGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCTGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -c GGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTT --dump -qwc 20-30_45-50 -q 30 --default_min_aln_score 80 -an FANC -n params --base_edit -fg AGCCTTGCAGTGGGCGCGCTA,CCCACTGAAGGCCC --dsODN GCTAGATTTCCCAAGAAGA -gn hi -fgn dear --debug &> CRISPResso_on_params.log 7 | 8 | echo Running CRISPRessoBatch 9 | CRISPRessoBatch -bs FANC.batch -a CGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCGGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG -g GGAATCCCTTCTGCAGCACC -p 2 --debug --base_editor --debug &> CRISPRessoBatch_on_FANC.log 10 | 11 | echo Running CRISPRessoPooled 12 | CRISPRessoPooled -r1 Both.Cas9.fastq -f Cas9.amplicons.txt -p 2 --keep_intermediate --min_reads_to_use_region 100 --debug &> CRISPRessoPooled_on_Both.Cas9.log 13 | 14 | echo Running CRISPRessoWGS 15 | CRISPRessoWGS -b Both.Cas9.fastq.smallGenome.bam -r smallGenome/smallGenome.fa -f Cas9.regions.txt --debug &> CRISPRessoWGS_on_Both.Cas9.fastq.smallGenome.log 16 | 17 | echo TESTING CRISPRESSO2 18 | diff CRISPResso_on_FANC.Cas9/Reference.nucleotide_frequency_table.txt expectedResults/CRISPResso_on_FANC.Cas9/Reference.nucleotide_frequency_table.txt 19 | diff CRISPResso_on_FANC.Cas9/CRISPResso_quantification_of_editing_frequency.txt tests/expectedResults/CRISPResso_on_FANC.Cas9/CRISPResso_quantification_of_editing_frequency.txt 20 | 21 | echo TESTING CRISPRESSO2 PARAMS 22 | diff CRISPResso_on_params/FANC.nucleotide_frequency_table.txt expectedResults/CRISPResso_on_params/FANC.nucleotide_frequency_table.txt 23 | diff CRISPResso_on_params/CRISPResso_quantification_of_editing_frequency.txt tests/expectedResults/CRISPResso_on_params/CRISPResso_quantification_of_editing_frequency.txt 24 | 25 | echo TESTING BATCH 26 | diff CRISPRessoBatch_on_FANC/Reference.MODIFICATION_FREQUENCY_SUMMARY.txt tests/expectedResults/CRISPRessoBatch_on_FANC/Reference.MODIFICATION_FREQUENCY_SUMMARY.txt 27 | 28 | echo TESTING POOLED 29 | diff CRISPRessoPooled_on_Both.Cas9/SAMPLES_QUANTIFICATION_SUMMARY.txt tests/expectedResults/CRISPRessoPooled_on_Both.Cas9/SAMPLES_QUANTIFICATION_SUMMARY.txt 30 | 31 | echo TESTING WGS 32 | diff CRISPRessoWGS_on_Both.Cas9.fastq.smallGenome/SAMPLES_QUANTIFICATION_SUMMARY.txt tests/expectedResults/CRISPRessoWGS_on_Both.Cas9.fastq.smallGenome/SAMPLES_QUANTIFICATION_SUMMARY.txt 33 | 34 | echo Finished 35 | -------------------------------------------------------------------------------- /tests/unit_tests/README.md: -------------------------------------------------------------------------------- 1 | # CRISPResso2 Unit Tests 2 | 3 | Testing CRISPResso2 is done using `pytest`, and you can run `pytest tests` from the root of the project. 4 | If you get errors, make sure that the version of `pytest` you installed matches the version of Python in your environment. 5 | If you get errors about not being able to import the CRISPResso modules, make sure that you specify the directory (e.g. `pytest tests`). 6 | -------------------------------------------------------------------------------- /tests/unit_tests/test_CRISPResso2Align.py: -------------------------------------------------------------------------------- 1 | """Unit tests for CRISPResso2Align.""" 2 | 3 | from CRISPResso2 import CRISPResso2Align 4 | import numpy as np 5 | 6 | ALN_MATRIX = CRISPResso2Align.read_matrix('./CRISPResso2/EDNAFULL') 7 | 8 | 9 | def test_global_align(): 10 | """General alignment tests.""" 11 | seq1, seq2, score = CRISPResso2Align.global_align('ATTA', 'ATTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,0,0],dtype=int)) 12 | assert seq1 == 'ATTA' 13 | assert seq2 == 'ATTA' 14 | assert score == 100 15 | 16 | 17 | def test_global_align_gap_incentive_s1(): 18 | """Test the global_align gap incentives for gaps in sequence 1 (the first sequence).""" 19 | seq1, seq2, score = CRISPResso2Align.global_align('ATTTA', 'ATTTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,0,0,0],dtype=int)) 20 | # print('seq1: ' + seq1 + ' seq2: ' + seq2 + ' score ' + str(score)) 21 | assert seq1 == 'ATTTA' 22 | assert seq2 == 'ATTTA' 23 | assert score == 100 24 | 25 | seq1, seq2, score = CRISPResso2Align.global_align('ATTTA', 'ATTA', matrix=ALN_MATRIX, gap_incentive=np.array([1,0,0,0,0],dtype=int)) 26 | assert seq1 == 'ATTTA' 27 | assert seq2 == 'ATT-A' 28 | assert round(score,3) == round(100*4/5.0,3) 29 | 30 | seq1, seq2, score = CRISPResso2Align.global_align('ATTTA', 'ATTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,1,0,0,0],dtype=int)) 31 | assert seq1 == 'ATTTA' 32 | assert seq2 == 'A-TTA' 33 | assert round(score,3) == round(100*4/5.0,3) 34 | 35 | seq1, seq2, score = CRISPResso2Align.global_align('ATTTA', 'ATTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,1,0,0],dtype=int)) 36 | assert seq1 == 'ATTTA' 37 | assert seq2 == 'AT-TA' 38 | assert round(score,3) == round(100*4/5.0,3) 39 | 40 | seq1, seq2, score = CRISPResso2Align.global_align('ATTTA', 'ATTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,1,0],dtype=int)) 41 | assert seq1 == 'ATTTA' 42 | assert seq2 == 'ATT-A' 43 | assert round(score,3) == round(100*4/5.0,3) 44 | 45 | seq1, seq2, score = CRISPResso2Align.global_align('ATTTA', 'ATTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,1,0],dtype=int)) 46 | assert seq1 == 'ATTTA' 47 | assert seq2 == 'ATT-A' 48 | assert round(score,3) == round(100*4/5.0,3) 49 | 50 | seq1, seq2, score = CRISPResso2Align.global_align('ATTTA', 'ATTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,0,1],dtype=int)) 51 | assert seq1 == 'ATTTA' 52 | assert seq2 == 'ATT-A' 53 | assert round(score,3) == round(100*4/5.0,3) 54 | 55 | seq1, seq2, score = CRISPResso2Align.global_align('TTTTT', 'TTTT', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,0,0],dtype=int)) 56 | assert seq1 == 'TTTTT' 57 | assert seq2 == 'TTTT-' 58 | assert round(score,3) == round(100*4/5.0,3) 59 | 60 | seq1, seq2, score = CRISPResso2Align.global_align('TTTTT', 'TTTT', matrix=ALN_MATRIX, gap_incentive=np.array([1,0,0,0,0],dtype=int)) 61 | assert seq1 == 'TTTTT' 62 | assert seq2 == '-TTTT' 63 | assert round(score,3) == round(100*4/5.0,3) 64 | 65 | seq1, seq2, score = CRISPResso2Align.global_align('TTTTT', 'TTTT', matrix=ALN_MATRIX, gap_incentive=np.array([0,1,0,0,0],dtype=int)) 66 | assert seq1 == 'TTTTT' 67 | assert seq2 == 'T-TTT' 68 | assert round(score,3) == round(100*4/5.0,3) 69 | 70 | seq1, seq2, score = CRISPResso2Align.global_align('TTTTT', 'TTTT', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,1,0,0],dtype=int)) 71 | assert seq1 == 'TTTTT' 72 | assert seq2 == 'TT-TT' 73 | assert round(score,3) == round(100*4/5.0,3) 74 | 75 | seq1, seq2, score = CRISPResso2Align.global_align('TTTTT', 'TTTT', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,1,0],dtype=int)) 76 | assert seq1 == 'TTTTT' 77 | assert seq2 == 'TTT-T' 78 | assert round(score,3) == round(100*4/5.0,3) 79 | 80 | seq1, seq2, score = CRISPResso2Align.global_align('TTTTT', 'TTTT', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,0,1],dtype=int)) 81 | assert seq1 == 'TTTTT' 82 | assert seq2 == 'TTTT-' 83 | assert round(score,3) == round(100*4/5.0,3) 84 | 85 | def test_global_align_gap_incentive_s2(): 86 | """Test the global_align gap incentives for gaps in sequence 2 (the second sequence).""" 87 | seq1, seq2, score = CRISPResso2Align.global_align('ATTA', 'ATTTA', matrix=ALN_MATRIX, gap_incentive=np.array([1,0,0,0,0,0],dtype=int)) 88 | assert seq1 == 'ATT-A' 89 | assert seq2 == 'ATTTA' 90 | assert round(score,3) == round(100*4/5.0,3) 91 | 92 | seq1, seq2, score = CRISPResso2Align.global_align('ATTA', 'ATTTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,1,0,0,0,0],dtype=int)) 93 | assert seq1 == 'A-TTA' 94 | assert seq2 == 'ATTTA' 95 | assert round(score,3) == round(100*4/5.0,3) 96 | 97 | seq1, seq2, score = CRISPResso2Align.global_align('ATTA', 'ATTTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,1,0,0,0],dtype=int)) 98 | assert seq1 == 'AT-TA' 99 | assert seq2 == 'ATTTA' 100 | assert round(score,3) == round(100*4/5.0,3) 101 | 102 | seq1, seq2, score = CRISPResso2Align.global_align('ATTA', 'ATTTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,1,0,0],dtype=int)) 103 | assert seq1 == 'ATT-A' 104 | assert seq2 == 'ATTTA' 105 | assert round(score,3) == round(100*4/5.0,3) 106 | 107 | seq1, seq2, score = CRISPResso2Align.global_align('ATTA', 'ATTTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,0,1,0],dtype=int)) 108 | assert seq1 == 'ATT-A' 109 | assert seq2 == 'ATTTA' 110 | assert round(score,3) == round(100*4/5.0,3) 111 | 112 | seq1, seq2, score = CRISPResso2Align.global_align('ATTA', 'ATTTA', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,0,0,1],dtype=int)) 113 | assert seq1 == 'ATT-A' 114 | assert seq2 == 'ATTTA' 115 | assert round(score,3) == round(100*4/5.0,3) 116 | 117 | seq1, seq2, score = CRISPResso2Align.global_align('TTTT', 'TTTTT', matrix=ALN_MATRIX, gap_incentive=np.array([1,0,0,0,0,0],dtype=int)) 118 | assert seq1 == '-TTTT' 119 | assert seq2 == 'TTTTT' 120 | assert round(score,3) == round(100*4/5.0,3) 121 | 122 | seq1, seq2, score = CRISPResso2Align.global_align('TTTT', 'TTTTT', matrix=ALN_MATRIX, gap_incentive=np.array([0,1,0,0,0,0],dtype=int)) 123 | assert seq1 == 'T-TTT' 124 | assert seq2 == 'TTTTT' 125 | assert round(score,3) == round(100*4/5.0,3) 126 | 127 | seq1, seq2, score = CRISPResso2Align.global_align('TTTT', 'TTTTT', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,1,0,0,0],dtype=int)) 128 | assert seq1 == 'TT-TT' 129 | assert seq2 == 'TTTTT' 130 | assert round(score,3) == round(100*4/5.0,3) 131 | 132 | seq1, seq2, score = CRISPResso2Align.global_align('TTTT', 'TTTTT', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,1,0,0],dtype=int)) 133 | assert seq1 == 'TTT-T' 134 | assert seq2 == 'TTTTT' 135 | assert round(score,3) == round(100*4/5.0,3) 136 | 137 | seq1, seq2, score = CRISPResso2Align.global_align('TTTT', 'TTTTT', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,0,1,0],dtype=int)) 138 | assert seq1 == 'TTTT-' 139 | assert seq2 == 'TTTTT' 140 | assert round(score,3) == round(100*4/5.0,3) 141 | 142 | seq1, seq2, score = CRISPResso2Align.global_align('TTTT', 'TTTTT', matrix=ALN_MATRIX, gap_incentive=np.array([0,0,0,0,0,1],dtype=int)) 143 | assert seq1 == 'TTTT-' 144 | assert seq2 == 'TTTTT' 145 | assert round(score,3) == round(100*4/5.0,3) 146 | 147 | if __name__ == "__main__": 148 | # execute only if run as a script 149 | test_global_align() 150 | test_global_align_gap_incentive_s1() 151 | test_global_align_gap_incentive_s2() 152 | -------------------------------------------------------------------------------- /tests/unit_tests/test_CRISPRessoBatchCORE.py: -------------------------------------------------------------------------------- 1 | from CRISPResso2 import CRISPRessoBatchCORE 2 | 3 | 4 | 5 | def test_should_plot_large_plots(): 6 | num_rows = 60 7 | c2pro_installed = False 8 | use_matplotlib = False 9 | large_plot_cutoff = 300 10 | assert CRISPRessoBatchCORE.should_plot_large_plots(num_rows, c2pro_installed, use_matplotlib, large_plot_cutoff) 11 | 12 | 13 | def test_should_plot_large_plots_c2pro_installed_use_matplotlib_small(): 14 | num_rows = 60 15 | c2pro_installed = True 16 | use_matplotlib = True 17 | large_plot_cutoff = 300 18 | assert CRISPRessoBatchCORE.should_plot_large_plots(num_rows, c2pro_installed, use_matplotlib, large_plot_cutoff) 19 | 20 | 21 | def test_should_plot_large_plots_c2pro_installed(): 22 | num_rows = 6000 23 | c2pro_installed = True 24 | use_matplotlib = False 25 | large_plot_cutoff = 300 26 | assert CRISPRessoBatchCORE.should_plot_large_plots(num_rows, c2pro_installed, use_matplotlib, large_plot_cutoff) 27 | 28 | 29 | def test_should_plot_large_plots_c2pro_installed_use_matplotlib_large(): 30 | num_rows = 6000 31 | c2pro_installed = True 32 | use_matplotlib = True 33 | large_plot_cutoff = 300 34 | assert not CRISPRessoBatchCORE.should_plot_large_plots(num_rows, c2pro_installed, use_matplotlib, large_plot_cutoff) 35 | 36 | 37 | def test_should_plot_large_plots_c2pro_not_installed_use_matplotlib(): 38 | num_rows = 6000 39 | c2pro_installed = False 40 | use_matplotlib = True 41 | large_plot_cutoff = 300 42 | assert not CRISPRessoBatchCORE.should_plot_large_plots(num_rows, c2pro_installed, use_matplotlib, large_plot_cutoff) 43 | 44 | 45 | -------------------------------------------------------------------------------- /tests/unit_tests/test_CRISPRessoCompareCORE.py: -------------------------------------------------------------------------------- 1 | """Unit tests for CRISPRessoCompareCORE.""" 2 | 3 | from CRISPResso2 import CRISPRessoCompareCORE 4 | 5 | from copy import deepcopy 6 | import pytest 7 | 8 | 9 | @pytest.fixture(scope='function') 10 | def run_info(): 11 | return { 12 | 'results': { 13 | 'refs': { 14 | 'Reference': { 15 | 'sequence':'CGGATGTTCCAATCAGTACGCAGAGAGTCGCCGTCTCCAAGGTGAAAGCGGAAGTAGGGCCTTCGCGCACCTCATGGAATCCCTTCTGCAGCACCTGGATCGCTTTTCCGAGCTTCTGGCGGTCTCAAGCACTACCTACGTCAGCACCTGGGACCCCGCCACCGTGCGCCGGGCCTTGCAGTGGGCGCGCTACCTGCGCCACATCCATCGGCGCTTTGGTCGG', 16 | 'sgRNA_orig_sequences': ['GGCCCTTAAAA'], 17 | 'sgRNA_cut_points': [50], 18 | 'allele_frequency_files': ['Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt'], 19 | }, 20 | }, 21 | }, 22 | } 23 | 24 | 25 | @pytest.fixture(scope='function') 26 | def run_info_1(run_info): 27 | return deepcopy(run_info) 28 | 29 | 30 | @pytest.fixture(scope='function') 31 | def run_info_2(run_info): 32 | return deepcopy(run_info) 33 | 34 | 35 | def test_get_matching_allele_files(run_info): 36 | matching_allele_files = CRISPRessoCompareCORE.get_matching_allele_files(run_info, run_info) 37 | assert matching_allele_files == [('Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt', 'Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt')] 38 | 39 | 40 | def test_get_matching_allele_files_different_cut_points(run_info_1, run_info_2): 41 | run_info_2['results']['refs']['Reference']['sgRNA_cut_points'] = [50, 51] 42 | matching_allele_files = CRISPRessoCompareCORE.get_matching_allele_files(run_info_1, run_info_2) 43 | assert matching_allele_files == [] 44 | 45 | 46 | def test_get_matching_allele_files_different_guides(run_info_1, run_info_2): 47 | run_info_2['results']['refs']['Reference']['sgRNA_orig_sequences'] = ['GGCCCTTAAAC'] 48 | run_info_2['results']['refs']['Reference']['allele_frequency_files'] = ['Alleles_frequency_table_around_sgRNA_GGCCCTTAAAC.txt'] 49 | matching_allele_files = CRISPRessoCompareCORE.get_matching_allele_files(run_info_1, run_info_2) 50 | assert matching_allele_files == [] 51 | 52 | 53 | def test_get_matching_allele_files_multiple_alleles(run_info_1, run_info_2): 54 | run_info_1['results']['refs']['Other_Amplicon'] = deepcopy(run_info_1['results']['refs']['Reference']) 55 | run_info_1['results']['refs']['Other_Amplicon']['sequence'] = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA' 56 | run_info_1['results']['refs']['Other_Amplicon']['allele_frequency_files'] = ['Other_Amplicon.Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt'] 57 | matching_allele_files = CRISPRessoCompareCORE.get_matching_allele_files(run_info_1, run_info_2) 58 | assert matching_allele_files == [('Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt', 'Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt')] 59 | 60 | 61 | def test_get_matching_allele_files_different_amplicon_names_same_sequence(run_info_1, run_info_2): 62 | run_info_2['results']['refs']['Other_Amplicon'] = deepcopy(run_info_1['results']['refs']['Reference']) 63 | del run_info_2['results']['refs']['Reference'] 64 | matching_allele_files = CRISPRessoCompareCORE.get_matching_allele_files(run_info_1, run_info_2) 65 | assert matching_allele_files == [('Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt', 'Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt')] 66 | 67 | 68 | def test_get_matching_allele_files_some_different_guides(run_info_1, run_info_2): 69 | run_info_1['results']['refs']['Reference']['sgRNA_orig_sequences'] += ['AAAAAAAAAAAAAAAAAAA'] 70 | run_info_1['results']['refs']['Reference']['allele_frequency_files'] += ['Alleles_frequency_table_around_sgRNA_AAAAAAAAAAAAAAAAAAA.txt'] 71 | matching_allele_files = CRISPRessoCompareCORE.get_matching_allele_files(run_info_1, run_info_2) 72 | assert matching_allele_files == [('Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt', 'Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt')] 73 | 74 | 75 | def test_get_matching_allele_files_multiple_guides(run_info_1, run_info_2): 76 | run_info_1['results']['refs']['Reference']['sgRNA_orig_sequences'] += ['AAAAAAAAAAAAAAAAAAA'] 77 | run_info_1['results']['refs']['Reference']['allele_frequency_files'] += ['Alleles_frequency_table_around_sgRNA_AAAAAAAAAAAAAAAAAAA.txt'] 78 | run_info_2['results']['refs']['Reference']['sgRNA_orig_sequences'] += ['AAAAAAAAAAAAAAAAAAA'] 79 | run_info_2['results']['refs']['Reference']['allele_frequency_files'] += ['Alleles_frequency_table_around_sgRNA_AAAAAAAAAAAAAAAAAAA.txt'] 80 | matching_allele_files = CRISPRessoCompareCORE.get_matching_allele_files(run_info_1, run_info_2) 81 | assert matching_allele_files == [ 82 | ('Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt', 'Alleles_frequency_table_around_sgRNA_GGCCCTTAAAA.txt'), 83 | ('Alleles_frequency_table_around_sgRNA_AAAAAAAAAAAAAAAAAAA.txt', 'Alleles_frequency_table_around_sgRNA_AAAAAAAAAAAAAAAAAAA.txt'), 84 | ] 85 | 86 | -------------------------------------------------------------------------------- /tests/unit_tests/test_CRISPRessoPooledCORE.py: -------------------------------------------------------------------------------- 1 | from CRISPResso2 import CRISPRessoPooledCORE 2 | 3 | 4 | def test_calculate_aligned_samtools_exclude_flags(): 5 | assert CRISPRessoPooledCORE.calculate_aligned_samtools_exclude_flags('0') == hex(0x900) 6 | 7 | 8 | def test_calculate_aligned_samtools_exclude_flags_4(): 9 | assert CRISPRessoPooledCORE.calculate_aligned_samtools_exclude_flags('4') == hex(0x904) 10 | 11 | 12 | def test_calculate_aligned_samtools_exclude_flags_9(): 13 | assert CRISPRessoPooledCORE.calculate_aligned_samtools_exclude_flags('9') == hex(0x909) 14 | 15 | 16 | def test_calculate_aligned_samtools_exclude_flags_0x100(): 17 | assert CRISPRessoPooledCORE.calculate_aligned_samtools_exclude_flags('0x100') == hex(0x900) 18 | 19 | 20 | def test_calculate_aligned_samtools_exclude_flags_010(): 21 | """This tests for proper handling of octal numbers.""" 22 | assert CRISPRessoPooledCORE.calculate_aligned_samtools_exclude_flags('010') == hex(0x908) 23 | 24 | 25 | def test_calculate_aligned_samtools_exclude_flags_comma(): 26 | """This tests for proper handling of commas.""" 27 | assert CRISPRessoPooledCORE.calculate_aligned_samtools_exclude_flags('0,4') == f'0,4,{hex(0x900)}' 28 | -------------------------------------------------------------------------------- /tests/unit_tests/test_CRISPRessoShared.py: -------------------------------------------------------------------------------- 1 | from CRISPResso2 import CRISPResso2Align, CRISPRessoShared 2 | import tempfile 3 | import os 4 | import gzip 5 | 6 | ALN_MATRIX = CRISPResso2Align.read_matrix('./CRISPResso2/EDNAFULL') 7 | 8 | 9 | def test_get_mismatches(): 10 | mismatch_cords = CRISPRessoShared.get_mismatches( 11 | 'ATTA', 12 | 'ATTA', 13 | ALN_MATRIX, 14 | -5, 15 | -3, 16 | ) 17 | assert len(mismatch_cords) == 0 18 | 19 | mismatch_cords = CRISPRessoShared.get_mismatches( 20 | 'GCAGTGGGCGCGCTA', 21 | 'CCCACTGAAGGCCC', 22 | ALN_MATRIX, 23 | -5, 24 | -3, 25 | ) 26 | assert len(mismatch_cords) == 6 27 | 28 | def test_get_relative_coordinates(): 29 | s1inds_gap_left, s1inds_gap_right = CRISPRessoShared.get_relative_coordinates('ATCGT', 'TTCGT') 30 | assert s1inds_gap_left == [0, 1, 2, 3, 4] 31 | assert s1inds_gap_right == [0, 1, 2, 3, 4] 32 | 33 | 34 | def test_get_n_reads_fastq(): 35 | with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.fastq') as f: 36 | f.write("@SEQ_ID\n") 37 | f.write("GATTACA\n") 38 | f.write("+\n") 39 | f.write("AAAAAAA\n") # Ensure the file content is correct and ends with a newline 40 | f.flush() # Flush the content to disk 41 | os.fsync(f.fileno()) # Ensure all internal buffers associated with the file are written to disk 42 | 43 | # Since the file needs to be read by another process, we ensure it's closed and written before passing it 44 | assert CRISPRessoShared.get_n_reads_fastq(f.name) == 1 45 | 46 | # Clean up: delete the file after the test 47 | os.remove(f.name) 48 | 49 | def test_get_n_reads_fastq_gzip(): 50 | with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.fastq') as f: 51 | f.write("@SEQ_ID\n") 52 | f.write("GATTACA\n") 53 | f.write("+\n") 54 | f.write("AAAAAAA\n") # Ensure the file content is correct and ends with a newline 55 | f.flush() # Flush the content to disk 56 | os.fsync(f.fileno()) # Ensure all internal buffers associated with the file are written to disk 57 | 58 | # gzip file 59 | with open(f.name, 'rb') as f_in, gzip.open(f.name + '.gz', 'wb') as f_out: 60 | f_out.writelines(f_in) 61 | 62 | # Since the file needs to be read by another process, we ensure it's closed and written before passing it 63 | assert CRISPRessoShared.get_n_reads_fastq(f.name + '.gz') == 1 64 | 65 | # Clean up: delete the file after the test 66 | os.remove(f.name) 67 | os.remove(f.name + '.gz') 68 | 69 | 70 | def test_get_n_reads_fastq_three_extra_newlines(): 71 | with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.fastq') as f: 72 | f.write("@SEQ_ID\n") 73 | f.write("GATTACA\n") 74 | f.write("+\n") 75 | f.write("AAAAAAA\n") # Ensure the file content is correct and ends with a newline 76 | f.write("\n\n") # Ensure the file content is correct and ends with a newline 77 | f.flush() # Flush the content to disk 78 | os.fsync(f.fileno()) # Ensure all internal buffers associated with the file are written to disk 79 | 80 | # Since the file needs to be read by another process, we ensure it's closed and written before passing it 81 | assert CRISPRessoShared.get_n_reads_fastq(f.name) == 1 82 | 83 | # Clean up: delete the file after the test 84 | os.remove(f.name) 85 | 86 | 87 | def test_get_n_reads_fastq_four_extra_newlines(): 88 | with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.fastq') as f: 89 | f.write("@SEQ_ID\n") 90 | f.write("GATTACA\n") 91 | f.write("+\n") 92 | f.write("AAAAAAA\n") # Ensure the file content is correct and ends with a newline 93 | f.write("\n\n\n\n\n\n\n\n") # Ensure the file content is correct and ends with a newline 94 | f.flush() # Flush the content to disk 95 | os.fsync(f.fileno()) # Ensure all internal buffers associated with the file are written to disk 96 | 97 | # Since the file needs to be read by another process, we ensure it's closed and written before passing it 98 | assert CRISPRessoShared.get_n_reads_fastq(f.name) == 1 99 | 100 | # Clean up: delete the file after the test 101 | os.remove(f.name) 102 | 103 | 104 | def test_get_n_reads_fastq_100_reads(): 105 | with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.fastq') as f: 106 | for i in range(100): 107 | f.write("@SEQ_ID\n") 108 | f.write("GATTACA\n") 109 | f.write("+\n") 110 | f.write("AAAAAAA\n") 111 | f.flush() # Flush the content to disk 112 | os.fsync(f.fileno()) # Ensure all internal buffers associated with the file are written to disk 113 | 114 | # Since the file needs to be read by another process, we ensure it's closed and written before passing it 115 | assert CRISPRessoShared.get_n_reads_fastq(f.name) == 100 116 | 117 | # Clean up: delete the file after the test 118 | os.remove(f.name) 119 | 120 | def test_get_n_reads_fastq_no_newline(): 121 | with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.fastq') as f: 122 | f.write("@SEQ_ID\n") 123 | f.write("GATTACA\n") 124 | f.write("+\n") 125 | f.write("AAAAAAA") # Ensure the file content is correct and ends with a newline 126 | f.flush() # Flush the content to disk 127 | os.fsync(f.fileno()) # Ensure all internal buffers associated with the file are written to disk 128 | 129 | # Since the file needs to be read by another process, we ensure it's closed and written before passing it 130 | assert CRISPRessoShared.get_n_reads_fastq(f.name) == 1 131 | 132 | # Clean up: delete the file after the test 133 | os.remove(f.name) 134 | 135 | 136 | def test_get_n_reads_fastq_empty_file(): 137 | with tempfile.NamedTemporaryFile(mode='w+', delete=False, suffix='.fastq') as f: 138 | f.flush() # Flush the content to disk 139 | os.fsync(f.fileno()) # Ensure all internal buffers associated with the file are written to disk 140 | 141 | # Since the file needs to be read by another process, we ensure it's closed and written before passing it 142 | assert CRISPRessoShared.get_n_reads_fastq(f.name) == 0 143 | 144 | # Clean up: delete the file after the test 145 | os.remove(f.name) 146 | 147 | 148 | def test_get_relative_coordinates_to_gap(): 149 | # unaligned sequences 150 | seq_1 = 'TTCGT' 151 | seq_2 = 'TTCT' 152 | 153 | # aligned_sequences 154 | to_sequence = 'TTC-T' 155 | from_sequence = 'TTCGT' 156 | 157 | s1inds_gap_left, s1inds_gap_right = CRISPRessoShared.get_relative_coordinates(to_sequence, from_sequence) 158 | assert s1inds_gap_left == [0, 1, 2, 2, 3] 159 | assert s1inds_gap_right == [0, 1, 2, 3, 3] 160 | 161 | 162 | assert seq_1[0] == seq_2[s1inds_gap_left[0]] 163 | assert seq_1[1] == seq_2[s1inds_gap_left[1]] 164 | assert seq_1[2] == seq_2[s1inds_gap_left[2]] 165 | assert seq_1[4] == seq_2[s1inds_gap_left[4]] 166 | 167 | 168 | def test_get_relative_coordinates_start_gap(): 169 | s1inds_gap_left, s1inds_gap_right = CRISPRessoShared.get_relative_coordinates('--CGT', 'TTCGT') 170 | assert s1inds_gap_left == [-1, -1, 0, 1, 2] 171 | assert s1inds_gap_right == [0, 0, 0, 1, 2] 172 | 173 | 174 | def test_get_relative_coordinates_from_gap(): 175 | s1inds_gap_left, s1inds_gap_right = CRISPRessoShared.get_relative_coordinates('ATCGT', 'ATC-T') 176 | assert s1inds_gap_left == [0, 1, 2, 4] 177 | assert s1inds_gap_right == [0, 1, 2, 4] 178 | 179 | def test_get_relative_coordinates_end_gap(): 180 | s1inds_gap_left, s1inds_gap_right = CRISPRessoShared.get_relative_coordinates('ATC--', 'ATCGT') 181 | assert s1inds_gap_left == [0, 1, 2, 2, 2] 182 | assert s1inds_gap_right == [0, 1, 2, 3, 3] 183 | 184 | def test_get_relative_coordinates_multiple_gaps(): 185 | s1inds_gap_left, s1inds_gap_right = CRISPRessoShared.get_relative_coordinates('AT--TC--G--CC', 'ATCGTCGCGTTCC') 186 | assert s1inds_gap_left == [0, 1, 1, 1, 2, 3, 3, 3, 4, 4, 4, 5, 6] 187 | assert s1inds_gap_right == [0, 1, 2, 2, 2, 3, 4, 4, 4, 5, 5, 5, 6] 188 | 189 | def test_get_relative_coordinates_ind_and_dels(): 190 | s1inds_gap_left, s1inds_gap_right = CRISPRessoShared.get_relative_coordinates('ATG--C', 'A-GCTC') 191 | assert s1inds_gap_left == [0, 2, 2, 2, 3] 192 | assert s1inds_gap_right == [0, 2, 3, 3, 3] 193 | 194 | 195 | def test_get_quant_window_ranges_from_include_idxs(): 196 | include_idxs = [0, 1, 2, 10, 11, 12] 197 | assert CRISPRessoShared.get_quant_window_ranges_from_include_idxs(include_idxs) == [(0, 2), (10, 12)] 198 | 199 | 200 | def test_get_quant_window_ranges_from_include_idxs_empty(): 201 | include_idxs = [] 202 | assert CRISPRessoShared.get_quant_window_ranges_from_include_idxs(include_idxs) == [] 203 | 204 | 205 | def test_get_quant_window_ranges_from_include_idxs_single(): 206 | include_idxs = [50, 51, 52, 53] 207 | assert CRISPRessoShared.get_quant_window_ranges_from_include_idxs(include_idxs) == [(50, 53)] 208 | 209 | 210 | def test_get_quant_window_ranges_from_include_idxs_single_gap(): 211 | include_idxs = [50, 51, 52, 53, 55] 212 | assert CRISPRessoShared.get_quant_window_ranges_from_include_idxs(include_idxs) == [(50, 53), (55, 55)] 213 | 214 | 215 | def test_get_quant_window_ranges_from_include_idxs_multiple_gaps(): 216 | include_idxs = [50, 51, 52, 53, 55, 56, 57, 58, 60] 217 | assert CRISPRessoShared.get_quant_window_ranges_from_include_idxs(include_idxs) == [(50, 53), (55, 58), (60, 60)] 218 | 219 | --------------------------------------------------------------------------------