├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── question.md └── workflows │ ├── pythonpublish.yml │ ├── pythonpublish_manual.yml │ └── tests.yml ├── .gitignore ├── .readthedocs.yml ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── __init__.py ├── coolpuppy ├── CLI.py ├── __init__.py ├── _version.py ├── coolpup.py ├── divide_pups_CLI.py ├── lib │ ├── __init__.py │ ├── io.py │ ├── numutils.py │ ├── puputils.py │ └── util.py ├── plotpup.py └── plotpuppy_CLI.py ├── docs ├── Makefile ├── make.bat ├── requirements.txt └── source │ ├── Examples │ ├── CH12_TADs_Rao.bed │ ├── CH12_loops_Rao.bed │ ├── Ctrl_TAD.txt │ ├── Ctrl_loop.txt │ ├── Scc1-KO.10000-10.0K_over_CH12_loops_Rao_10-shifts_dist_100000-inf_unbalanced_covnorm.np.txt │ ├── Scc1-KO.10000.cool │ ├── Scc1-control.10000-10.0K_over_CH12_loops_Rao_10-shifts_dist_100000-inf_unbalanced_covnorm.np.txt │ ├── Scc1-control.10000.cool │ ├── Scc1KO_TAD.txt │ ├── Scc1KO_loop.txt │ ├── TAD_score.ipynb │ ├── TADs.png │ ├── Walkthrough_API.ipynb │ ├── Walkthrough_CLI.ipynb │ ├── all.png │ ├── annotated_ctcf_sites.tsv │ ├── loops.png │ └── stripes.png │ ├── _static │ └── my_theme.css │ ├── conf.py │ ├── coolpup_py_cli.md │ ├── coolpuppy.rst.bak │ ├── favicon.ico │ ├── favicon.png │ ├── figs │ ├── chip_profile.png │ ├── example_local_pileup.png │ ├── example_local_rescaled_pileup.png │ ├── example_loop_pileup.png │ ├── example_pileup.png │ ├── local_quant.png │ ├── local_quant_borders.png │ ├── local_quant_tads.png │ ├── loop_quant.png │ ├── loopability.png │ └── new_grid_loop_quant.png │ ├── index.md │ ├── modules.md │ └── walkthrough.md ├── loop_quant.png ├── loop_quant.svg ├── pytest.ini ├── requirements-dev.txt ├── requirements.txt ├── setup.py └── tests ├── Bonev_CTCF+.bed ├── Bonev_CTCF-.bed ├── CH12_TADs_Rao.bed ├── CH12_loops_Rao.bed ├── CH12_loops_Rao_numeric_chroms.bed ├── CH12_loops_Rao_numeric_chroms_noX.bed ├── Scc1-control.10000.cool ├── Scc1-control.10000.numeric_chroms.cool ├── bed2_ref.np.txt ├── data ├── CN.mm9.1000kb.cool ├── CN.mm9.toy_expected.tsv ├── CN.mm9.toy_regions.bed └── toy_features.bed ├── loop_ref.np.txt ├── tad_ref.np.txt ├── test.bed ├── test.bedpe └── test_coolpup.py /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | Please make sure you've read the relevant parts of the tutorials and API documentation. 13 | 14 | **To Reproduce** 15 | Steps to reproduce the behavior: 16 | 1. Use these versions of coolpuppy, cooltools and bioframe: 17 | 2. Use this data (share if possible, or explain what kind experiment it was from): 18 | 3. Run this command or Python code: 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Results / Error** 24 | What results you got, whether it was an error or an unexpected output. 25 | 26 | **System** 27 | - OS: [e.g. Linux, macOS] 28 | - Python version 29 | 30 | **Additional context** 31 | Add any other context about the problem here. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Create a report to help us improve 4 | title: "[Q]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **State the question** 11 | A clear and concise description of the question. 12 | 13 | **What have you tried?** 14 | - [ ] Have you read the documentation and tutorials about your question? 15 | 16 | **Additional context** 17 | Add any other context about the problem here. 18 | -------------------------------------------------------------------------------- /.github/workflows/pythonpublish.yml: -------------------------------------------------------------------------------- 1 | name: Upload Python Package 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - name: Set up Python 13 | uses: actions/setup-python@v3 14 | with: 15 | python-version: '3.x' 16 | - name: Install dependencies 17 | run: | 18 | python -m pip install --upgrade pip 19 | pip install setuptools wheel twine 20 | - name: Build and publish 21 | env: 22 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} 23 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} 24 | run: | 25 | python setup.py sdist bdist_wheel 26 | twine upload dist/* 27 | -------------------------------------------------------------------------------- /.github/workflows/pythonpublish_manual.yml: -------------------------------------------------------------------------------- 1 | name: Upload Python Package 2 | 3 | on: workflow_dispatch 4 | 5 | jobs: 6 | deploy: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - name: Set up Python 11 | uses: actions/setup-python@v3 12 | with: 13 | python-version: '3.x' 14 | - name: Install dependencies 15 | run: | 16 | python -m pip install --upgrade pip 17 | pip install setuptools wheel twine 18 | - name: Build and publish 19 | env: 20 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} 21 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} 22 | run: | 23 | python setup.py sdist bdist_wheel 24 | twine upload dist/* 25 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions 3 | 4 | name: Pytest 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | python-version: [ '3.8', '3.9', '3.10' ] 19 | 20 | steps: 21 | - uses: actions/checkout@v4 22 | - name: Set up Python ${{ matrix.python-version }} 23 | uses: actions/setup-python@v3 24 | with: 25 | python-version: ${{ matrix.python-version }} 26 | - name: Install dependencies 27 | run: | 28 | pip install --upgrade pip wheel setuptools 29 | pip install numpy cython 30 | pip install -r requirements-dev.txt 31 | pip install -e . 32 | - name: Lint with flake8 33 | run: | 34 | # stop the build if there are Python syntax errors or undefined names 35 | flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics 36 | # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide 37 | flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics 38 | - name: Test with pytest 39 | run: | 40 | pytest 41 | - name: Test CLI notebook 42 | run: | 43 | pytest --nbval-lax docs/source/Examples/Walkthrough_CLI.ipynb 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | wheels/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | MANIFEST 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *.cover 46 | .hypothesis/ 47 | .pytest_cache/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | db.sqlite3 57 | 58 | # Flask stuff: 59 | instance/ 60 | .webassets-cache 61 | 62 | # Scrapy stuff: 63 | .scrapy 64 | 65 | # Sphinx documentation 66 | docs/_build/ 67 | 68 | # PyBuilder 69 | target/ 70 | 71 | # Jupyter Notebook 72 | .ipynb_checkpoints 73 | 74 | # pyenv 75 | .python-version 76 | 77 | # celery beat schedule file 78 | celerybeat-schedule 79 | 80 | # SageMath parsed files 81 | *.sage.py 82 | 83 | # Environments 84 | .env 85 | .venv 86 | env/ 87 | venv/ 88 | ENV/ 89 | env.bak/ 90 | venv.bak/ 91 | 92 | # Spyder project settings 93 | .spyderproject 94 | .spyproject 95 | 96 | # Rope project settings 97 | .ropeproject 98 | 99 | # mkdocs documentation 100 | /site 101 | 102 | # mypy 103 | .mypy_cache/ 104 | 105 | docs/jupyter_execute 106 | tests/testing_* 107 | tests/test_*.pdf 108 | .vscode/ 109 | docs/Examples/*.clpy 110 | 111 | .DS_Store -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.11" 13 | # You can also specify other tool versions: 14 | # nodejs: "19" 15 | # rust: "1.64" 16 | # golang: "1.19" 17 | 18 | # Build documentation in the docs/ directory with Sphinx 19 | sphinx: 20 | configuration: docs/source/conf.py 21 | 22 | # If using Sphinx, optionally build your docs in additional formats such as PDF 23 | # formats: 24 | # - pdf 25 | 26 | # Optionally declare the Python requirements required to build your docs 27 | python: 28 | install: 29 | - requirements: docs/requirements.txt 30 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.6" 4 | - "3.7" 5 | - "3.8" 6 | # command to install dependencies 7 | install: 8 | - pip install Cython 9 | - pip install cooltools 10 | - pip install . 11 | # command to run tests 12 | script: 13 | - pytest 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Release notes 2 | 3 | ## [Upcoming release](https://github.com/open2c/coolpuppy/compare/v1.1.0...HEAD) 4 | 5 | ## [v1.1.0] (https://github.com/open2c/coolpuppy/compare/v1.0.0...v1.1.0) 6 | 7 | * Added `ignore_group_order` and `--ignore_group_order` argument to flip and combine groups when using groupby, i.e. combining e.g. group1-group2 and group2-group1 8 | 9 | * Changed how flipping and group reassignment is implemented 10 | 11 | * Fixed zooming near diagonal 12 | 13 | * `divide_pups` now allows dividing even if columns are different, gives warning instead 14 | 15 | * Added additional tests 16 | 17 | * Bug fixes and logs/warnings added 18 | 19 | * Changes to walkthroughs 20 | 21 | ## [v1.0.0](https://github.com/open2c/coolpuppy/compare/0.9.5...v1.0.0) 22 | 23 | This is a major release with a lot of changes. The main ones are included below, but probably there are a lot of smaller ones too. 24 | 25 | ### API changes 26 | * New HDF5-based storage format, with functions to write and read the files in coolpuppy.lib.io 27 | 28 | * New “user-facing” `pileup` function in python API for convenient single-step pileups, and with interface similar to `cooltools.pileup` 29 | 30 | * Pileups can be restricted using a genomic view (`--view` in CLI and `view_df` in API) in line with cooltools/bioframe (note that the expected has to be calculated for the same view, if used) 31 | 32 | * If using expected, by default each snippet is now normalized to expected and only averaged afterwards; this is controlled by `ooe` argument in API and `--not-ooe` argument in CLI) 33 | 34 | * Added options to split snippets based on strands, genomic distance, or both 35 | 36 | * Added option `flip_negative_strand` (API) and `--flip-negative-strand` (CLI) to flip features located on the negative strand 37 | 38 | * Added option to groupby snippets by their properties and generate multiple pileups in one run (`groupby` in API and `--groupby` in CLI) 39 | 40 | * Added option `trans=True` (API) and `--trans` (CLI) to generate inter-chromosomal (trans) pileups 41 | 42 | * Added option `store_stripes=True` (API) and `--store_stripes` (CLI) to store individual vertical and horizontal stripe pairs 43 | 44 | * Added advanced option (`modify_2Dintervals_func` of `PileUpper.pileupsWithControls`) to apply an arbitrary function to pairs of intervals before they are used for generating pileups (i.e. bedpe-style intervals generated internally from either bedpe- or bed-style input features) 45 | 46 | * Added advanced option to apply an arbitrary function to each snippet before averaging in API (`postprocess_func` of `PileUpper.pileupsWithControls`) 47 | 48 | * Added function `divide_pups()` (API) and `dividepups.py` (CLI) to divide two pileups 49 | 50 | * CLI detects headers of bed and bedpe files 51 | 52 | * Overall API and CLI argument names are aligned with cooltools wherever possible 53 | 54 | ### Plotting changes 55 | * Changed names of `plotpup.make_heatmap_grid()` to `plotpup.plot()` 56 | * Added option `plotpup.plot_stripes()` (API) and `--stripe` (CLI) for plotting stripes 57 | * Added option `--divide_pups` (CLI) to plot the ratio of two pileups 58 | 59 | ### Documentation 60 | * Extensive tutorials for both python API and CLI 61 | 62 | ### Maintenance 63 | * Code restructured, so all CLI tools are in one package, and created .lib with shared internal functions in lib/io.py, lib/numutils.py, lib/puputils.py and lib/util.py 64 | 65 | * Tests migrated to github actions, and also running nbsmoke on the CLI notebook to ensure it runs without errors 66 | 67 | * Only support python >=3.8, cooltools >=0.5.2 68 | 69 | ### Miscellaneous 70 | * Logging has been fixed so the --logLevel properly works 71 | * Removed the launch_pileups.sh script 72 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## General guidelines 4 | 5 | If you haven't contributed to open-source before, we recommend you read [this excellent guide by GitHub on how to contribute to open source](https://opensource.guide/how-to-contribute). The guide is long, so you can gloss over things you're familiar with. 6 | 7 | If you're not already familiar with it, we follow the [fork and pull model](https://help.github.com/articles/about-collaborative-development-models) on GitHub. Also, check out this recommended [git workflow](https://www.asmeurer.com/git-workflow/). 8 | 9 | As a rough guide for cooltools: 10 | - contributors should preferably work on their forks and submit pull requests to the main branch 11 | - core maintainers can work on feature branches in the main fork and then submit pull requests to the main branch 12 | - core maintainers can push directly to the main branch if it's urgently needed 13 | 14 | 15 | ## Contributing Code 16 | 17 | This project has a number of requirements for all code contributed. 18 | 19 | * We follow the [PEP-8 style](https://www.python.org/dev/peps/pep-0008/) convention. 20 | * We use [flake8](http://flake8.pycqa.org/en/latest/) to automatically lint the code and maintain code style. You can use a code formatter like [black](https://github.com/psf/black) or [autopep8](https://github.com/hhatto/autopep8) to help keep the linter happy. 21 | * We use [Numpy-style docstrings](https://numpydoc.readthedocs.io/en/latest/format.html). 22 | * User-facing API changes or new features should have documentation added. 23 | 24 | Ideally, provide full test coverage for new code submitted in PRs. 25 | 26 | 27 | ## Setting up Your Development Environment 28 | 29 | For setting up an isolated virtual environment for development, we recommend using [conda](https://docs.conda.io/en/latest/miniconda.html). After forking and cloning the repository, install in "editable" (i.e. development) mode using the `-e` option: 30 | 31 | ```sh 32 | $ git clone https://github.com/open2c/coolpuppy.git 33 | $ cd coolpuppy 34 | $ pip install -e . 35 | ``` 36 | 37 | Editable mode installs the package by creating a "link" to your working (repo) directory. 38 | 39 | 40 | ## Unit Tests 41 | 42 | It is best if all new functionality and/or bug fixes have unit tests added with each use-case. 43 | 44 | We use [pytest](https://docs.pytest.org/en/latest) as our unit testing framework with the `pytest-cov` extension to check code coverage and `pytest-flake8` to check code style. You don't need to configure these extensions yourself. 45 | This automatically checks code style and functionality, and prints code coverage, even though it doesn't fail on low coverage. 46 | 47 | Once you've configured your environment, you can just `cd` to the root of your repository and run 48 | 49 | ```sh 50 | $ pytest 51 | ``` 52 | 53 | Unit tests are automatically run on GitHub Actions for pull requests. 54 | 55 | 56 | ## Coverage 57 | 58 | The `pytest` script automatically reports coverage, both on the terminal for missing line numbers, and in annotated HTML form in `htmlcov/index.html`. 59 | 60 | 61 | ## Documentation 62 | 63 | If a feature is stable and relatively finalized, it is time to add it to the documentation. If you are adding any private/public functions, it is best to add docstrings, to aid in reviewing code and also for the API reference. 64 | 65 | We use [Numpy style docstrings](https://numpydoc.readthedocs.io/en/latest/format.html>) and [Sphinx](http://www.sphinx-doc.org/en/stable) to document this library. Sphinx, in turn, uses [reStructuredText](http://www.sphinx-doc.org/en/stable/rest.html) as its markup language for adding code. 66 | 67 | We use the [Sphinx Autosummary extension](http://www.sphinx-doc.org/en/stable/ext/autosummary.html) to generate API references. You may want to look at `docs/api.rst` to see how these files look and where to add new functions, classes or modules. 68 | 69 | We also use the [nbsphinx extension](https://nbsphinx.readthedocs.io/en/0.5.0/) to render tutorial pages from Jupyter notebooks. 70 | 71 | To build the documentation: 72 | 73 | ```sh 74 | $ make docs 75 | ``` 76 | 77 | After this, you can find an HTML version of the documentation in `docs/_build/html/index.html`. 78 | 79 | Documentation from `master` and tagged releases is automatically built and hosted thanks to [readthedocs](https://readthedocs.org/). 80 | 81 | 82 | ## Acknowledgement 83 | 84 | If you've contributed significantly and would like your authorship to be included in subsequent uploads to [Zenodo](https://zenodo.org), please make a separate PR to add your name and affiliation to the `.zenodo.json` file. 85 | 86 | --- 87 | 88 | This document was modified from the [guidelines from the sparse project](https://github.com/pydata/sparse/blob/master/docs/contributing.rst). 89 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ilya Flyamer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include CHANGELOG.md 2 | include README.md 3 | include LICENSE 4 | include requirements.txt 5 | include requirements-dev.txt 6 | 7 | graft tests 8 | graft docs 9 | prune docs/_build 10 | prune docs/_static 11 | prune docs/_templates 12 | 13 | global-exclude __pycache__/* 14 | global-exclude *.so 15 | global-exclude *.pyd 16 | global-exclude *.pyc 17 | global-exclude .git* 18 | global-exclude .deps/* 19 | global-exclude .DS_Store 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # coolpup.py 2 | [![DOI](https://zenodo.org/badge/147190130.svg)](https://zenodo.org/badge/latestdoi/147190130) 3 | [![PyPI version](https://badge.fury.io/py/coolpuppy.svg)](https://badge.fury.io/py/coolpuppy) 4 | [![install with bioconda](https://img.shields.io/badge/install%20with-bioconda-brightgreen.svg?style=flat)](http://bioconda.github.io/recipes/coolpuppy/README.html) 5 | [![Pytest](https://github.com/open2c/coolpuppy/actions/workflows/tests.yml/badge.svg)](https://github.com/open2c/coolpuppy/actions/workflows/tests.yml) 6 | [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) 7 | [![Docs status](https://readthedocs.org/projects/coolpuppy/badge/)](https://coolpuppy.readthedocs.io/en/latest/) 8 | 9 | .**cool** file **p**ile-**up**s with **py**thon. 10 | 11 | A versatile tool to perform pile-up analysis on Hi-C data in .cool format (https://github.com/mirnylab/cooler). And who doesn't like cool pupppies? 12 | 13 | # Introduction 14 | 15 | ## What are pileups? 16 | 17 | Pileups is the generic term we use to describe any procedure that averages multiple 2D regions (snippets) of a 2D matrix, e.g. Hi-C data. In some contexts they are also known as APA (aggregate peak analysis, from Rao et al., 2014), or aggregate region/TAD analysis (in GENOVA, van der Weide et al., 2021), and other names. 18 | The most typical use case is to quantify average strength of called dots (loops) in Hi-C data, or strength of TAD boundaries. However the approach can do much more than that. 19 | This is the idea of how pileups work to check whether certain regions tend to interact with each other: 20 | 21 | Pileup schematic 22 | 23 | On the right is the more typical use case for quantification of loop strength. On the left is a different approach, designed to check whether specific regions in the genome (e.g. binding sites of a certain factor) tend to interact with each other. 24 | 25 | What is very important for this quantification, is the normalization to expected values. This can be done in two ways: either using a chromosome- (or arm-) wide by-distance expected interactions, using a file with average values of interactions at different distances (e.g. output of `cooltools expected-cis`), or directly from Hi-C data by dividing the pileups over randomly shifted control regions. If neither expected normalization approach is used (just set `--nshifts 0`), this becomes essentially identical to the APA approach (Rao et al., 2014), which can be used for averaging strongly interacting regions, e.g. annotated loops. For weaker interactors, decay of contact probability with distance can hide any focal enrichment that could be observed otherwise. However, most importantly, when comparing different sets of regions at even slightly different distances, or comparing different datasets, the decay of contact probability with distance will very strongly affect the resulting values, hence normalizing to it is essential in many cases, and generally recommended. 26 | 27 | ## `coolpup.py` vs `cooltools pileup` 28 | 29 | `cooltools` is the main package with Hi-C analysis maintained by open2C. It also has a tool to perform pileups. Why does `coolpup.py` exist then? 30 | The way `cooltools pileup` works, is it accumulates all snippets for the pileup into one 3D array (stack). Which gives a lot of flexibility in case one wants to subset the snippets based on some features later, or do some other non-standard computations based on the stack. But this is only advantageous when one performs analysis using the Python API, and moreover limits the application of `cooltools pileup` so it can't be applied to a truly large number of snippets due to memory requirements. That's where `coolpup.py` comes in: internally it never stores more than one snippet in memory, hence there is no limit to how many snippets can be processed. `coolpup.py` is particularly well suited performance-wise for analysing huge numbers of potential interactions, since it loads whole chromosomes into memory one by one (or in parallel to speed it up) to extract small submatrices quickly. Having to read everything into memory makes it relatively slow for small numbers of loops, but performance doesn't decrease until you reach a huge number of interactions. Additionally, `cooltools pileup` doesn't support inter-chromosomal (trans) pileups, however it is possible in `coolpup.py`. 31 | 32 | While there is no way to subset the snippets after the pileup is generated (since they are not stored), `coolpup.py` allows one to perform various subsetting during the pileup procedure. Builtin options in the CLI are subsetting by distance, by strand, by strand and distance at the same time, and by window/region - in case of a provided BED file, one pileup is generated for each row against all others in the same chromosome; in case of trans-pileups, pileups for each chromosome pair can be generated. Importantly, in Python API any arbitrary grouping of snippets is possible. 33 | 34 | ## .cool format 35 | 36 | .cool is a modern and flexible format to store Hi-C data. 37 | It uses HDF5 to store a sparse representation of the Hi-C data, which allows low memory requirements when dealing with high resolution datasets. Another popular format to store Hi-C data, .hic, can be converted into .cool files using `hic2cool` (https://github.com/4dn-dcic/hic2cool). 38 | 39 | See for details: 40 | 41 | Abdennur, N., and Mirny, L. (2019). Cooler: scalable storage for Hi-C data and other genomically-labeled arrays. Bioinformatics. [10.1093/bioinformatics/btz540](https://doi.org/10.1093/bioinformatics/btz540) 42 | 43 | # Getting started 44 | 45 | ## Installation 46 | All requirements apart are available from PyPI or conda. 47 | 48 | Before installing everything you need to obtain `Cython` using either pip or conda. Then for coolpuppy (and other dependencies) simply do: 49 | 50 | `pip install coolpuppy` 51 | 52 | or 53 | 54 | `pip install https://github.com/open2c/coolpuppy/archive/master.zip` 55 | 56 | to get the latest version from GitHub. This will make `coolpup.py` callable in your terminal, and importable in python as `coolpuppy`. 57 | 58 | ## Usage 59 | 60 | The basic usage syntax is as follows: 61 | 62 | `coolpup.py [OPTIONS] coolfile.cool regionfile.bed` 63 | 64 | A guide walkthrough to pile-up analysis is available here (WIP): [Walkthrough](https://coolpuppy.readthedocs.io/en/latest/walkthrough.html) 65 | 66 | Docs for the command line interface are available here: [CLI docs](https://coolpuppy.readthedocs.io/en/latest/coolpup_py_cli.html) 67 | 68 | Some examples to get you started with CLI interface are available [here](https://coolpuppy.readthedocs.io/en/latest/Examples/Walkthrough_CLI.html) and for the python API examples see [here](https://coolpuppy.readthedocs.io/en/latest/Examples/Walkthrough_API.html). 69 | 70 | ### Plotting results 71 | For flexible plotting, I suggest to use `matplotlib` or another library. However simple plotting capabilities are included in this package. Just run `plotpup.py` with desired options and list all the output files of `coolpup.py` you'd like to plot. 72 | 73 | ## Citing coolpup.py 74 | Ilya M Flyamer, Robert S Illingworth, Wendy A Bickmore (2020). Coolpup.py: versatile pile-up analysis of Hi-C data. Bioinformatics, 36, 10, 2980–2985. 75 | 76 | [https://academic.oup.com/bioinformatics/article/36/10/2980/5719023](https://academic.oup.com/bioinformatics/article/36/10/2980/5719023) 77 | 78 | doi: 10.1093/bioinformatics/btaa073 79 | 80 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | # from .coolpuppy import * 4 | # from .plotpuppy import * 5 | # from .version import __version__ 6 | -------------------------------------------------------------------------------- /coolpuppy/CLI.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from .coolpup import pileup 3 | from .lib.io import save_pileup_df, sniff_for_header 4 | from .lib.util import validate_csv 5 | 6 | # from coolpuppy import * 7 | from coolpuppy._version import __version__ 8 | from cooltools.lib import common, io 9 | import cooler 10 | import numpy as np 11 | import pandas as pd 12 | import bioframe 13 | import os 14 | import argparse 15 | import logging 16 | 17 | import sys 18 | import pdb, traceback 19 | 20 | 21 | def parse_args_coolpuppy(): 22 | parser = argparse.ArgumentParser( 23 | formatter_class=argparse.ArgumentDefaultsHelpFormatter 24 | ) 25 | parser.add_argument("cool_path", type=str, help="Cooler file with your Hi-C data") 26 | parser.add_argument( 27 | "features", 28 | type=str, 29 | help="""A 3-column bed file or a 6-column double-bed file 30 | i.e. chr1,start1,end1,chr2,start2,end2. 31 | Should be tab-delimited. 32 | 33 | With a bed file, will consider all combinations 34 | of intervals. To pileup features along the diagonal 35 | instead, use the ``--local`` argument. 36 | 37 | Can be piped in via stdin, then use "-" 38 | """, 39 | ) 40 | ##### Extra arguments 41 | parser.add_argument( 42 | "--features_format", 43 | "--features-format", 44 | "--format", 45 | "--basetype", 46 | type=str, 47 | choices=["bed", "bedpe", "auto"], 48 | help="""Format of the features. 49 | Options: 50 | bed: chrom, start, end 51 | bedpe: chrom1, start1, end1, chrom2, start2, end2 52 | auto (default): determined from the file name extension 53 | Has to be explicitly provided is features is piped through stdin""", 54 | default="auto", 55 | required=False, 56 | ) 57 | parser.add_argument( 58 | "--view", 59 | type=str, 60 | help="""Path to a file which defines which regions of the chromosomes to use""", 61 | default=None, 62 | required=False, 63 | ) 64 | parser.add_argument( 65 | "--flank", 66 | "--pad", 67 | default=100_000, 68 | type=int, 69 | required=False, 70 | help="""Flanking of the windows around the centres of specified features 71 | i.e. final size of the matrix is 2 × flank+res, in bp. 72 | Ignored with ``--rescale``, use ``--rescale_flank`` instead""", 73 | ) 74 | ### Control of controls 75 | parser.add_argument( 76 | "--minshift", 77 | default=10**5, 78 | type=int, 79 | required=False, 80 | help="""Shortest shift for random controls, bp 81 | """, 82 | ) 83 | parser.add_argument( 84 | "--maxshift", 85 | default=10**6, 86 | type=int, 87 | required=False, 88 | help="""Longest shift for random controls, bp 89 | """, 90 | ) 91 | parser.add_argument( 92 | "--nshifts", 93 | default=10, 94 | type=int, 95 | required=False, 96 | help="""Number of control regions per averaged window 97 | """, 98 | ) 99 | parser.add_argument( 100 | "--expected", 101 | default=None, 102 | type=validate_csv, 103 | required=False, 104 | help="""File with expected (output of ``cooltools compute-expected``). 105 | If None, don't use expected and use randomly shifted controls""", 106 | ) 107 | parser.add_argument( 108 | "--not_ooe", 109 | "--not-ooe", 110 | dest="ooe", 111 | default=True, 112 | action="store_false", 113 | help="""If expected is provided, will accumulate all expected snippets just like for randomly shifted controls, instead of normalizing each snippet individually""", 114 | ) 115 | # Filtering 116 | parser.add_argument( 117 | "--mindist", 118 | type=int, 119 | required=False, 120 | help="""Minimal distance of interactions to use, bp. 121 | If not provided, uses 2*flank+2 (in bins) as mindist to avoid first two 122 | diagonals""", 123 | ) 124 | parser.add_argument( 125 | "--maxdist", 126 | type=int, 127 | required=False, 128 | help="""Maximal distance of interactions to use""", 129 | ) 130 | parser.add_argument( 131 | "--ignore_diags", 132 | "--ignore-diags", 133 | type=int, 134 | default=2, 135 | required=False, 136 | help="""How many diagonals to ignore""", 137 | ) 138 | parser.add_argument( 139 | "--subset", 140 | default=0, 141 | type=int, 142 | required=False, 143 | help="""Take a random sample of the bed file. 144 | Useful for files with too many featuers to run as is, i.e. some repetitive elements. Set to 0 or lower to keep all data""", 145 | ) 146 | # Modes of action 147 | parser.add_argument( 148 | "--by_window", 149 | "--by-window", 150 | action="store_true", 151 | default=False, 152 | required=False, 153 | help="""Perform by-window pile-ups. 154 | Create a pile-up for each coordinate in the features. 155 | Not compatible with --by_strand and --by_distance. 156 | 157 | Only works with bed format features, and generates pairwise 158 | combinations of each feature against the rest.""", 159 | ) 160 | parser.add_argument( 161 | "--by_strand", 162 | "--by-strand", 163 | action="store_true", 164 | default=False, 165 | required=False, 166 | help="""Perform by-strand pile-ups. 167 | Create a separate pile-up for each strand combination in the features.""", 168 | ) 169 | parser.add_argument( 170 | "--by_distance", 171 | "--by-distance", 172 | nargs="*", 173 | required=False, 174 | help="""Perform by-distance pile-ups. 175 | Create a separate pile-up for each distance band. If empty, will use default 176 | (0,50000,100000,200000,...) edges. Specify edges using multiple argument 177 | values, e.g. `--by_distance 1000000 2000000` """, 178 | ) 179 | parser.add_argument( 180 | "--groupby", 181 | nargs="*", 182 | required=False, 183 | help="""Additional columns of features to use for groupby, space separated. 184 | If feature_format=='bed', each columns should be specified twice with suffixes 185 | '1' and '2', i.e. if features have a column 'group', specify 'group1 group2'., 186 | e.g. --groupby chrom1 chrom2""", 187 | ) 188 | parser.add_argument( 189 | "--ignore_group_order", 190 | nargs="*", 191 | required=False, 192 | help="""When using groupby, reorder so that e.g. group1-group2 and group2-group1 will be 193 | combined into one and flipped to the correct orientation. If using multiple paired 194 | groupings (e.g. group1-group2 and category1-category2), need to specify which 195 | grouping should be prioritised, e.g. "group" or "group1 group2". For flip_negative_strand, 196 | +- and -+ strands will be combined""", 197 | ) 198 | parser.add_argument( 199 | "--flip_negative_strand", 200 | "--flip-negative-strand", 201 | action="store_true", 202 | default=False, 203 | required=False, 204 | help="""Flip snippets so the positive strand always points to bottom-right. 205 | Requires strands to be annotated for each feature (or two strands for 206 | bedpe format features)""", 207 | ) 208 | parser.add_argument( 209 | "--local", 210 | action="store_true", 211 | default=False, 212 | required=False, 213 | help="""Create local pileups, i.e. along the diagonal""", 214 | ) 215 | parser.add_argument( 216 | "--coverage_norm", 217 | "--coverage-norm", 218 | default="", 219 | type=str, 220 | required=False, 221 | nargs="?", 222 | const="total", 223 | help=""" 224 | Normalize the final pileup by accumulated coverage as an alternative to balancing. 225 | Useful for single-cell Hi-C data. Can be a string: "cis" or "total" to use 226 | "cov_cis_raw" or "cov_tot_raw" columns in the cooler bin table, respectively. 227 | If they are not present, will calculate coverage with same ignore_diags as 228 | used in coolpup.py and store result in the cooler. 229 | Alternatively, if a different string is provided, will attempt to use a 230 | column with the that name in the cooler bin table, and will raise a 231 | ValueError if it does not exist. 232 | If no argument is given following the option string, will use "total". 233 | Only allowed when using empty --clr_weight_name""", 234 | ) 235 | parser.add_argument( 236 | "--trans", 237 | action="store_true", 238 | default=False, 239 | required=False, 240 | help="""Perform inter-chromosomal (trans) pileups. 241 | This ignores all contacts in cis.""", 242 | ) 243 | parser.add_argument( 244 | "--store_stripes", 245 | action="store_true", 246 | default=False, 247 | required=False, 248 | help="""Store horizontal and vertical stripes in pileup output""", 249 | ) 250 | 251 | # Rescaling 252 | parser.add_argument( 253 | "--rescale", 254 | action="store_true", 255 | default=False, 256 | required=False, 257 | help="""Rescale all features to the same size. 258 | Do not use centres of features and flank, and rather use the actual 259 | feature sizes and rescale pileups to the same shape and size""", 260 | ) 261 | parser.add_argument( 262 | "--rescale_flank", 263 | "--rescale_pad", 264 | "--rescale-flank", 265 | "--rescale-pad", 266 | default=1.0, 267 | required=False, 268 | type=float, 269 | help="""If --rescale, flanking in fraction of feature length""", 270 | ) 271 | parser.add_argument( 272 | "--rescale_size", 273 | "--rescale-size", 274 | type=int, 275 | default=99, 276 | required=False, 277 | help="""Size to rescale to. 278 | If ``--rescale``, used to determine the final size of the pileup, 279 | i.e. it will be size×size. Due to technical limitation in the current 280 | implementation, has to be an odd number""", 281 | ) 282 | # Balancing 283 | parser.add_argument( 284 | "--clr_weight_name", 285 | "--weight_name", 286 | "--clr-weight-name", 287 | "--weight-name", 288 | default="weight", 289 | type=str, 290 | required=False, 291 | nargs="?", 292 | const=None, 293 | help="""Name of the norm to use for getting balanced data. 294 | Provide empty argument to calculate pileups on raw data 295 | (no masking bad pixels).""", 296 | ) 297 | # Output 298 | parser.add_argument( 299 | "-o", 300 | "--outname", 301 | "--output", 302 | default="auto", 303 | type=str, 304 | required=False, 305 | help="""Name of the output file. 306 | If not set, file is saved in the current directory and the name is 307 | generated automatically to include important information and avoid 308 | overwriting files generated with different settings.""", 309 | ) 310 | # Technicalities 311 | parser.add_argument( 312 | "-p", 313 | "--nproc", 314 | "--n_proc", 315 | "--n-proc", 316 | default=1, 317 | type=int, 318 | required=False, 319 | dest="n_proc", 320 | help="""Number of processes to use. 321 | Each process works on a separate chromosome, so might require quite a 322 | bit more memory, although the data are always stored as sparse matrices. 323 | Set to 0 to use all available cores. 324 | """, 325 | ) 326 | parser.add_argument( 327 | "--seed", 328 | default=None, 329 | type=int, 330 | required=False, 331 | help="""Set specific seed value to ensure reproducibility""", 332 | ) 333 | parser.add_argument( 334 | "-l", 335 | "--log", 336 | dest="logLevel", 337 | choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], 338 | default="INFO", 339 | help="Set the logging level", 340 | ) 341 | parser.add_argument( 342 | "--post_mortem", 343 | "--post-mortem", 344 | action="store_true", 345 | default=False, 346 | required=False, 347 | help="""Enter debugger if there is an error""", 348 | ) 349 | parser.add_argument("-v", "--version", action="version", version=__version__) 350 | return parser 351 | 352 | 353 | def main(): 354 | parser = parse_args_coolpuppy() 355 | args = parser.parse_args() 356 | 357 | if args.post_mortem: 358 | 359 | def _excepthook(exc_type, value, tb): 360 | traceback.print_exception(exc_type, value, tb) 361 | print() 362 | pdb.pm() 363 | 364 | sys.excepthook = _excepthook 365 | if args.by_distance is not None: 366 | if len(args.by_distance) > 0: 367 | try: 368 | distance_edges = [int(item) for item in args.by_distance] 369 | except: 370 | raise ValueError( 371 | "Distance edges must be integers. Separate edges with spaces." 372 | ) 373 | else: 374 | distance_edges = "default" 375 | args.by_distance = True 376 | else: 377 | args.by_distance = False 378 | distance_edges = False 379 | 380 | if args.ignore_group_order is not None: 381 | if len(args.ignore_group_order) > 0: 382 | try: 383 | args.ignore_group_order = [str(item) for item in args.ignore_group_order] 384 | except: 385 | raise ValueError( 386 | "ignore_group_order must be one or two strings separated with spaces." 387 | ) 388 | else: 389 | args.ignore_group_order = True 390 | else: 391 | args.ignore_group_order = False 392 | 393 | logger = logging.getLogger("coolpuppy") 394 | logger.setLevel(getattr(logging, args.logLevel)) 395 | 396 | logger.debug(args) 397 | 398 | if args.seed is not None: 399 | np.random.seed(args.seed) 400 | 401 | if args.n_proc == 0: 402 | nproc = -1 403 | else: 404 | nproc = args.n_proc 405 | 406 | clr = cooler.Cooler(args.cool_path) 407 | 408 | coolname = os.path.basename(clr.filename) 409 | if args.features != "-": 410 | bedname, ext = os.path.splitext(os.path.basename(args.features)) 411 | features = args.features 412 | buf, names, ncols = sniff_for_header(features) 413 | if args.features_format == "auto": 414 | schema = ext[1:] 415 | else: 416 | schema = args.features_format 417 | if schema == "bed": 418 | schema = "bed12" 419 | features_format = "bed" 420 | dtypes = {"chrom": str, 421 | "start": np.int64, 422 | "end": np.int64,} 423 | else: 424 | features_format = "bedpe" 425 | dtypes = { 426 | "chrom1": str, 427 | "start1": np.int64, 428 | "end1": np.int64, 429 | "chrom2": str, 430 | "start2": np.int64, 431 | "end2": np.int64, 432 | } 433 | if (features_format == "bedpe") & (ncols < 6): 434 | raise ValueError("Too few columns") 435 | elif ncols < 3: 436 | raise ValueError("Too few columns") 437 | if names is not None: 438 | features = pd.read_table(buf, dtype=dtypes) 439 | else: 440 | features = bioframe.read_table( 441 | features, schema=schema, index_col=False, dtype=dtypes 442 | ) 443 | else: 444 | if args.features_format == "auto": 445 | raise ValueError( 446 | "Can't determine format when features is piped in, please specify" 447 | ) 448 | schema = args.features_format 449 | if schema == "bed": 450 | schema = "bed12" 451 | features_format = "bed" 452 | dtypes = {"chrom": str, 453 | "start": np.int64, 454 | "end": np.int64,} 455 | else: 456 | features_format = "bedpe" 457 | dtypes = { 458 | "chrom1": str, 459 | "start1": np.int64, 460 | "end1": np.int64, 461 | "chrom2": str, 462 | "start2": np.int64, 463 | "end2": np.int64, 464 | } 465 | bedname = "stdin" 466 | buf, names, ncols = sniff_for_header(sys.stdin) 467 | if (features_format == "bedpe") & (ncols < 6): 468 | raise ValueError("Too few columns") 469 | elif ncols < 3: 470 | raise ValueError("Too few columns") 471 | if names is not None: 472 | features = pd.read_table(buf, dtype=dtypes) 473 | else: 474 | features = bioframe.read_table(buf, schema=schema, index_col=False, dtype=dtypes) 475 | 476 | 477 | if args.view is None: 478 | # full chromosome case 479 | view_df = common.make_cooler_view(clr) 480 | else: 481 | # Read view_df dataframe, and verify against cooler 482 | view_df = io.read_viewframe_from_file(args.view, clr, check_sorting=True) 483 | 484 | if args.expected is None: 485 | expected = None 486 | expected_value_col = None 487 | else: 488 | expected_path, expected_value_col = args.expected 489 | expected_value_cols = [ 490 | expected_value_col, 491 | ] 492 | if args.trans: 493 | expected = io.read_expected_from_file( 494 | expected_path, 495 | contact_type="trans", 496 | expected_value_cols=expected_value_cols, 497 | verify_view=view_df, 498 | verify_cooler=clr, 499 | ) 500 | else: 501 | expected = io.read_expected_from_file( 502 | expected_path, 503 | contact_type="cis", 504 | expected_value_cols=expected_value_cols, 505 | verify_view=view_df, 506 | verify_cooler=clr, 507 | ) 508 | args.nshifts = 0 509 | 510 | if args.mindist is None: 511 | mindist = "auto" 512 | else: 513 | mindist = args.mindist 514 | 515 | if args.maxdist is None: 516 | maxdist = np.inf 517 | else: 518 | maxdist = args.maxdist 519 | 520 | if args.rescale and args.rescale_size % 2 == 0: 521 | raise ValueError("Please provide an odd rescale_size") 522 | if not args.rescale: 523 | rescale_flank = None 524 | else: 525 | rescale_flank = args.rescale_flank 526 | 527 | if args.by_window: 528 | if schema != "bed12": 529 | raise ValueError("Can't make by-window pileups without making combinations") 530 | if args.local: 531 | raise ValueError("Can't make local by-window pileups") 532 | 533 | pups = pileup( 534 | clr=clr, 535 | features=features, 536 | features_format=features_format, 537 | view_df=view_df, 538 | expected_df=expected, 539 | expected_value_col=expected_value_col, 540 | clr_weight_name=args.clr_weight_name, 541 | flank=args.flank, 542 | minshift=args.minshift, 543 | maxshift=args.maxshift, 544 | nshifts=args.nshifts, 545 | ooe=args.ooe, 546 | mindist=mindist, 547 | maxdist=maxdist, 548 | min_diag=args.ignore_diags, 549 | subset=args.subset, 550 | by_window=args.by_window, 551 | by_strand=args.by_strand, 552 | by_distance=distance_edges, 553 | groupby=[] if args.groupby is None else args.groupby, 554 | ignore_group_order=args.ignore_group_order, 555 | flip_negative_strand=args.flip_negative_strand, 556 | local=args.local, 557 | coverage_norm=args.coverage_norm, 558 | trans=args.trans, 559 | rescale=args.rescale, 560 | rescale_flank=rescale_flank, 561 | rescale_size=args.rescale_size, 562 | store_stripes=args.store_stripes, 563 | nproc=nproc, 564 | seed=args.seed, 565 | ) 566 | 567 | if args.outname == "auto": 568 | outname = f"{coolname}-{clr.binsize / 1000}K_over_{bedname}" 569 | if args.nshifts > 0 and args.expected is None: 570 | outname += f"_{args.nshifts}-shifts" 571 | if args.expected is not None: 572 | outname += "_expected" 573 | if args.nshifts <= 0 and args.expected is None: 574 | outname += "_noNorm" 575 | if args.local: 576 | outname += "_local" 577 | elif args.mindist is not None or args.maxdist is not None: 578 | outname += f"_dist_{mindist}-{maxdist}" 579 | if args.rescale: 580 | outname += "_rescaled" 581 | if args.coverage_norm: 582 | outname += "_covnorm" 583 | if args.subset > 0: 584 | outname += f"_subset-{args.subset}" 585 | if args.by_window: 586 | outname += "_by-window" 587 | if args.by_strand: 588 | outname += "_by-strand" 589 | if args.trans: 590 | outname += "_trans" 591 | if args.groupby: 592 | outname += f"_by-{'_'.join(args.groupby)}" 593 | outname += ".clpy" 594 | else: 595 | outname = args.outname 596 | 597 | if args.expected: 598 | pups["expected_file"] = expected_path 599 | if args.view: 600 | pups["view_file"] = args.view 601 | pups["features"] = args.features 602 | save_pileup_df(outname, pups) 603 | logger.info(f"Saved output to {outname}") 604 | -------------------------------------------------------------------------------- /coolpuppy/__init__.py: -------------------------------------------------------------------------------- 1 | # from coolpuppy import * 2 | -------------------------------------------------------------------------------- /coolpuppy/_version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | __version__ = "1.1.0" 5 | -------------------------------------------------------------------------------- /coolpuppy/divide_pups_CLI.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from .lib.io import load_pileup_df, save_pileup_df 3 | from .lib.puputils import divide_pups 4 | 5 | from ._version import __version__ 6 | import argparse 7 | import logging 8 | 9 | 10 | def parse_args_divide_pups(): 11 | parser = argparse.ArgumentParser( 12 | formatter_class=argparse.ArgumentDefaultsHelpFormatter 13 | ) 14 | parser.add_argument( 15 | "input_pups", type=str, nargs="+", help="""Two pileups to divide""" 16 | ) 17 | parser.add_argument("-v", "--version", action="version", version=__version__) 18 | 19 | # Output 20 | parser.add_argument( 21 | "-o", 22 | "--outname", 23 | default="auto", 24 | type=str, 25 | required=False, 26 | help="""Name of the output file. 27 | If not set, file is saved in the current directory and the name is 28 | generated automatically.""", 29 | ) 30 | return parser 31 | 32 | 33 | def main(): 34 | parser = parse_args_divide_pups() 35 | args = parser.parse_args() 36 | 37 | logging.info(args) 38 | 39 | if len(args.input_pups) != 2: 40 | raise ValueError("Need exactly two input pups") 41 | else: 42 | pup1 = load_pileup_df(args.input_pups[0]) 43 | pup2 = load_pileup_df(args.input_pups[1]) 44 | pups = divide_pups(pup1, pup2) 45 | 46 | if args.outname == "auto": 47 | outname = f"{str(args.input_pups[0])}_over_{str(args.input_pups[1])}.clpy" 48 | else: 49 | outname = args.outname 50 | 51 | save_pileup_df(outname, pups) 52 | logging.info(f"Saved output to {outname}") 53 | -------------------------------------------------------------------------------- /coolpuppy/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/coolpuppy/lib/__init__.py -------------------------------------------------------------------------------- /coolpuppy/lib/io.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import numpy as np 3 | from scipy import sparse 4 | import pandas as pd 5 | import h5sparse 6 | import re 7 | import os 8 | import yaml 9 | import io 10 | import gzip 11 | import csv 12 | import logging 13 | from coolpuppy._version import __version__ 14 | 15 | logger = logging.getLogger("coolpuppy") 16 | 17 | 18 | def save_pileup_df(filename, df, metadata=None, mode="w", compression="lzf"): 19 | """ 20 | Saves a dataframe with metadata into a binary HDF5 file` 21 | 22 | Parameters 23 | ---------- 24 | filename : str 25 | File to save to. 26 | df : pd.DataFrame 27 | DataFrame to save into binary hdf5 file. 28 | metadata : dict, optional 29 | Dictionary with meatadata. 30 | mode : str, optional 31 | Mode for the first time access to the output file: 'w' to overwrite if file 32 | exists, or 'a' to fail if output file already exists 33 | compression : str, optional 34 | Compression to use for saving, e.g. 'gzip'. Defaults to 'lzf' 35 | 36 | Returns 37 | ------- 38 | None. 39 | 40 | Notes 41 | ----- 42 | Replaces `None` in metadata values with `False`, since HDF5 doesn't support `None` 43 | 44 | """ 45 | if metadata is None: 46 | metadata = {} 47 | df[ 48 | df.columns[ 49 | ~df.columns.isin( 50 | ["data", "vertical_stripe", "horizontal_stripe", "coordinates"] 51 | ) 52 | ] 53 | ].to_hdf(filename, "annotation", mode=mode) 54 | 55 | with h5sparse.File(filename, "a") as f: 56 | width = df["data"].iloc[0].shape[0] 57 | height = width * df["data"].shape[0] 58 | ds = f.create_dataset( 59 | "data", 60 | compression=compression, 61 | chunks=(width, width), 62 | shape=(height, width), 63 | ) 64 | for i, arr in df["data"].reset_index(drop=True).items(): 65 | ds[i * width : (i + 1) * width, :] = arr 66 | if df["store_stripes"].any(): 67 | for i, arr in df["vertical_stripe"].reset_index(drop=True).items(): 68 | f.create_dataset( 69 | "vertical_stripe_" + str(i), 70 | compression=compression, 71 | shape=(len(arr), width), 72 | data=sparse.csr_matrix(arr), 73 | ) 74 | for i, arr in df["horizontal_stripe"].reset_index(drop=True).items(): 75 | f.create_dataset( 76 | "horizontal_stripe_" + str(i), 77 | compression=compression, 78 | shape=(len(arr), width), 79 | data=sparse.csr_matrix(arr), 80 | ) 81 | for i, arr in df["coordinates"].reset_index(drop=True).items(): 82 | f.create_dataset( 83 | "coordinates_" + str(i), 84 | compression=compression, 85 | shape=(len(arr), 6), 86 | data=arr.astype(object), 87 | ) 88 | group = f.create_group("attrs") 89 | if metadata is not None: 90 | for key, val in metadata.items(): 91 | if val is None: 92 | val = False 93 | group.attrs[key] = val 94 | group.attrs["version"] = __version__ 95 | return 96 | 97 | 98 | def load_pileup_df(filename, quaich=False, skipstripes=False): 99 | """ 100 | Loads a dataframe saved using `save_pileup_df` 101 | 102 | Parameters 103 | ---------- 104 | filename : str 105 | File to load from. 106 | quaich : bool, optional 107 | Whether to assume standard quaich file naming to extract sample name and bedname. 108 | The default is False. 109 | 110 | Returns 111 | ------- 112 | annotation : pd.DataFrame 113 | Pileups are in the "data" column, all metadata in other columns 114 | 115 | """ 116 | with h5sparse.File(filename, "r", libver="latest") as f: 117 | metadata = dict(zip(f["attrs"].attrs.keys(), f["attrs"].attrs.values())) 118 | dstore = f["data"] 119 | data = [] 120 | for chunk in dstore.iter_chunks(): 121 | chunk = dstore[chunk] 122 | data.append(chunk) 123 | annotation = pd.read_hdf(filename, "annotation") 124 | annotation["data"] = data 125 | vertical_stripe = [] 126 | horizontal_stripe = [] 127 | coordinates = [] 128 | if not skipstripes: 129 | try: 130 | for i in range(len(data)): 131 | vstripe = "vertical_stripe_" + str(i) 132 | hstripe = "horizontal_stripe_" + str(i) 133 | coords = "coordinates_" + str(i) 134 | vertical_stripe.append(f[vstripe][:].toarray()) 135 | horizontal_stripe.append(f[hstripe][:].toarray()) 136 | coordinates.append(f[coords][:].astype("U13")) 137 | annotation["vertical_stripe"] = vertical_stripe 138 | annotation["horizontal_stripe"] = horizontal_stripe 139 | annotation["coordinates"] = coordinates 140 | except KeyError: 141 | pass 142 | for key, val in metadata.items(): 143 | if key != "version": 144 | annotation[key] = val 145 | elif val != __version__: 146 | logger.debug( 147 | f"pileup generated with v{val}. Current version is v{__version__}" 148 | ) 149 | if quaich: 150 | basename = os.path.basename(filename) 151 | sample, bedname = re.search( 152 | "^(.*)-(?:[0-9]+)_over_(.*)_(?:[0-9]+-shifts|expected).*\.clpy", basename 153 | ).groups() 154 | annotation["sample"] = sample 155 | annotation["bedname"] = bedname 156 | return annotation 157 | 158 | 159 | def load_pileup_df_list(files, quaich=False, nice_metadata=True, skipstripes=False): 160 | """ 161 | 162 | Parameters 163 | ---------- 164 | files : iterable 165 | Files to read pileups from. 166 | quaich : bool, optional 167 | Whether to assume standard quaich file naming to extract sample name and bedname. 168 | The default is False. 169 | nice_metadata : bool, optional 170 | Whether to add nicer metadata for direct plotting. The default is True. 171 | Adds a "norm" column ("expected", "shifts" or "none"). 172 | 173 | 174 | Returns 175 | ------- 176 | pups : pd.DataFrame 177 | Combined dataframe with all pileups and annotations from all files. 178 | 179 | """ 180 | pups = pd.concat( 181 | [load_pileup_df(path, quaich=quaich, skipstripes=skipstripes) for path in files] 182 | ).reset_index(drop=True) 183 | if nice_metadata: 184 | pups["norm"] = np.where( 185 | pups["expected"], ["expected"] * pups.shape[0], ["shifts"] * pups.shape[0] 186 | ).astype(str) 187 | pups.loc[ 188 | np.logical_not(np.logical_or(pups["nshifts"] > 0, pups["expected"])), "norm" 189 | ] = "none" 190 | return pups 191 | 192 | 193 | def save_array_with_header(array, header, filename): 194 | """Save a numpy array with a YAML header generated from a dictionary 195 | 196 | Parameters 197 | ---------- 198 | array : np.array 199 | Array to save. 200 | header : dict 201 | Dictionaty to save into the header. 202 | filename : string 203 | Name of file to save array and metadata into. 204 | 205 | """ 206 | header = yaml.dump(header).strip() 207 | np.savetxt(filename, array, header=header) 208 | 209 | 210 | def load_array_with_header(filename): 211 | """Load array from files generated using `save_array_with_header`. 212 | They are simple txt files with an optional header in the first lines, commented 213 | using "# ". If uncommented, the header is in YAML. 214 | 215 | Parameters 216 | ---------- 217 | filename : string 218 | File to load from. 219 | 220 | Returns 221 | ------- 222 | data : dict 223 | Dictionary with information from the header. Access the associated data in an 224 | array using data['data']. 225 | 226 | """ 227 | with open(filename) as f: 228 | read_data = f.read() 229 | 230 | lines = read_data.split("\n") 231 | header = "\n".join([line[2:] for line in lines if line.startswith("# ")]) 232 | if len(header) > 0: 233 | metadata = yaml.load(header, Loader=yaml.FullLoader) 234 | else: 235 | metadata = {} 236 | data = "\n".join([line for line in lines if not line.startswith("# ")]) 237 | with io.StringIO(data) as f: 238 | metadata["data"] = np.loadtxt(f) 239 | return metadata 240 | 241 | 242 | def is_gz_file(filepath): 243 | with open(filepath, "rb") as test_f: 244 | return test_f.read(2) == b"\x1f\x8b" 245 | 246 | 247 | def sniff_for_header(file, sep="\t", comment="#"): 248 | """ 249 | Warning: reads the entire file into a StringIO buffer! 250 | """ 251 | if isinstance(file, str): 252 | if is_gz_file(file): 253 | with gzip.open(file, "rt") as f: 254 | buf = io.StringIO(f.read()) 255 | else: 256 | with open(file, "r") as f: 257 | buf = io.StringIO(f.read()) 258 | else: 259 | buf = io.StringIO(file.read()) 260 | 261 | sample_lines = [] 262 | for line in buf: 263 | if not line.startswith(comment): 264 | sample_lines.append(line) 265 | break 266 | for _ in range(10): 267 | sample_lines.append(buf.readline()) 268 | buf.seek(0) 269 | 270 | has_header = csv.Sniffer().has_header("\n".join(sample_lines)) 271 | if has_header: 272 | names = sample_lines[0].strip().split(sep) 273 | else: 274 | names = None 275 | 276 | ncols = len(sample_lines[0].strip().split(sep)) 277 | 278 | return buf, names, ncols 279 | -------------------------------------------------------------------------------- /coolpuppy/lib/numutils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import numpy as np 3 | from cooltools import numutils as ctutils 4 | 5 | 6 | def _copy_array_halves(x): 7 | cntr = int(np.floor(x.shape[1] / 2)) 8 | x[:, : (cntr + 1)] = np.fliplr(x[:, cntr:]) 9 | return x 10 | 11 | 12 | def corner_cv(amap, i=4): 13 | """Get coefficient of variation for upper left and lower right corners of a pileup 14 | to estimate how noisy it is 15 | 16 | Parameters 17 | ---------- 18 | amap : 2D array 19 | Pileup. 20 | i : int, optional 21 | How many bins to use from each upper left and lower right corner: final corner 22 | shape is i^2. 23 | The default is 4. 24 | 25 | Returns 26 | ------- 27 | CV : float 28 | Coefficient of variation for the corner pixels. 29 | 30 | """ 31 | corners = np.concatenate((amap[0:i, 0:i], amap[-i:, -i:])) 32 | corners = corners[np.isfinite(corners)] 33 | return np.std(corners) / np.mean(corners) 34 | 35 | 36 | def norm_cis(amap, i=3): 37 | """Normalize the pileup by mean of pixels from upper left and lower right corners 38 | 39 | Parameters 40 | ---------- 41 | amap : 2D array 42 | Pileup. 43 | i : int, optional 44 | How many bins to use from each upper left and lower right corner: final corner 45 | shape is i^2. 0 will not normalize. 46 | The default is 3. 47 | 48 | Returns 49 | ------- 50 | amap : 2D array 51 | Normalized pileup. 52 | 53 | """ 54 | if i > 0: 55 | return amap / np.nanmean((amap[0:i, 0:i] + amap[-i:, -i:])) * 2 56 | else: 57 | return amap 58 | 59 | 60 | def get_enrichment(amap, n): 61 | """Get values from the center of a pileup for a square with side *n* 62 | 63 | Parameters 64 | ---------- 65 | amap : 2D array 66 | Pileup. 67 | n : int 68 | Side of the central square to use. 69 | 70 | Returns 71 | ------- 72 | enrichment : float 73 | Mean of the pixels in the central square. 74 | 75 | """ 76 | c = amap.shape[0] // 2 77 | if c < n: 78 | raise ValueError(f"Central pixel value {n} is too large, can be maximum {c}") 79 | return np.nanmean(amap[c - n // 2 : c + n // 2 + 1, c - n // 2 : c + n // 2 + 1]) 80 | 81 | 82 | def get_local_enrichment(amap, flank=1): 83 | """Get values for a square from the central part of a pileup, ignoring padding 84 | 85 | Parameters 86 | ---------- 87 | amap : 2D array 88 | Pileup. 89 | flank : int 90 | Relative padding used, i.e. if 1 the central third is used, if 2 the central 91 | fifth is used. 92 | The default is 1. 93 | 94 | Returns 95 | ------- 96 | enrichment : float 97 | Mean of the pixels in the central square. 98 | 99 | """ 100 | c = amap.shape[0] / (flank * 2 + 1) 101 | assert int(c) == c 102 | c = int(c) 103 | return np.nanmean(amap[c:-c, c:-c]) 104 | 105 | 106 | def get_domain_score(amap, flank=1): 107 | """Divide sum of values in a square from the central part of a matrix by the upper 108 | and right rectangles corresponding to interactions of the central region with 109 | its surroundings. 110 | 111 | Parameters 112 | ---------- 113 | amap : 2D array 114 | Pileup. 115 | flank : int 116 | Relative padding used, i.e. if 1 the central third is used, if 2 the central 117 | fifth is used. 118 | The default is 1. 119 | 120 | Returns 121 | ------- 122 | score : float 123 | Domain score. 124 | 125 | """ 126 | c = amap.shape[0] / (flank * 2 + 1) 127 | assert int(c) == c 128 | c = int(c) 129 | central = np.nansum(amap[c:-c, c:-c]) 130 | top = np.nansum(amap[:c, c:-c]) 131 | right = np.nansum(amap[c:-c, -c:]) 132 | return central / (top + right) * 2 133 | 134 | 135 | def get_insulation_strength(amap, ignore_central=0, ignore_diags=2): 136 | """Divide values in upper left and lower right corners over upper right and lower 137 | left, ignoring the central bins. 138 | 139 | Parameters 140 | ---------- 141 | amap : 2D array 142 | Pileup. 143 | ignore_central : int, optional 144 | How many central bins to ignore. Has to be odd or 0. The default is 0. 145 | 146 | Returns 147 | ------- 148 | float 149 | Insulation strength. 150 | 151 | """ 152 | for d in range(ignore_diags): 153 | amap = ctutils.fill_diag(amap, np.nan, d) 154 | if d != 0: 155 | amap = ctutils.fill_diag(amap, np.nan, -d) 156 | if ignore_central != 0 and ignore_central % 2 != 1: 157 | raise ValueError(f"ignore_central has to be odd (or 0), got {ignore_central}") 158 | i = (amap.shape[0] - ignore_central) // 2 159 | intra = np.nanmean(np.concatenate([amap[:i, :i].ravel(), amap[-i:, -i:].ravel()])) 160 | inter = np.nanmean(np.concatenate([amap[:i, -i:].ravel(), amap[-i:, :i].ravel()])) 161 | return intra / inter 162 | 163 | 164 | def _prepare_single(item): 165 | """(Deprecated) Generate enrichment and corner CV, reformat into a list 166 | 167 | Parameters 168 | ---------- 169 | item : tuple 170 | Key, (n, pileup). 171 | 172 | Returns 173 | ------- 174 | list 175 | Concatenated list of key, n, enrichment1, enrichment3, cv3, cv5. 176 | 177 | """ 178 | key, (n, amap) = item 179 | enr1 = get_enrichment(amap, 1) 180 | enr3 = get_enrichment(amap, 3) 181 | cv3 = corner_cv(amap, 3) 182 | cv5 = corner_cv(amap, 5) 183 | return list(key) + [n, enr1, enr3, cv3, cv5] 184 | -------------------------------------------------------------------------------- /coolpuppy/lib/puputils.py: -------------------------------------------------------------------------------- 1 | from .numutils import get_enrichment, get_domain_score, get_insulation_strength 2 | 3 | import numpy as np 4 | import pandas as pd 5 | from more_itertools import collapse 6 | import logging 7 | import warnings 8 | 9 | logger = logging.getLogger("coolpuppy") 10 | 11 | 12 | def _add_snip(outdict, key, snip, extra_funcs=None): 13 | if key not in outdict: 14 | outdict[key] = {key: snip[key] for key in ["data", "cov_start", "cov_end"]} 15 | outdict[key]["coordinates"] = [snip["coordinates"]] 16 | outdict[key]["horizontal_stripe"] = [snip["horizontal_stripe"]] 17 | outdict[key]["vertical_stripe"] = [snip["vertical_stripe"]] 18 | outdict[key]["num"] = np.isfinite(snip["data"]).astype(int) 19 | outdict[key]["n"] = 1 20 | else: 21 | outdict[key]["data"] = np.nansum([outdict[key]["data"], snip["data"]], axis=0) 22 | outdict[key]["num"] += np.isfinite(snip["data"]).astype(int) 23 | outdict[key]["cov_start"] = np.nansum( 24 | [outdict[key]["cov_start"], snip["cov_start"]], axis=0 25 | ) 26 | outdict[key]["cov_end"] = np.nansum( 27 | [outdict[key]["cov_end"], snip["cov_end"]], axis=0 28 | ) 29 | outdict[key]["n"] += 1 30 | outdict[key]["horizontal_stripe"] = outdict[key]["horizontal_stripe"] + [ 31 | snip["horizontal_stripe"] 32 | ] 33 | outdict[key]["vertical_stripe"] = outdict[key]["vertical_stripe"] + [ 34 | snip["vertical_stripe"] 35 | ] 36 | outdict[key]["coordinates"] = outdict[key]["coordinates"] + [ 37 | snip["coordinates"] 38 | ] 39 | if extra_funcs is not None: 40 | for key2, func in extra_funcs.items(): 41 | outdict[key] = func(outdict[key], snip) 42 | 43 | 44 | def get_score(pup, center=3, ignore_central=3): 45 | """Calculate a reasonable score for any kind of pileup 46 | For non-local (off-diagonal) pileups, calculates average signal in the central 47 | pixels (based on 'center'). 48 | For local non-rescaled pileups calculates insulation strength, and ignores the 49 | central bins (based on 'ignore_central') 50 | For local rescaled pileups calculates enrichment in the central rescaled area 51 | relative to the two neighouring areas on the sides. 52 | 53 | Parameters 54 | ---------- 55 | pup : pd.Series or dict 56 | Series or dict with pileup in 'data' and annotations in other keys. 57 | Will correctly calculate enrichment score with annotations in 'local' (book), 58 | 'rescale' (bool) and 'rescale_flank' (float) 59 | enrichment : int, optional 60 | Passed to 'get_enrichment' to calculate the average strength of central pixels. 61 | The default is 3. 62 | ignore_central : int, optional 63 | How many central bins to ignore for calculation of insulation in local pileups. 64 | The default is 3. 65 | 66 | Returns 67 | ------- 68 | float 69 | Score. 70 | 71 | """ 72 | if not pup["local"]: 73 | logger.debug(f"Calculating enrichment for the central {center} pixels") 74 | return get_enrichment(pup["data"], center) 75 | else: 76 | if pup["rescale"]: 77 | logger.debug( 78 | "Calculating domain enrichment for the central rescaled domain versus surrounding" 79 | ) 80 | return get_domain_score(pup["data"], pup["rescale_flank"]) 81 | else: 82 | logger.debug( 83 | "Calculating insulation score, i.e., upper left and lower right corners over upper right and lower left corners" 84 | ) 85 | return get_insulation_strength(pup["data"], ignore_central) 86 | 87 | 88 | def sum_pups(pup1, pup2, extra_funcs={}): 89 | """ 90 | Preserves data, stripes, cov_start, cov_end, n, num and coordinates 91 | Assumes n=1 if not present, and calculates num if not present 92 | If store_stripes is set to False, stripes and coordinates will be empty 93 | 94 | extra_funcs allows to give arbitrary functions to accumulate extra information 95 | from the two pups. 96 | """ 97 | pup1["data"] = np.nan_to_num(pup1["data"]) 98 | pup2["data"] = np.nan_to_num(pup2["data"]) 99 | pup = { 100 | "data": pup1["data"] + pup2["data"], 101 | "cov_start": pup1["cov_start"] + pup2["cov_start"], 102 | "cov_end": pup1["cov_end"] + pup2["cov_end"], 103 | "n": pup1.get("n", 1) + pup2.get("n", 1), 104 | "num": pup1.get("num", np.isfinite(pup1["data"]).astype(int)) 105 | + pup2.get("num", np.isfinite(pup2["data"]).astype(int)), 106 | "horizontal_stripe": pup1["horizontal_stripe"] + pup2["horizontal_stripe"], 107 | "vertical_stripe": pup1["vertical_stripe"] + pup2["vertical_stripe"], 108 | "coordinates": pup1["coordinates"] + pup2["coordinates"], 109 | } 110 | if extra_funcs: 111 | for key, func in extra_funcs.items(): 112 | pup = func(pup1, pup2) 113 | return pd.Series(pup) 114 | 115 | 116 | def divide_pups(pup1, pup2): 117 | """ 118 | Divide two pups and get the resulting pup. Requires that the pups have identical shapes, resolutions, flanks, etc. If pups contain stripes, these will only be divided if stripes have identical coordinates. 119 | """ 120 | drop_columns = [ 121 | "control_n", 122 | "control_num", 123 | "n", 124 | "num", 125 | "clr", 126 | "chroms", 127 | "minshift", 128 | "expected_file", 129 | "group", 130 | "maxshift", 131 | "mindist", 132 | "maxdist", 133 | "subset", 134 | "seed", 135 | "data", 136 | "horizontal_stripe", 137 | "vertical_stripe", 138 | "cooler", 139 | "features", 140 | "outname", 141 | "coordinates", 142 | ] 143 | if pup1.shape[0] > 1 or pup2.shape[0] > 1: 144 | raise ValueError("Pileups cannot contain multiple conditions") 145 | pup1 = pup1.reset_index(drop=True) 146 | pup2 = pup2.reset_index(drop=True) 147 | drop_columns = list(set(drop_columns) & set(pup1.columns)) 148 | div_pup = pup1.drop(columns=drop_columns) 149 | for col in div_pup.columns: 150 | if np.all(np.sort(pup1[col]) != np.sort(pup2[col])): 151 | warnings.warn(f"Note that {col} is different between the two pileups") 152 | div_pup["data"] = pup1["data"] / pup2["data"] 153 | div_pup["clrs"] = str(pup1["clr"]) + "/" + str(pup2["clr"]) 154 | div_pup["n"] = pup1["n"] + pup2["n"] 155 | if set(["vertical_stripe", "horizontal_stripe"]).issubset(pup1.columns): 156 | if np.all(np.sort(pup1["coordinates"]) == np.sort(pup2["coordinates"])): 157 | div_pup["coordinates"] = pup1["coordinates"] 158 | for stripe in ["vertical_stripe", "horizontal_stripe"]: 159 | div_pup[stripe] = pup1[stripe] / pup2[stripe] 160 | div_pup[stripe] = div_pup[stripe].apply( 161 | lambda x: np.where(np.isin(x, [np.inf, np.nan]), 0, x) 162 | ) 163 | else: 164 | logging.info("Stripes cannot be divided, coordinates differ between pups") 165 | return div_pup 166 | 167 | 168 | def norm_coverage(snip): 169 | """Normalize a pileup by coverage arrays 170 | 171 | Parameters 172 | ---------- 173 | loop : 2D array 174 | Pileup. 175 | cov_start : 1D array 176 | Accumulated coverage of the left side of the pileup. 177 | cov_end : 1D array 178 | Accumulated coverage of the bottom side of the pileup. 179 | 180 | Returns 181 | ------- 182 | loop : 2D array 183 | Normalized pileup. 184 | 185 | """ 186 | coverage = np.outer(snip["cov_start"], snip["cov_end"]) 187 | coverage = coverage / np.nanmean(coverage) 188 | snip["data"] /= coverage 189 | snip["data"][np.isnan(snip["data"])] = 0 190 | return snip 191 | 192 | 193 | def bin_distance(snip, band_edges="default"): 194 | """ 195 | 196 | 197 | Parameters 198 | ---------- 199 | snip : pd.Series 200 | Series containing any annotations. Has to have ['distance'] 201 | band_edges : list or array-like, or "default", optional 202 | Edges of distance bands used to assign the distance band. 203 | Default is np.append([0], 50000 * 2 ** np.arange(30)) 204 | 205 | Returns 206 | ------- 207 | snip : pd.Series 208 | The same snip with added ['distance_band'] annotation. 209 | 210 | """ 211 | if band_edges == "default": 212 | band_edges = np.append([0], 50000 * 2 ** np.arange(30)) 213 | i = np.searchsorted(band_edges, snip["distance"]) 214 | snip["distance_band"] = tuple(band_edges[i - 1 : i + 1]) 215 | return snip 216 | 217 | 218 | def group_by_region(snip): 219 | snip1 = snip.copy() 220 | snip1["group"] = tuple([snip1["chrom1"], snip1["start1"], snip1["end1"]]) 221 | snip2 = snip.copy() 222 | snip2["group"] = tuple([snip2["chrom2"], snip2["start2"], snip2["end2"]]) 223 | yield from (snip1, snip2) 224 | 225 | 226 | def _combine_rows(row1, row2, normalize_order=True): 227 | """Deprecated, unused""" 228 | d = row2.center - row1.center 229 | if d < 0 and normalize_order: 230 | row1, row2 = row2, row1 231 | d = -d 232 | # row1.index = [i+'1' for i in row1.index] 233 | # row2.index = [i+'2' for i in row2.index] 234 | double_row = pd.Series( 235 | index=[i + "1" for i in row1.index] 236 | + [i + "2" for i in row2.index] 237 | + ["distance"], 238 | data=np.concatenate([row1.values, row2.values, [d]]), 239 | ) 240 | # double_row['distance'] = d 241 | return double_row 242 | 243 | 244 | def accumulate_values(dict1, dict2, key): 245 | """ 246 | Useful as an extra_sum_func 247 | """ 248 | assert key in dict2, f"{key} not in dict2" 249 | if key in dict1: 250 | dict1[key] = list(collapse([dict1[key], dict2[key]])) 251 | else: 252 | dict1[key] = [dict2[key]] 253 | return dict1 254 | -------------------------------------------------------------------------------- /coolpuppy/lib/util.py: -------------------------------------------------------------------------------- 1 | import os.path as op 2 | 3 | 4 | def validate_csv(value, default_column="balanced.avg"): 5 | if value is None: 6 | return 7 | file_path, _, field_name = value.partition("::") 8 | if not op.exists(file_path): 9 | raise ValueError(f"Path not found: {file_path}") 10 | if not field_name: 11 | field_name = default_column 12 | elif field_name.isdigit(): 13 | field_name = int(field_name) 14 | return file_path, field_name 15 | -------------------------------------------------------------------------------- /coolpuppy/plotpup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from coolpuppy.lib import numutils, puputils 3 | 4 | import numpy as np 5 | import pandas as pd 6 | 7 | import matplotlib.pyplot as plt 8 | import matplotlib.gridspec as grd 9 | from matplotlib.colors import LogNorm, Normalize 10 | from matplotlib import ticker 11 | from matplotlib import cm 12 | import seaborn as sns 13 | 14 | from cooltools.lib import plotting 15 | 16 | import logging 17 | import warnings 18 | 19 | logger = logging.getLogger("coolpuppy") 20 | 21 | warnings.filterwarnings(action="ignore", message=".*tight_layout.*") 22 | warnings.filterwarnings(action="ignore", message=".*Tight layout.*") 23 | pd.options.mode.chained_assignment = None 24 | import natsort 25 | import copy 26 | 27 | 28 | def auto_rows_cols(n): 29 | """Automatically determines number of rows and cols for n pileups 30 | 31 | Parameters 32 | ---------- 33 | n : int 34 | Number of pileups. 35 | 36 | Returns 37 | ------- 38 | rows : int 39 | How many rows to use. 40 | cols : int 41 | How many columsn to use. 42 | 43 | """ 44 | rows = int(np.ceil(np.sqrt(n))) 45 | cols = int(np.ceil(n / rows)) 46 | return rows, cols 47 | 48 | 49 | def get_min_max(pups, vmin=None, vmax=None, sym=True, scale="log"): 50 | """Automatically determine minimal and maximal colour intensity for pileups 51 | 52 | Parameters 53 | ---------- 54 | pups : np.array 55 | Numpy array of numpy arrays conaining pileups. 56 | vmin : float, optional 57 | Force certain minimal colour. The default is None. 58 | vmax : float, optional 59 | Force certain maximal colour. The default is None. 60 | sym : bool, optional 61 | Whether the output should be cymmetrical around 0. The default is True. 62 | 63 | Returns 64 | ------- 65 | vmin : float 66 | Selected minimal colour. 67 | vmax : float 68 | Selected maximal colour. 69 | 70 | """ 71 | if vmin is not None and vmax is not None: 72 | if sym: 73 | logger.info( 74 | "Can't set both vmin and vmax and get symmetrical scale. Plotting non-symmetrical" 75 | ) 76 | return vmin, vmax 77 | else: 78 | comb = np.concatenate([pup.ravel() for pup in pups.ravel()]) 79 | comb = comb[comb != -np.inf] 80 | comb = comb[comb != np.inf] 81 | comb = comb[comb != 0] 82 | if np.isnan(comb).all(): 83 | raise ValueError("Data only contains NaNs or zeros") 84 | if vmin is None and vmax is None: 85 | vmax = np.nanmax(comb) 86 | vmin = np.nanmin(comb) 87 | elif vmin is not None: 88 | if sym and scale == "log": 89 | vmax = 1 90 | else: 91 | vmax = np.nanmax(comb) 92 | elif vmax is not None: 93 | if sym and scale == "log": 94 | vmin = 1 95 | else: 96 | vmin = np.nanmin(comb) 97 | if sym: 98 | 99 | if scale == "linear": 100 | logger.info( 101 | "Can't use symmetrical scale with linear. Plotting non-symmetrical" 102 | ) 103 | pass 104 | else: 105 | vmax = 2 ** (np.max(np.abs(np.log2([vmin, vmax])))) 106 | if vmax >= 1: 107 | vmin = 2 ** -np.log2(vmax) 108 | else: 109 | raise ValueError( 110 | "Maximum value is less than 1.0, can't plot using symmetrical scale" 111 | ) 112 | return vmin, vmax 113 | 114 | 115 | def add_heatmap( 116 | data, 117 | flank, 118 | rescale, 119 | rescale_flank, 120 | n, 121 | max_coordinates, 122 | height=1, 123 | aspect="auto", 124 | color=None, 125 | cmap="coolwarm", 126 | norm=LogNorm(0.5, 2), 127 | plot_ticks=False, 128 | stripe=False, 129 | font_scale=1, 130 | ): 131 | """ 132 | Adds the array contained in data.values[0] to the current axes as a heatmap of stripes 133 | """ 134 | if len(data) > 1: 135 | raise ValueError( 136 | "Multiple pileups for one of the conditions, ensure unique correspondence for each col/row combination" 137 | ) 138 | elif len(data) == 0: 139 | return 140 | flank = int(flank.iloc[0]) 141 | ax = plt.gca() 142 | if stripe: 143 | extents = [-flank / max_coordinates[1], flank / max_coordinates[1], -int(n), 0] 144 | ax.set_ylim(-max_coordinates[2], 0) 145 | else: 146 | extents = [ 147 | -flank / max_coordinates[1], 148 | flank / max_coordinates[1], 149 | -flank / max_coordinates[1], 150 | flank / max_coordinates[1], 151 | ] 152 | ax.set_xlim(-(flank / max_coordinates[1]), (flank / max_coordinates[1])) 153 | ax.set_ylim(-(flank / max_coordinates[1]), (flank / max_coordinates[1])) 154 | ax.imshow( 155 | data.values[0], 156 | cmap=cmap, 157 | norm=norm, 158 | aspect=aspect, 159 | interpolation="none", 160 | extent=extents, 161 | ) 162 | if plot_ticks: 163 | ax.tick_params( 164 | axis="both", 165 | which="major", 166 | labelsize=font_scale * (4.94 + height), 167 | width=1 + (height / 2), 168 | length=1 + height, 169 | ) 170 | 171 | if not rescale.any(): 172 | ticks_pixels = np.linspace( 173 | -max_coordinates[0] / max_coordinates[1], 174 | max_coordinates[0] / max_coordinates[1], 175 | 5, 176 | ) 177 | ticks_kbp = ((ticks_pixels * max_coordinates[1]) // 1000).astype(int) 178 | plt.xticks(ticks_pixels.tolist(), ticks_kbp.tolist()) 179 | if not stripe: 180 | plt.yticks(ticks_pixels.tolist(), []) 181 | else: 182 | ticks_n = np.floor(np.linspace(0, -max_coordinates[2], 5)).astype(int) 183 | plt.yticks(ticks_n, np.append("", np.negative(ticks_n)[1:])) 184 | else: 185 | plt.yticks([], []) 186 | plt.xticks([], []) 187 | 188 | 189 | def add_stripe_lineplot( 190 | data, 191 | resolution, 192 | flank, 193 | rescale, 194 | rescale_flank, 195 | height=1, 196 | aspect="auto", 197 | color=None, 198 | cmap="coolwarm", 199 | scale="log", 200 | norm=LogNorm(0.5, 2), 201 | plot_ticks=False, 202 | stripe=False, 203 | font_scale=1, 204 | colnames=None, 205 | ): 206 | """ 207 | Adds the array contained in data.values[0] to the current axes as a heatmap of stripes and an average lineplot on top. 208 | Only works with one condition at a time. 209 | """ 210 | gs = grd.GridSpec( 211 | 2, 2, height_ratios=[1, 5], width_ratios=[8.25, 1], wspace=0.05, hspace=0.05 212 | ) 213 | flank = int(flank) 214 | resolution = int(resolution) 215 | ticks_pixels = np.linspace(0, flank * 2 // resolution, 5) 216 | ticks_kbp = ((ticks_pixels - ticks_pixels[-1] / 2) * resolution // 1000).astype(int) 217 | mean = np.nanmean(data.values[0], axis=0) 218 | if scale == "log": 219 | mean = np.log(mean) 220 | mean = np.where(mean == -np.inf, 0, mean) 221 | kbp = np.linspace(-flank, flank, int(flank / resolution * 2 + 1)) / 1000 222 | ax2 = plt.subplot(gs[0]) 223 | ax2.plot(kbp, mean) 224 | ax2.spines["right"].set_visible(False) 225 | ax2.spines["top"].set_visible(False) 226 | plt.xlim(-(flank + (resolution / 2)) / 1000, (flank + (resolution / 2)) / 1000) 227 | if plot_ticks: 228 | ax2.tick_params( 229 | axis="both", 230 | which="major", 231 | labelsize=font_scale * (4.94 + height), 232 | width=1 + (height / 2), 233 | length=1 + height, 234 | ) 235 | plt.yticks([np.round(min(mean), 4), np.round(max(mean), 4)]) 236 | else: 237 | plt.yticks([], []) 238 | plt.xticks([], []) 239 | if colnames is not None: 240 | plt.title(colnames[0]) 241 | ax = plt.subplot(gs[2]) 242 | p = ax.imshow( 243 | data.values[0], cmap=cmap, norm=norm, interpolation="none", aspect=aspect 244 | ) 245 | if plot_ticks: 246 | ax.tick_params( 247 | axis="both", 248 | which="major", 249 | labelsize=font_scale * (4.94 + height), 250 | width=1 + (height / 2), 251 | length=1 + height, 252 | ) 253 | if not rescale.any(): 254 | plt.xticks(ticks_pixels.tolist(), ticks_kbp.tolist()) 255 | ticks_n = np.floor(np.linspace(0, data.values[0].shape[0], 5)).astype(int) 256 | plt.yticks(ticks_n, np.append("", -np.negative(ticks_n)[1:])) 257 | else: 258 | plt.xticks([], []) 259 | plt.yticks([], []) 260 | ax.spines["right"].set_visible(False) 261 | ax.spines["top"].set_visible(False) 262 | 263 | 264 | def add_score(score, height=1, color=None, font_scale=1): 265 | """ 266 | Adds the value contained in score.values[0] to the current axes as a label in top left corner 267 | """ 268 | if score is not None: 269 | ax = plt.gca() 270 | ax.text( 271 | s=f"{score.values[0]:.3g}", 272 | y=0.95, 273 | x=0.05, 274 | ha="left", 275 | va="top", 276 | size=font_scale * (4.94 + height), 277 | transform=ax.transAxes, 278 | ) 279 | 280 | 281 | def sort_separation(sep_string_series, sep="Mb"): 282 | s = set(sep_string_series.dropna()) 283 | s.discard("all") 284 | return sorted( 285 | s, 286 | key=lambda x: float(x.split(sep)[0]), 287 | ) 288 | 289 | 290 | def plot_stripes( 291 | pupsdf, 292 | cols=None, 293 | rows=None, 294 | col_order=None, 295 | row_order=None, 296 | vmin=None, 297 | vmax=None, 298 | sym=True, 299 | cmap="coolwarm", 300 | cmap_emptypixel=(0.98, 0.98, 0.98), 301 | scale="log", 302 | height=1, 303 | aspect="auto", 304 | stripe="corner_stripe", 305 | stripe_sort="sum", 306 | out_sorted_bedpe=None, 307 | font="DejaVu Sans", 308 | font_scale=1, 309 | plot_ticks=False, 310 | colnames=None, 311 | rownames=None, 312 | lineplot=False, 313 | **kwargs, 314 | ): 315 | pupsdf = pupsdf.copy() 316 | if np.any(pupsdf.index.duplicated()): 317 | pupsdf = pupsdf.reset_index(drop=True) 318 | if not set(["vertical_stripe", "horizontal_stripe"]).issubset(pupsdf.columns): 319 | raise ValueError("No stripes stored in pup") 320 | if cols == "separation" and col_order is None: 321 | col_order = sort_separation(pupsdf["separation"]) 322 | ncols = len(col_order) 323 | elif cols is not None and col_order is None: 324 | col_order = list(set(pupsdf[cols].dropna())) 325 | ncols = len(col_order) 326 | elif col_order is not None: 327 | if isinstance(col_order, str): 328 | col_order = [col_order] 329 | ncols = len(col_order) 330 | else: 331 | ncols = 1 332 | 333 | if rows == "separation" and row_order is None: 334 | row_order = sort_separation(pupsdf["separation"]) 335 | nrows = len(row_order) 336 | elif rows is not None and row_order is None: 337 | row_order = list(set(pupsdf[rows].dropna())) 338 | nrows = len(row_order) 339 | elif row_order is not None: 340 | if isinstance(row_order, str): 341 | row_order = [row_order] 342 | nrows = len(row_order) 343 | else: 344 | nrows = 1 345 | 346 | if cols is None and rows is None: 347 | if pupsdf.shape[0] > 1: 348 | if "orientation" in pupsdf.columns: 349 | rows = "orientation" 350 | row_order = list(set(pupsdf[rows].dropna())) 351 | nrows = len(row_order) 352 | if "separation" in pupsdf.columns: 353 | cols = "separation" 354 | col_order = sort_separation(pupsdf["separation"]) 355 | ncols = len(col_order) 356 | 357 | logger.debug(f"Plotting stripe stackups with {ncols} columns and {nrows} rows") 358 | 359 | vmin, vmax = get_min_max(pupsdf["data"].values, vmin, vmax, sym=sym, scale=scale) 360 | 361 | if scale == "log": 362 | norm = LogNorm 363 | elif scale == "linear": 364 | norm = Normalize 365 | else: 366 | raise ValueError( 367 | f"Unknown scale value, only log or linear implemented, but got {scale}" 368 | ) 369 | 370 | right = ncols / (ncols + 0.25) 371 | 372 | pupsdf = pupsdf.reset_index() 373 | 374 | # Generate corner stripes 375 | cntr = int(np.floor(pupsdf["data"][0].shape[0] / 2)) 376 | pupsdf["corner_stripe"] = pupsdf["horizontal_stripe"] 377 | for i in range(len(pupsdf)): 378 | pupsdf["corner_stripe"][i] = np.concatenate( 379 | ( 380 | pupsdf["horizontal_stripe"][i][:, :(cntr)], 381 | pupsdf["vertical_stripe"][i][:, cntr:], 382 | ), 383 | axis=1, 384 | ) 385 | 386 | # Sorting stripes 387 | if not stripe_sort == None: 388 | different = False 389 | for i in range(len(pupsdf)): 390 | pupsdf["coordinates"][i] = np.array(pupsdf["coordinates"][i], dtype=object) 391 | pupsdf["corner_stripe"][i] = np.array(pupsdf["corner_stripe"][i]) 392 | pupsdf["vertical_stripe"][i] = np.array(pupsdf["vertical_stripe"][i]) 393 | pupsdf["horizontal_stripe"][i] = np.array(pupsdf["horizontal_stripe"][i]) 394 | ind_regions = natsort.index_natsorted(pupsdf["coordinates"][i]) 395 | pupsdf.loc[ 396 | i, 397 | [ 398 | "coordinates", 399 | "corner_stripe", 400 | "vertical_stripe", 401 | "horizontal_stripe", 402 | ], 403 | ] = pupsdf.loc[ 404 | i, 405 | [ 406 | "coordinates", 407 | "corner_stripe", 408 | "vertical_stripe", 409 | "horizontal_stripe", 410 | ], 411 | ].apply( 412 | lambda x: x[ind_regions] 413 | ) 414 | for i in range(len(pupsdf)): 415 | if not np.array_equal(pupsdf["coordinates"][0], pupsdf["coordinates"][i]): 416 | different = True 417 | warnings.warn( 418 | "Cannot sort stripes, rows or columns contain different regions. Plot one by one if you want to sort", 419 | stacklevel=2, 420 | ) 421 | if not different: 422 | if stripe_sort == "sum": 423 | ind_sort = np.argsort(-np.nansum(pupsdf[stripe][0], axis=1)) 424 | elif stripe_sort == "center_pixel": 425 | cntr = int(np.floor(pupsdf[stripe][0].shape[1] / 2)) 426 | ind_sort = np.argsort(-pupsdf[stripe][0][:, cntr]) 427 | else: 428 | raise ValueError("stripe_sort can only be None, sum, or center_pixel") 429 | for i in range(len(pupsdf)): 430 | pupsdf.loc[ 431 | i, 432 | [ 433 | "coordinates", 434 | "corner_stripe", 435 | "vertical_stripe", 436 | "horizontal_stripe", 437 | ], 438 | ] = pupsdf.loc[ 439 | i, 440 | [ 441 | "coordinates", 442 | "corner_stripe", 443 | "vertical_stripe", 444 | "horizontal_stripe", 445 | ], 446 | ].apply( 447 | lambda x: x[ind_sort] 448 | ) 449 | if isinstance(out_sorted_bedpe, str): 450 | pd.DataFrame(pupsdf.loc[0, "coordinates"]).to_csv( 451 | out_sorted_bedpe, sep="\t", header=None, index=False 452 | ) 453 | 454 | sns.set(font=font, font_scale=font_scale, style="ticks") 455 | 456 | fg = sns.FacetGrid( 457 | pupsdf, 458 | col=cols, 459 | row=rows, 460 | row_order=row_order, 461 | col_order=col_order, 462 | margin_titles=True, 463 | height=height, 464 | gridspec_kws={ 465 | "right": right, 466 | }, 467 | **kwargs, 468 | ) 469 | 470 | norm = norm(vmin, vmax) 471 | 472 | cmap = copy.copy(cm.get_cmap(cmap)) 473 | cmap.set_bad(cmap_emptypixel) 474 | 475 | max_coordinates = [ 476 | pupsdf.loc[pd.to_numeric(pupsdf["flank"]).idxmax(), "flank"], 477 | pupsdf.loc[pd.to_numeric(pupsdf["flank"]).idxmax(), "resolution"], 478 | max(pupsdf.loc[pupsdf.drop(columns="index").iloc[:, 1] != "all", "n"]), 479 | ] 480 | 481 | if stripe in ["horizontal_stripe", "vertical_stripe", "corner_stripe"]: 482 | if lineplot and nrows == 1 and ncols == 1: 483 | fg.map( 484 | add_stripe_lineplot, 485 | stripe, 486 | "resolution", 487 | "flank", 488 | "rescale", 489 | "rescale_flank", 490 | scale=scale, 491 | norm=norm, 492 | cmap=cmap, 493 | aspect=aspect, 494 | height=height, 495 | plot_ticks=plot_ticks, 496 | stripe=stripe, 497 | font_scale=font_scale, 498 | colnames=colnames, 499 | ) 500 | logger.debug(f"Plotting lineplot on top of stripes") 501 | try: 502 | for ax in fg.axes[0]: 503 | ax.remove() 504 | except: 505 | pass 506 | else: 507 | fg.map( 508 | add_heatmap, 509 | stripe, 510 | "flank", 511 | "rescale", 512 | "rescale_flank", 513 | "n", 514 | norm=norm, 515 | cmap=cmap, 516 | aspect=aspect, 517 | height=height, 518 | plot_ticks=plot_ticks, 519 | stripe=stripe, 520 | font_scale=font_scale, 521 | max_coordinates=max_coordinates, 522 | ) 523 | if lineplot: 524 | logger.info( 525 | "Can only do lineplot for single conditions (no rows/columns). Doing normal stripe plot instead." 526 | ) 527 | else: 528 | raise ValueError( 529 | "stripe can only be 'vertical_stripe', 'horizontal_stripe' or 'corner_stripe'" 530 | ) 531 | if plot_ticks: 532 | fg.fig.subplots_adjust(wspace=0.2, hspace=0.05) 533 | if not lineplot: 534 | fg.set_titles(col_template="", row_template="") 535 | if nrows > 1 and ncols > 1: 536 | for (row_val, col_val), ax in fg.axes_dict.items(): 537 | if row_val == row_order[0]: 538 | ax.set_title(col_val) 539 | if row_val == row_order[-1]: 540 | ax.set_xlabel("") 541 | if col_val == col_order[0]: 542 | ax.set_ylabel(row_val, rotation=0, ha="right", va="center") 543 | else: 544 | if nrows == 1 and ncols > 1: 545 | for col_val, ax in fg.axes_dict.items(): 546 | ax.set_xlabel("") 547 | ax.set_ylabel("") 548 | ax.set_title(col_val) 549 | elif nrows > 1 and ncols == 1: 550 | for row_val, ax in fg.axes_dict.items(): 551 | ax.set_ylabel(row_val, rotation=0, ha="right", va="center") 552 | ax.set_xlabel("") 553 | else: 554 | plt.title("") 555 | plt.ylabel("") 556 | plt.xlabel("") 557 | else: 558 | fg.fig.subplots_adjust(wspace=0.05, hspace=0.05) 559 | if not lineplot: 560 | fg.map(lambda color: plt.gca().set_xticks([])) 561 | fg.map(lambda color: plt.gca().set_yticks([])) 562 | fg.set_titles(col_template="", row_template="") 563 | if nrows > 1 and ncols > 1: 564 | for (row_val, col_val), ax in fg.axes_dict.items(): 565 | if row_val == row_order[-1]: 566 | ax.set_xlabel(col_val) 567 | if col_val == col_order[0]: 568 | ax.set_ylabel(row_val, rotation=0, ha="right") 569 | else: 570 | if nrows == 1 and ncols > 1: 571 | for col_val, ax in fg.axes_dict.items(): 572 | ax.set_xlabel(col_val) 573 | ax.set_ylabel("") 574 | elif nrows > 1 and ncols == 1: 575 | for row_val, ax in fg.axes_dict.items(): 576 | ax.set_xlabel("") 577 | ax.set_ylabel(row_val, rotation=0, ha="right") 578 | else: 579 | plt.title("") 580 | plt.xlabel("") 581 | plt.ylabel("") 582 | 583 | if colnames is not None: 584 | if len(colnames) != ncols: 585 | logger.info(f"{len(colnames)} colnames but {ncols} columns, ignoring") 586 | else: 587 | i = 0 588 | if nrows > 1 and ncols > 1: 589 | for (row_val, col_val), ax in fg.axes_dict.items(): 590 | if not plot_ticks and row_val == row_order[-1]: 591 | ax.set_xlabel(colnames[i]) 592 | i += 1 593 | elif plot_ticks and row_val == row_order[0]: 594 | ax.set_title(colnames[i]) 595 | i += 1 596 | else: 597 | if nrows == 1 and ncols > 1: 598 | for col_val, ax in fg.axes_dict.items(): 599 | if plot_ticks: 600 | ax.set_title(colnames[i]) 601 | else: 602 | ax.set_xlabel(colnames[i]) 603 | i += 1 604 | elif nrows > 1 and ncols == 1: 605 | for row_val, ax in fg.axes_dict.items(): 606 | if not plot_ticks and row_val == row_order[-1]: 607 | ax.set_xlabel(colnames[i]) 608 | i += 1 609 | elif plot_ticks and row_val == row_order[0]: 610 | ax.set_title(colnames[i]) 611 | i += 1 612 | else: 613 | if not lineplot: 614 | plt.title(colnames[i]) 615 | 616 | if rownames is not None: 617 | if len(rownames) != nrows: 618 | logger.info(f"{len(rownames)} rownames but {nrows} rows, ignoring") 619 | else: 620 | i = 0 621 | if nrows > 1 and ncols > 1: 622 | for (row_val, col_val), ax in fg.axes_dict.items(): 623 | if col_val == col_order[0]: 624 | ax.set_ylabel(rownames[i], rotation=0, ha="right", va="center") 625 | i += 1 626 | else: 627 | if nrows == 1 and ncols > 1: 628 | for col_val, ax in fg.axes_dict.items(): 629 | ax.set_ylabel(rownames[i], rotation=0, ha="right", va="center") 630 | elif nrows > 1 and ncols == 1: 631 | for row_val, ax in fg.axes_dict.items(): 632 | ax.set_ylabel(rownames[i], rotation=0, ha="right", va="center") 633 | i += 1 634 | else: 635 | plt.ylabel(rownames[i], rotation=0, ha="right", va="center") 636 | 637 | plt.draw() 638 | ax_bottom = fg.axes[-1, -1] 639 | bottom = ax_bottom.get_position().y0 640 | ax_top = fg.axes[0, -1] 641 | top = ax_top.get_position().y1 642 | right = ax_top.get_position().x1 643 | ax_left = fg.axes[-1, 0] 644 | left = ax_left.get_position().x0 645 | cax = fg.fig.add_axes([right + 0.01, bottom, (1 - right - 0.01) / 5, top - bottom]) 646 | if plot_ticks: 647 | if pupsdf["rescale"].any(): 648 | string = "rescaled" 649 | else: 650 | string = "pos. [kb]" 651 | fg.fig.text( 652 | (right + left) / 2, 653 | (0.05 + (0.01 * nrows) - (0.25 / height / nrows)), 654 | s=string, 655 | ha="center", 656 | fontsize=font_scale * 2 * (4.94 + height), 657 | ) 658 | if sym and scale == "log": 659 | ticks = [norm.vmin, 1, norm.vmax] 660 | else: 661 | ticks = [norm.vmin, norm.vmax] 662 | cb = plt.colorbar( 663 | cm.ScalarMappable(norm, cmap), 664 | ticks=ticks, 665 | cax=cax, 666 | format=ticker.FuncFormatter(lambda x, pos: f"{x:.2g}"), 667 | ) 668 | cax.minorticks_off() 669 | return fg 670 | 671 | 672 | def plot( 673 | pupsdf, 674 | cols=None, 675 | rows=None, 676 | score="score", 677 | center=3, 678 | ignore_central=3, 679 | col_order=None, 680 | row_order=None, 681 | vmin=None, 682 | vmax=None, 683 | sym=True, 684 | norm_corners=0, 685 | cmap="coolwarm", 686 | cmap_emptypixel=(0.98, 0.98, 0.98), 687 | scale="log", 688 | height=1, 689 | aspect=1, 690 | font="DejaVu Sans", 691 | font_scale=1, 692 | plot_ticks=False, 693 | colnames=None, 694 | rownames=None, 695 | **kwargs, 696 | ): 697 | pupsdf = pupsdf.copy() 698 | if np.any(pupsdf.index.duplicated()): 699 | pupsdf = pupsdf.reset_index(drop=True) 700 | cmap = copy.copy(cm.get_cmap(cmap)) 701 | cmap.set_bad(cmap_emptypixel) 702 | 703 | sns.set(font=font, font_scale=font_scale, style="ticks") 704 | if norm_corners: 705 | pupsdf["data"] = pupsdf.apply( 706 | lambda x: numutils.norm_cis(x["data"], norm_corners), axis=1 707 | ) 708 | if cols == "separation" and col_order is None: 709 | col_order = sort_separation(pupsdf["separation"]) 710 | ncols = len(col_order) 711 | elif cols is not None and col_order is None: 712 | col_order = list(set(pupsdf[cols].dropna())) 713 | ncols = len(col_order) 714 | elif col_order is not None: 715 | if isinstance(col_order, str): 716 | col_order = [col_order] 717 | ncols = len(col_order) 718 | else: 719 | ncols = 1 720 | 721 | if rows == "separation" and row_order is None: 722 | row_order = sort_separation(pupsdf["separation"]) 723 | nrows = len(row_order) 724 | elif rows is not None and row_order is None: 725 | row_order = list(set(pupsdf[rows].dropna())) 726 | nrows = len(row_order) 727 | elif row_order is not None: 728 | if isinstance(row_order, str): 729 | row_order = [row_order] 730 | nrows = len(row_order) 731 | else: 732 | nrows = 1 733 | if cols is None and rows is None: 734 | if pupsdf.shape[0] > 1: 735 | if "orientation" in pupsdf.columns: 736 | rows = "orientation" 737 | row_order = list(set(pupsdf[rows].dropna())) 738 | nrows = len(row_order) 739 | if "separation" in pupsdf.columns: 740 | cols = "separation" 741 | col_order = sort_separation(pupsdf["separation"]) 742 | ncols = len(col_order) 743 | 744 | logger.debug(f"Plotting pileup with {ncols} columns and {nrows} rows") 745 | 746 | vmin, vmax = get_min_max(pupsdf["data"].values, vmin, vmax, sym=sym, scale=scale) 747 | 748 | if scale == "log": 749 | norm = LogNorm 750 | elif scale == "linear": 751 | norm = Normalize 752 | else: 753 | raise ValueError( 754 | f"Unknown scale value, only log or linear implemented, but got {scale}" 755 | ) 756 | right = ncols / (ncols + 0.25) 757 | 758 | fg = sns.FacetGrid( 759 | pupsdf, 760 | col=cols, 761 | row=rows, 762 | row_order=row_order, 763 | col_order=col_order, 764 | margin_titles=True, 765 | aspect=1, 766 | height=height, 767 | gridspec_kws={ 768 | "right": right, 769 | }, 770 | **kwargs, 771 | ) 772 | norm = norm(vmin, vmax) 773 | max_coordinates = [ 774 | pupsdf.loc[pd.to_numeric(pupsdf["flank"]).idxmax(), "flank"], 775 | pupsdf.loc[pd.to_numeric(pupsdf["flank"]).idxmax(), "resolution"], 776 | ] 777 | fg.map( 778 | add_heatmap, 779 | "data", 780 | "flank", 781 | "rescale", 782 | "rescale_flank", 783 | "n", 784 | max_coordinates=max_coordinates, 785 | norm=norm, 786 | cmap=cmap, 787 | aspect=aspect, 788 | height=height, 789 | plot_ticks=plot_ticks, 790 | font_scale=font_scale, 791 | ) 792 | 793 | if score: 794 | if score is True: 795 | score = "score" 796 | pupsdf[score] = pupsdf.apply( 797 | puputils.get_score, center=center, ignore_central=ignore_central, axis=1 798 | ) 799 | fg.map(add_score, "score", height=height, font_scale=font_scale) 800 | 801 | if plot_ticks: 802 | fg.fig.subplots_adjust(wspace=0.2, hspace=0.05) 803 | fg.set_titles(col_template="", row_template="") 804 | if nrows > 1 and ncols > 1: 805 | for (row_val, col_val), ax in fg.axes_dict.items(): 806 | if row_val == row_order[0]: 807 | ax.set_title(col_val) 808 | saveax = ax 809 | if row_val == row_order[-1]: 810 | ax.set_xlabel("") 811 | if col_val == col_order[0]: 812 | ax.set_ylabel(row_val, rotation=0, ha="right", va="center") 813 | else: 814 | if nrows == 1 and ncols > 1: 815 | for col_val, ax in fg.axes_dict.items(): 816 | ax.set_xlabel("") 817 | ax.set_ylabel("") 818 | ax.set_title(col_val) 819 | elif nrows > 1 and ncols == 1: 820 | for row_val, ax in fg.axes_dict.items(): 821 | ax.set_ylabel(row_val, rotation=0, ha="right", va="center") 822 | ax.set_xlabel("") 823 | else: 824 | plt.title("") 825 | plt.ylabel("") 826 | plt.xlabel("") 827 | 828 | else: 829 | fg.fig.subplots_adjust(wspace=0.05, hspace=0.05) 830 | fg.map(lambda color: plt.gca().set_xticks([])) 831 | fg.map(lambda color: plt.gca().set_yticks([])) 832 | fg.set_titles(col_template="", row_template="") 833 | if nrows > 1 and ncols > 1: 834 | for (row_val, col_val), ax in fg.axes_dict.items(): 835 | if row_val == row_order[-1]: 836 | ax.set_xlabel(col_val) 837 | if col_val == col_order[0]: 838 | ax.set_ylabel(row_val, rotation=0, ha="right", va="center") 839 | else: 840 | if nrows == 1 and ncols > 1: 841 | for col_val, ax in fg.axes_dict.items(): 842 | ax.set_xlabel(col_val) 843 | ax.set_ylabel("") 844 | elif nrows > 1 and ncols == 1: 845 | for row_val, ax in fg.axes_dict.items(): 846 | ax.set_xlabel("") 847 | ax.set_ylabel(row_val, rotation=0, ha="right", va="center") 848 | else: 849 | plt.xlabel("") 850 | plt.ylabel("") 851 | plt.title("") 852 | 853 | if colnames is not None: 854 | if len(colnames) != ncols: 855 | logger.info(f"{len(colnames)} colnames but {ncols} columns, ignoring") 856 | else: 857 | i = 0 858 | if nrows > 1 and ncols > 1: 859 | for (row_val, col_val), ax in fg.axes_dict.items(): 860 | if not plot_ticks and row_val == row_order[-1]: 861 | ax.set_xlabel(colnames[i]) 862 | i += 1 863 | elif plot_ticks and row_val == row_order[0]: 864 | ax.set_title(colnames[i]) 865 | i += 1 866 | else: 867 | if nrows == 1 and ncols > 1: 868 | for col_val, ax in fg.axes_dict.items(): 869 | if plot_ticks: 870 | ax.set_title(colnames[i]) 871 | else: 872 | ax.set_xlabel(colnames[i]) 873 | i += 1 874 | elif nrows > 1 and ncols == 1: 875 | for row_val, ax in fg.axes_dict.items(): 876 | if not plot_ticks and row_val == row_order[-1]: 877 | ax.set_xlabel(colnames[i]) 878 | i += 1 879 | elif plot_ticks and row_val == row_order[0]: 880 | ax.set_title(colnames[i]) 881 | i += 1 882 | else: 883 | plt.title(colnames[i]) 884 | 885 | if rownames is not None: 886 | if len(rownames) != nrows: 887 | logger.info(f"{len(rownames)} rownames but {nrows} rows, ignoring") 888 | else: 889 | i = 0 890 | if nrows > 1 and ncols > 1: 891 | for (row_val, col_val), ax in fg.axes_dict.items(): 892 | if col_val == col_order[0]: 893 | ax.set_ylabel(rownames[i], rotation=0, ha="right", va="center") 894 | i += 1 895 | else: 896 | if nrows == 1 and ncols > 1: 897 | for col_val, ax in fg.axes_dict.items(): 898 | ax.set_ylabel(rownames[i], rotation=0, ha="right", va="center") 899 | elif nrows > 1 and ncols == 1: 900 | for row_val, ax in fg.axes_dict.items(): 901 | ax.set_ylabel(rownames[i], rotation=0, ha="right", va="center") 902 | i += 1 903 | else: 904 | plt.ylabel(rownames[i], rotation=0, ha="right", va="center") 905 | 906 | plt.draw() 907 | ax_bottom = fg.axes[-1, -1] 908 | bottom = ax_bottom.get_position().y0 909 | ax_top = fg.axes[0, -1] 910 | top = ax_top.get_position().y1 911 | right = ax_top.get_position().x1 912 | ax_left = fg.axes[-1, 0] 913 | left = ax_left.get_position().x0 914 | cax = fg.fig.add_axes( 915 | [right + 0.005, bottom, (1 - right - 0.005) / 5, top - bottom] 916 | ) 917 | if plot_ticks: 918 | if pupsdf["rescale"].any(): 919 | string = "rescaled" 920 | else: 921 | string = "pos. [kb]" 922 | fg.fig.text( 923 | (right + left) / 2, 924 | (0.1 - (0.25 / height / nrows)), 925 | s=string, 926 | ha="center", 927 | fontsize=font_scale * 2 * (4.94 + height), 928 | ) 929 | if sym and scale == "log": 930 | ticks = [norm.vmin, 1, norm.vmax] 931 | else: 932 | ticks = [norm.vmin, norm.vmax] 933 | 934 | cb = plt.colorbar( 935 | cm.ScalarMappable(norm, cmap), 936 | ticks=ticks, 937 | cax=cax, 938 | format=ticker.FuncFormatter(lambda x, pos: f"{x:.2g}"), 939 | ) 940 | cax.minorticks_off() 941 | return fg 942 | -------------------------------------------------------------------------------- /coolpuppy/plotpuppy_CLI.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Mon Mar 23 14:05:06 2020 5 | 6 | @author: Ilya Flyamer 7 | """ 8 | from coolpuppy.lib import numutils 9 | from coolpuppy.lib import puputils 10 | from coolpuppy.lib import io 11 | 12 | from coolpuppy.plotpup import plot, plot_stripes 13 | from coolpuppy._version import __version__ 14 | 15 | import matplotlib 16 | 17 | matplotlib.use("Agg") 18 | 19 | import matplotlib.pyplot as plt 20 | import matplotlib as mpl 21 | import re 22 | import argparse 23 | import logging 24 | 25 | import sys 26 | import pdb, traceback 27 | 28 | 29 | def parse_args_plotpuppy(): 30 | parser = argparse.ArgumentParser( 31 | formatter_class=argparse.ArgumentDefaultsHelpFormatter 32 | ) 33 | parser.add_argument( 34 | "--cmap", 35 | type=str, 36 | required=False, 37 | default="coolwarm", 38 | help="""Colormap to use 39 | (see https://matplotlib.org/users/colormaps.html)""", 40 | ) 41 | parser.add_argument( 42 | "--not_symmetric", 43 | "--not-symmetric", 44 | "--not_symmetrical", 45 | "--not-symmetrical", 46 | default=False, 47 | action="store_true", 48 | help="""Whether to **not** make colormap symmetric around 1, if log scale""", 49 | ) 50 | parser.add_argument( 51 | "--vmin", type=float, required=False, help="""Value for the lowest colour""" 52 | ) 53 | parser.add_argument( 54 | "--vmax", type=float, required=False, help="""Value for the highest colour""" 55 | ) 56 | parser.add_argument( 57 | "--scale", 58 | type=str, 59 | default="log", 60 | required=False, 61 | choices={"linear", "log"}, 62 | help="""Whether to use linear or log scaling for mapping colours""", 63 | ) 64 | parser.add_argument( 65 | "--stripe", 66 | type=str, 67 | default=None, 68 | required=False, 69 | help="""For plotting stripe stackups""", 70 | ) 71 | parser.add_argument( 72 | "--stripe_sort", 73 | type=str, 74 | default="sum", 75 | required=False, 76 | help="""Whether to sort stripe stackups by total signal (sum), central pixel signal (center_pixel), or not at all (None)""", 77 | ) 78 | parser.add_argument( 79 | "--lineplot", 80 | default=False, 81 | action="store_true", 82 | help="""Whether to plot the average lineplot above stripes. 83 | This only works for a single plot, i.e. without rows/columns 84 | """, 85 | ) 86 | parser.add_argument( 87 | "--out_sorted_bedpe", 88 | type=str, 89 | default=None, 90 | required=False, 91 | help="""Output bedpe of sorted stripe regions""", 92 | ) 93 | parser.add_argument( 94 | "--divide_pups", 95 | default=False, 96 | action="store_true", 97 | help="""Whether to divide two pileups and plot the result""", 98 | ) 99 | parser.add_argument( 100 | "--font", 101 | type=str, 102 | default="DejaVu Sans", 103 | required=False, 104 | help="""Font to use for plotting""", 105 | ) 106 | 107 | parser.add_argument( 108 | "--font_scale", 109 | type=float, 110 | default=1, 111 | required=False, 112 | help="""Font scale to use for plotting. Defaults to 1""", 113 | ) 114 | # parser.add_argument( 115 | # "--cbar_mode", 116 | # type=str, 117 | # default="single", 118 | # required=False, 119 | # choices={"single", "edge", "each"}, 120 | # help="""Whether to show a single colorbar, one per row or one for each subplot 121 | # """, 122 | # ) 123 | # parser.add_argument( 124 | # "--n_cols", 125 | # type=int, 126 | # default=0, 127 | # required=False, 128 | # help="""How many columns to use for plotting the data. 129 | # If 0, automatically make the figure as square as possible""", 130 | # ) 131 | parser.add_argument( 132 | "--cols", 133 | type=str, 134 | required=False, 135 | help="""Which value to map as columns""", 136 | ) 137 | parser.add_argument( 138 | "--rows", 139 | type=str, 140 | required=False, 141 | help="""Which value to map as rows""", 142 | ) 143 | parser.add_argument( 144 | "--col_order", 145 | type=lambda s: re.split(" |, ", s), 146 | required=False, 147 | help="""Order of columns to use, space separated inside quotes""", 148 | ) 149 | parser.add_argument( 150 | "--row_order", 151 | type=lambda s: re.split(" |, ", s), 152 | required=False, 153 | help="""Order of rows to use, space separated inside quotes""", 154 | ) 155 | parser.add_argument( 156 | "--colnames", 157 | type=str, 158 | nargs="+", 159 | required=False, 160 | help="""Names to plot for columns, space separated.""", 161 | ) 162 | parser.add_argument( 163 | "--rownames", 164 | type=str, 165 | nargs="+", 166 | required=False, 167 | help="""Names to plot for rows, space separated.""", 168 | ) 169 | parser.add_argument( 170 | "--query", 171 | type=str, 172 | default="", 173 | required=False, 174 | action="append", 175 | help="""Pandas query to select pups to plot from concatenated input files. 176 | Multiple query arguments can be used. Usage example: 177 | --query "orientation == '+-' | orientation == '-+'" """, 178 | ) 179 | parser.add_argument( 180 | "--norm_corners", 181 | type=int, 182 | required=False, 183 | default=0, 184 | help="""Whether to normalize pileups by their top left and bottom right corners. 185 | 0 for no normalization, positive number to define the size of the corner 186 | squares whose values are averaged""", 187 | ) 188 | parser.add_argument( 189 | "--no_score", 190 | action="store_true", 191 | required=False, 192 | default=False, 193 | help="""If central pixel score should not be shown in top left corner""", 194 | ) 195 | parser.add_argument( 196 | "--center", 197 | type=int, 198 | required=False, 199 | default=3, 200 | help="""How many central pixels to consider when calculating enrichment for off-diagonal pileups.""", 201 | ) 202 | parser.add_argument( 203 | "--ignore_central", 204 | type=int, 205 | required=False, 206 | default=3, 207 | help="""How many central bins to ignore when calculating insulation for local (on-diagonal) non-rescaled pileups.""", 208 | ) 209 | parser.add_argument( 210 | "--quaich", 211 | required=False, 212 | default=False, 213 | action="store_true", 214 | help="""Activate if pileups are named accodring to Quaich naming convention to get information from the file name""", 215 | ) 216 | parser.add_argument( 217 | "--dpi", 218 | type=int, 219 | required=False, 220 | default=300, 221 | help="""DPI of the output plot. Try increasing if heatmaps look blurry""", 222 | ) 223 | # parser.add_argument("--n_rows", type=int, default=0, 224 | # required=False, 225 | # help="""How many rows to use for plotting the data""") 226 | parser.add_argument( 227 | "--height", 228 | type=float, 229 | required=False, 230 | default=1, 231 | help="""Height of the plot""", 232 | ) 233 | parser.add_argument( 234 | "--plot_ticks", 235 | action="store_true", 236 | default=False, 237 | required=False, 238 | help="""Whether to plot ticks demarkating the center and flanking regions, only applicable for non-stripes""", 239 | ) 240 | parser.add_argument( 241 | "--output", 242 | "-o", 243 | "--outname", 244 | type=str, 245 | required=False, 246 | default="pup.pdf", 247 | help="""Where to save the plot""", 248 | ) 249 | parser.add_argument( 250 | "-l", 251 | "--log", 252 | dest="logLevel", 253 | choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], 254 | default="INFO", 255 | help="Set the logging level", 256 | ) 257 | parser.add_argument( 258 | "--post_mortem", 259 | action="store_true", 260 | default=False, 261 | required=False, 262 | help="""Enter debugger if there is an error""", 263 | ) 264 | parser.add_argument( 265 | "--input_pups", type=str, nargs="+", help="""All files to plot""" 266 | ) 267 | parser.add_argument("-v", "--version", action="version", version=__version__) 268 | return parser 269 | 270 | 271 | def main(): 272 | parser = parse_args_plotpuppy() 273 | args = parser.parse_args() 274 | 275 | logger = logging.getLogger("coolpuppy") 276 | logger.setLevel(getattr(logging, args.logLevel)) 277 | 278 | logger.debug(args) 279 | 280 | if args.post_mortem: 281 | 282 | def _excepthook(exc_type, value, tb): 283 | traceback.print_exception(exc_type, value, tb) 284 | print() 285 | pdb.pm() 286 | 287 | sys.excepthook = _excepthook 288 | mpl.rcParams["svg.fonttype"] = "none" 289 | mpl.rcParams["pdf.fonttype"] = 42 290 | 291 | if args.divide_pups: 292 | if len(args.input_pups) != 2: 293 | raise ValueError("Need exactly two input pups when using --divide_pups") 294 | else: 295 | pup1 = io.load_pileup_df(args.input_pups[0]) 296 | pup2 = io.load_pileup_df(args.input_pups[1]) 297 | pups = puputils.divide_pups(pup1, pup2) 298 | else: 299 | pups = io.load_pileup_df_list( 300 | args.input_pups, 301 | quaich=args.quaich, 302 | nice_metadata=True, 303 | skipstripes=not args.stripe, 304 | ) 305 | 306 | if args.query: 307 | for q in args.query: 308 | pups = pups.query(q) 309 | 310 | if args.norm_corners > 0: 311 | pups["data"] = pups["data"].apply(numutils.norm_cis, i=int(args.norm_corners)) 312 | 313 | if not args.no_score: 314 | pups["score"] = pups.apply( 315 | puputils.get_score, 316 | center=args.center, 317 | ignore_central=args.ignore_central, 318 | axis=1, 319 | ) 320 | score = "score" 321 | else: 322 | score = False 323 | 324 | if args.cols: 325 | if args.col_order: 326 | pups[args.cols] = pups[args.cols].astype(str) 327 | pups = pups[pups[args.cols].isin(args.col_order)] 328 | elif args.cols != "separation": 329 | args.col_order = pups[args.cols].unique() 330 | 331 | if args.rows: 332 | if args.row_order: 333 | pups[args.rows] = pups[args.rows].astype(str) 334 | pups = pups[pups[args.rows].isin(args.row_order)] 335 | elif args.rows != "separation": 336 | args.row_order = pups[args.rows].unique() 337 | 338 | if args.stripe_sort == "None": 339 | args.stripe_sort = None 340 | 341 | if args.not_symmetric: 342 | symmetric = False 343 | else: 344 | symmetric = True 345 | 346 | if args.stripe: 347 | fg = plot_stripes( 348 | pups, 349 | cols=args.cols, 350 | rows=args.rows, 351 | col_order=args.col_order, 352 | row_order=args.row_order, 353 | vmin=args.vmin, 354 | vmax=args.vmax, 355 | sym=symmetric, 356 | cmap=args.cmap, 357 | scale=args.scale, 358 | height=args.height, 359 | stripe=args.stripe, 360 | stripe_sort=args.stripe_sort, 361 | out_sorted_bedpe=args.out_sorted_bedpe, 362 | font=args.font, 363 | font_scale=args.font_scale, 364 | plot_ticks=args.plot_ticks, 365 | colnames=args.colnames, 366 | rownames=args.rownames, 367 | lineplot=args.lineplot, 368 | ) 369 | else: 370 | fg = plot( 371 | pups, 372 | cols=args.cols, 373 | rows=args.rows, 374 | score=score, 375 | col_order=args.col_order, 376 | row_order=args.row_order, 377 | vmin=args.vmin, 378 | vmax=args.vmax, 379 | sym=symmetric, 380 | cmap=args.cmap, 381 | scale=args.scale, 382 | height=args.height, 383 | font=args.font, 384 | font_scale=args.font_scale, 385 | plot_ticks=args.plot_ticks, 386 | colnames=args.colnames, 387 | rownames=args.rownames, 388 | ) 389 | 390 | plt.savefig(args.output, bbox_inches="tight", dpi=args.dpi) 391 | logger.info(f"Saved output to {args.output}") 392 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | pyyaml 2 | sphinx>=1.4 3 | ipykernel 4 | sphinx-argparse 5 | sphinxcontrib-napoleon 6 | natsort 7 | sphinx_rtd_theme 8 | myst_nb 9 | mock 10 | -------------------------------------------------------------------------------- /docs/source/Examples/Ctrl_loop.txt: -------------------------------------------------------------------------------- 1 | 8.218084879275394661e-01 8.748488346098787227e-01 8.587979934045240071e-01 8.194617552134687566e-01 8.764616349508570492e-01 8.565632716943185621e-01 1.005364387732792908e+00 1.017714602727376683e+00 8.718633334822051273e-01 1.291608856978280206e+00 1.155277829010853630e+00 1.312050419176929328e+00 1.130406719837887319e+00 1.091218895098428510e+00 9.182506342769657381e-01 7.802890922075677027e-01 9.719456773756226520e-01 8.412181003190027928e-01 8.419659221017770090e-01 9.284452151113407048e-01 8.478881404402458521e-01 2 | 7.681041005417632572e-01 8.413531010074760674e-01 8.547066515975753065e-01 9.666980587767545208e-01 6.923798538433021399e-01 9.740521394252873444e-01 8.866001582413139959e-01 9.865540595013783109e-01 9.367538460984836668e-01 1.242421513184180260e+00 1.200594945960182347e+00 1.252212542331871292e+00 9.037396034992304372e-01 1.014474770143169335e+00 1.102482193047100489e+00 9.023624438186457208e-01 9.314236199703318508e-01 9.316330036498001732e-01 1.092961258210290332e+00 7.766105737282953392e-01 6.350007159786362765e-01 3 | 7.709530339088480622e-01 8.113395615975839137e-01 8.382517033959892006e-01 8.782559247432361049e-01 9.410202288554639916e-01 8.918119298704640929e-01 8.818063241172358069e-01 9.694628282931265773e-01 1.062524647073770812e+00 1.122506593400647068e+00 1.105053420180330592e+00 1.046927442233890115e+00 1.103774727472937478e+00 9.895209111889734510e-01 1.336126264831074550e+00 9.363561305417746894e-01 9.874418430635004684e-01 8.253192004421394667e-01 9.453706804329247149e-01 8.843685046952928230e-01 9.728376387914134948e-01 4 | 8.561918740156707619e-01 7.784208383355474270e-01 8.825234992571487913e-01 8.984828623734150144e-01 8.783007001631120136e-01 9.146994455902791588e-01 1.042706271842786858e+00 1.005172603459394853e+00 1.115351673098997853e+00 9.230907172471559674e-01 9.736894285349431133e-01 1.044145401409513951e+00 1.140237392358793178e+00 8.247584469215359926e-01 1.139990719867539637e+00 8.846481338608407352e-01 9.067592460206175264e-01 1.089992381736164750e+00 9.971851197625936081e-01 1.039546052374407337e+00 7.842130376647797885e-01 5 | 8.501847330933849367e-01 9.291309185865055387e-01 8.566642194804972021e-01 8.810711427507359472e-01 9.364127492816252119e-01 7.548695484612689688e-01 9.354380619351719828e-01 1.004152703496980381e+00 1.201424144182091203e+00 1.019278450823888349e+00 1.098660595160633635e+00 1.148377735208762296e+00 1.027405278312555792e+00 9.107411656169693837e-01 1.099819057269055600e+00 8.734515883009614790e-01 8.485216837385580746e-01 1.089176223847198477e+00 9.893196308501137626e-01 6.671134010593343655e-01 6.582311622450132127e-01 6 | 8.832098430850893189e-01 9.080712158041320814e-01 8.552935448185701173e-01 7.698870858900932479e-01 9.376406660323833853e-01 9.681414249344746370e-01 1.014987706190133121e+00 9.820559096610682603e-01 1.075100242567315734e+00 1.020114042418661437e+00 1.214749716882120634e+00 1.074716819278572100e+00 1.000352372891562203e+00 9.494378143220426614e-01 8.767084247001786235e-01 9.290448355726594887e-01 1.148326185734022120e+00 1.287664086129592933e+00 1.121057211533179609e+00 8.028513091586757522e-01 8.398828884664151229e-01 7 | 8.528548894425205251e-01 9.132687897654412357e-01 8.187325355804137006e-01 9.566363113207113633e-01 1.059184347735478982e+00 9.737102485319065748e-01 9.772998267892049062e-01 1.032575720975164701e+00 1.074133683649249660e+00 1.162839316476926177e+00 1.068246572036223307e+00 1.075337401722038733e+00 1.034015709564766183e+00 1.225210486370233109e+00 1.007860131082707111e+00 8.951100066133039768e-01 1.057719069584082128e+00 8.623431707154639581e-01 9.579157139699232548e-01 8.865798128170567782e-01 1.023454700912157955e+00 8 | 7.582102266189557627e-01 7.978148459942926429e-01 9.090758000541409034e-01 8.846993397646366608e-01 1.092841531566880020e+00 1.042053550112024274e+00 1.001557615612372221e+00 1.094209053054015168e+00 1.058689201009551439e+00 1.119876438257104256e+00 1.204764128133222645e+00 1.152214264354637585e+00 1.129235512122372498e+00 1.066554050243041951e+00 9.743878696835808206e-01 1.145785720317370027e+00 1.164214251862420557e+00 9.706268484078549585e-01 7.990814595080875105e-01 8.212105361708459395e-01 1.157962376470081711e+00 9 | 9.314754271377196915e-01 9.484715352193435756e-01 1.048601184863894087e+00 1.017738461947640172e+00 1.007597682709929332e+00 9.912848475274099735e-01 9.940979594414843801e-01 1.202986868292058364e+00 1.139071724923453433e+00 1.200564016846620952e+00 1.326364229073827783e+00 1.295185692235289565e+00 1.191426418632165030e+00 1.102127105001307728e+00 1.051508805091535992e+00 1.133186410141043376e+00 9.445901754667852535e-01 1.110029124038689252e+00 1.016796033595275484e+00 1.067364203857027460e+00 1.050580731093536224e+00 10 | 9.163184019737911079e-01 9.919176728435735724e-01 1.072706977531219907e+00 9.488165573269623509e-01 1.041709195071094607e+00 1.044668175541167310e+00 1.100406608564918898e+00 1.122223359207634941e+00 1.511456026594965696e+00 1.222958845255202931e+00 1.427095556512588903e+00 1.302352556727627064e+00 1.114387931911551943e+00 1.212587623580383633e+00 1.130477936487177093e+00 1.078343753357749346e+00 9.802400092262837372e-01 1.235806320555113968e+00 1.037688917084132800e+00 1.224807963288886858e+00 1.156423847687642725e+00 11 | 1.045637943748977117e+00 1.080307277536137089e+00 1.170826202390549797e+00 1.098955558798269783e+00 1.145067196974746127e+00 1.100835050785706093e+00 1.088155107274922262e+00 1.320354751702878637e+00 1.402706009987670921e+00 1.495607700608602153e+00 1.625891664365587852e+00 1.541277646393683698e+00 1.353738129745036600e+00 1.366786721643136193e+00 1.072579222765223772e+00 1.077382002190024446e+00 1.062137672068594663e+00 1.002892808552608095e+00 9.906501165488538208e-01 1.120940160169758615e+00 1.019765565682825059e+00 12 | 1.072472302748412210e+00 1.224214359185451739e+00 1.056476127085036687e+00 1.240658638260819346e+00 1.157879761109120276e+00 1.065240166340585715e+00 1.117845300088158300e+00 1.260024597011803804e+00 1.405000907815063371e+00 1.375990248019235640e+00 1.338923832948205606e+00 1.550757079475753697e+00 1.087033932536344505e+00 1.197480126414076640e+00 1.111280551169818720e+00 1.057306031483457032e+00 9.993003402476248187e-01 1.031569152917607424e+00 9.528221093763113991e-01 9.096871648800036736e-01 1.108887600509621763e+00 13 | 1.044904738929802734e+00 1.177642476763691937e+00 1.020351130717993771e+00 1.107118328757212611e+00 1.049935489581888204e+00 1.186575385229267310e+00 1.221622612562039301e+00 1.149185022517455357e+00 1.224231691509255260e+00 1.231128004805452703e+00 1.415723455098691241e+00 1.272930537536830498e+00 1.127334929995275292e+00 9.218500478613216309e-01 1.145974513510040316e+00 1.079346190773155190e+00 1.028865628485212458e+00 1.090390645061627195e+00 8.825370456974347411e-01 9.186583474337978172e-01 9.449192173778591108e-01 14 | 1.121493547420147285e+00 1.194255012984675623e+00 1.085254917132950636e+00 1.019401212926991374e+00 1.029149334021329576e+00 1.077073771682478087e+00 1.093471267406623593e+00 1.039239881630985352e+00 1.138886904488102925e+00 1.135487955101434743e+00 1.249581823041489015e+00 1.079662767604075313e+00 1.066984538803740890e+00 9.905353212794071327e-01 9.874634311477165083e-01 1.072396419202566342e+00 1.093141308656600863e+00 9.286525816919493082e-01 7.309199897384368594e-01 8.127940906544638411e-01 8.358872789444332652e-01 15 | 9.691809573750013174e-01 1.102911709251341854e+00 9.433358554294464238e-01 9.961104060285942419e-01 1.060265674834339755e+00 9.916703685737152663e-01 1.064983411525206591e+00 1.135902827893214173e+00 1.226103251196017041e+00 1.131711962765422186e+00 1.233057744925222465e+00 1.156577582759307221e+00 8.992088870636695264e-01 1.011262068561947336e+00 1.009050834339294322e+00 9.296603384284632954e-01 9.417048195183524983e-01 1.018734903140563475e+00 1.009996899595066333e+00 1.018264937446945240e+00 7.893678665809380490e-01 16 | 1.072607688451770791e+00 1.099874780367200211e+00 1.067902702209590826e+00 9.692727153092881576e-01 1.049940900914707376e+00 1.049661322438603550e+00 1.021784660635052910e+00 1.034414938471051038e+00 1.245010001040361303e+00 1.083968394732147456e+00 1.186730382559864516e+00 1.116698396215971112e+00 9.243689177870603180e-01 8.709869667210844435e-01 9.322932176435948515e-01 1.042307361901944063e+00 9.791741086957610474e-01 9.418510226910838945e-01 8.479371798024707418e-01 9.249834139898928109e-01 7.701187469359094262e-01 17 | 1.038086438126743172e+00 1.155582073699748635e+00 1.167084246247562129e+00 1.016400428660767519e+00 9.708971808788326996e-01 1.156345538489998770e+00 1.054000418517463178e+00 9.529148063057349960e-01 1.009653606532299852e+00 1.105873144010068421e+00 1.166894637099754162e+00 1.094954089032588840e+00 9.594406529460887123e-01 9.150370776938402395e-01 8.603715897825749970e-01 8.446832976920857217e-01 9.199898780282593780e-01 1.077866913626014167e+00 8.894092925138633587e-01 7.981172368547546636e-01 1.030143049848571968e+00 18 | 9.805665927749804833e-01 1.163164591941581838e+00 1.166850779130095273e+00 1.037244289878970438e+00 9.720865747081383068e-01 9.583427630204542913e-01 9.557791164335490697e-01 1.000791692819527734e+00 1.085015967596481223e+00 1.045143160693091877e+00 1.202292958656495880e+00 1.078261871864832466e+00 9.803822934975708892e-01 9.379864571398246476e-01 8.813044704605305091e-01 8.916851701659156415e-01 9.163946404773947174e-01 8.483975752933081704e-01 9.280087456490917486e-01 8.939667153192034643e-01 8.876905734784382718e-01 19 | 1.084884757489745333e+00 1.041985638886737897e+00 9.256038453233796925e-01 9.640818378256212906e-01 9.676275353662557865e-01 1.028598962995802113e+00 9.963943578714634652e-01 1.100402785212499346e+00 1.066722215424728004e+00 1.101676670860657348e+00 1.096740540842750855e+00 1.043593472085286633e+00 1.064907881279797186e+00 9.791815401340232539e-01 8.304951368130331080e-01 8.333704269591015734e-01 8.633565576264072838e-01 6.982210992657095217e-01 7.725737687359156558e-01 8.078237284249132344e-01 9.926096719348957986e-01 20 | 9.384302056545433812e-01 9.925259398057195703e-01 9.577389264352914600e-01 9.900305604068248000e-01 1.007192644889856936e+00 9.861551809460442630e-01 1.016205326144939303e+00 9.718498885407483856e-01 1.090568814248927820e+00 1.070950289445711689e+00 1.106022496790699083e+00 8.831422330585804170e-01 9.503720661416109605e-01 9.793482099990189482e-01 8.835099428279662437e-01 8.288477090857556684e-01 8.920613613833722200e-01 8.035349116886943976e-01 8.534272903488206996e-01 8.242252276238697384e-01 9.040254911012258754e-01 21 | 1.020430810069788752e+00 1.036231802687957337e+00 1.009390473075393313e+00 1.090864407559446470e+00 1.127440538452838092e+00 1.083845046795649303e+00 1.084770914108898365e+00 9.905531084361379746e-01 1.082046421125151703e+00 1.117345724267211349e+00 1.067569734191317954e+00 9.010645693370917808e-01 8.786741267786117859e-01 8.626733898163854164e-01 7.903655794166059012e-01 8.610373672687242630e-01 8.610926510023231284e-01 7.866410604689740849e-01 7.398595814284676386e-01 8.513716605184171726e-01 7.807875882137930157e-01 22 | -------------------------------------------------------------------------------- /docs/source/Examples/Scc1-KO.10000-10.0K_over_CH12_loops_Rao_10-shifts_dist_100000-inf_unbalanced_covnorm.np.txt: -------------------------------------------------------------------------------- 1 | 9.249014931881643919e-01 9.020536489463281127e-01 9.963796453323444657e-01 9.176582336572228771e-01 8.614135812342827991e-01 1.000073804253249765e+00 1.151721381088183449e+00 9.540831942694705248e-01 1.098598382863187783e+00 8.743144712312624911e-01 1.046396124842493780e+00 9.630564350955268527e-01 7.595381333914154043e-01 8.357372652962228310e-01 6.976597031488125378e-01 1.090776973199495403e+00 9.262213409452045854e-01 8.967218540128411020e-01 8.959868747627174335e-01 8.879945609605489620e-01 7.308238076619388846e-01 2 | 9.570576318188984688e-01 8.430367636370668105e-01 1.039838152184119568e+00 9.354392338105779192e-01 9.203680362824152583e-01 1.051936058947382513e+00 1.086682520696520271e+00 8.181338927614411061e-01 9.645499366729965995e-01 9.939890007995655363e-01 1.105640443462008404e+00 1.063078430816076114e+00 7.870856231179278462e-01 1.152503254777220709e+00 8.509584934895498831e-01 1.018616182956751492e+00 9.180443584426454251e-01 8.280149314824039042e-01 1.011775416621187196e+00 8.306015109664032225e-01 8.137845736392775864e-01 3 | 9.549218244913476594e-01 8.593600865953284762e-01 1.010451498214021804e+00 9.161232633902074429e-01 9.570753031221223006e-01 1.061440524599505553e+00 9.250162363366060125e-01 9.072122141677049223e-01 1.053584637111925515e+00 9.429346497533349636e-01 1.197638170395023627e+00 1.061125057475176714e+00 8.687399729109477331e-01 7.600428457814546457e-01 1.008021199725646966e+00 9.911522407754439490e-01 8.903959036021084072e-01 8.716949883677762578e-01 9.018204614438994904e-01 9.213461402314362392e-01 7.944320915520485249e-01 4 | 8.504472015047814804e-01 9.686246497209730633e-01 9.680106670361254828e-01 1.020094432177781396e+00 1.063261437988078484e+00 1.067418412295367824e+00 9.159758670235897959e-01 1.061115278982808219e+00 1.205186672416291405e+00 1.071889508649797040e+00 9.568780061331739750e-01 7.262410176769448222e-01 8.619752545634421503e-01 8.420266507751898999e-01 1.160961200829497830e+00 9.807437585150104997e-01 8.501720777244557992e-01 8.647635196286682646e-01 6.801413385308101578e-01 1.014697300670236002e+00 8.587979046888394308e-01 5 | 9.600927801866085964e-01 9.427458319405681575e-01 9.409740393009412562e-01 9.120638377945300412e-01 7.998716541997495932e-01 1.019199370245331027e+00 1.023542955082402672e+00 9.944423246041405040e-01 1.057314508826143751e+00 9.761259842853262647e-01 1.093944471172214383e+00 8.809678002205370007e-01 9.391425117124712063e-01 9.699526564203315715e-01 8.786152315438164884e-01 7.763388583652935937e-01 7.948112736863061079e-01 9.170761054441227689e-01 8.479756301929300966e-01 8.554949367738675647e-01 9.114672082418097121e-01 6 | 9.564468975125229866e-01 9.684299217501066703e-01 8.588058680223864538e-01 8.379334303269402318e-01 1.019723481254006581e+00 9.157591692489862600e-01 7.619705348002497880e-01 9.064701740185096002e-01 1.014967025546052115e+00 1.156978516961548742e+00 9.050808796417394442e-01 9.804342188245164236e-01 1.130400789021885011e+00 1.023012794325220298e+00 8.357364760946233151e-01 9.429468464799118932e-01 8.961241243490664088e-01 8.373678259864005824e-01 9.754580833736400391e-01 8.412209495513822688e-01 8.366503453152881464e-01 7 | 1.015739560743731396e+00 8.923909342783317156e-01 9.385144572129900942e-01 9.213035499056356770e-01 9.026211876207337337e-01 1.005003084197153784e+00 1.017611082158459412e+00 8.736525548766955751e-01 8.054798044344242403e-01 9.521059058935338326e-01 9.223990031545070689e-01 9.583394312478031862e-01 9.370035154082246853e-01 9.520004545912360561e-01 9.664913273842345998e-01 9.330512801921294619e-01 9.505250499441927348e-01 1.004345575230205734e+00 8.672118001007858012e-01 8.747439768218391309e-01 1.038295581238284804e+00 8 | 9.382678679634613994e-01 9.368631672496915419e-01 9.151358429116931426e-01 9.796546726014232487e-01 9.376138947953143177e-01 9.331899253993224397e-01 9.459280939509506769e-01 9.343407069570467405e-01 9.027417330822607999e-01 1.017692120152477342e+00 1.042599724096090030e+00 1.111207114200020163e+00 9.689528125540620707e-01 9.391520172071294859e-01 9.236691940050628657e-01 9.719666572072680477e-01 1.050112967254966279e+00 9.585042447064925364e-01 9.094370473466212301e-01 7.605963418281307398e-01 7.650112477103471198e-01 9 | 9.417258842619105064e-01 1.035903207036625195e+00 1.053227445168147813e+00 8.854182046697707253e-01 9.471342990252545890e-01 9.519408473468214948e-01 1.015626089687613476e+00 9.673658888783899235e-01 1.104333295705816731e+00 1.007130554401027611e+00 9.775166598310072175e-01 1.295432820398364271e+00 1.031130811769838118e+00 8.997363931515903746e-01 9.185267999941632011e-01 7.441569579421497549e-01 8.799468847874833966e-01 8.932730302953142409e-01 8.420158460327062944e-01 8.875939793419398427e-01 8.621333937580848428e-01 10 | 9.958081869589797686e-01 1.001661723144018579e+00 9.596962623095880440e-01 1.002514437673296399e+00 1.066321110716997200e+00 1.050674935274911181e+00 9.415394236242443649e-01 9.891469065467054511e-01 9.352133344336214238e-01 1.116518670960729098e+00 8.950012293609549419e-01 9.610342862012113407e-01 8.086314350055371358e-01 9.355125729298000570e-01 9.046368727470204263e-01 1.036583683801409750e+00 9.877131938599699179e-01 8.948914050430091249e-01 8.443624468683835760e-01 9.421397161153998168e-01 7.771968134202535960e-01 11 | 9.432344492254651769e-01 9.648682101896642882e-01 9.533879111507148618e-01 9.761573238048308898e-01 1.004266075120362256e+00 1.016517478547104947e+00 1.017270648431072955e+00 1.158495043370737498e+00 9.894239811536537088e-01 9.977510788001977549e-01 1.276185951257349904e+00 9.375519573073218815e-01 1.139673795722011773e+00 1.050960371787775349e+00 9.111075634677092694e-01 9.476654222416230899e-01 9.295032188209257917e-01 9.810917870842890132e-01 8.682436389477469207e-01 8.704840789659403777e-01 1.053278766874461425e+00 12 | 9.841440676950186095e-01 9.595604157938975032e-01 9.473415798675774990e-01 1.029121158532737113e+00 1.082659299977731804e+00 9.591688750302839184e-01 1.028820268767282720e+00 1.017444354851485544e+00 1.042633570010392585e+00 9.203301407953242697e-01 1.097262668535599950e+00 9.428978783427564014e-01 9.759291016028960319e-01 9.680757995066324728e-01 1.031406337708678844e+00 1.036757596600521580e+00 8.791018036455020557e-01 9.155725799447730351e-01 8.320798726596090322e-01 8.267239949975314639e-01 1.170334070453697750e+00 13 | 1.023920157170273848e+00 1.024626508491538024e+00 9.806382778018823965e-01 1.020801358088969213e+00 9.666701029636481923e-01 9.891588804406252766e-01 9.687015820082515161e-01 9.939671727779003652e-01 1.200555322566804195e+00 9.379482875084068638e-01 9.989621515409954355e-01 8.965265252491512182e-01 8.098273235218944599e-01 9.975082350831725453e-01 9.060742407619083449e-01 1.114382064581446619e+00 1.013031217644340343e+00 8.098524909422024631e-01 1.054763962349943629e+00 9.880425606819202011e-01 9.481327084981847619e-01 14 | 1.021224670734706796e+00 9.408900974018664654e-01 1.028581019274021457e+00 9.500566941233460350e-01 9.607606400918344836e-01 1.015395963280682823e+00 9.565879279739299967e-01 9.678555783569471327e-01 1.060894275064387049e+00 9.590414476530645382e-01 9.619999114521746719e-01 1.038621767186342915e+00 9.304978325237002190e-01 9.930781655781633077e-01 9.171451186783207143e-01 9.078148331874413834e-01 8.328291904489231179e-01 8.871031953414441062e-01 9.238383513551819970e-01 8.209302443192986187e-01 9.572115120287366663e-01 15 | 1.001307239984471131e+00 1.012650179805819839e+00 1.010702068890001470e+00 9.532338816632246470e-01 1.041497874267071966e+00 1.002020574136778031e+00 1.020251765000149025e+00 9.647053625030298507e-01 1.064703316813845113e+00 1.057751747399342745e+00 1.049576653675238003e+00 9.323695529627485934e-01 1.065937027871469933e+00 9.261630340747643020e-01 9.423627338485209837e-01 7.811301963960194383e-01 9.996601109368697946e-01 7.999835939467785373e-01 8.437586661743845529e-01 1.011233058516769256e+00 9.550129938229340310e-01 16 | 1.000869761934450430e+00 1.124203056263855194e+00 9.904805900615877290e-01 1.082176316427807317e+00 1.018125164379825920e+00 1.004800523996219441e+00 1.015069363058557883e+00 9.955594337066016042e-01 1.022238652822045735e+00 1.093059591566831967e+00 9.902829153612596746e-01 9.319919710530462087e-01 9.442364870231664264e-01 8.489492836785786922e-01 8.339181951739129683e-01 9.620939436766208219e-01 9.722621911985430687e-01 9.091861039741059303e-01 9.862441923644387209e-01 1.097681748509521160e+00 9.379422919668983782e-01 17 | 1.090746023344114635e+00 1.093971348922021525e+00 9.280148196072652844e-01 9.765846129827864264e-01 1.113803846751608262e+00 1.056245802415286761e+00 1.029933727282354550e+00 9.757861417601337850e-01 1.002818087433172689e+00 1.000684326533753943e+00 1.014532633896755076e+00 1.057510874836340209e+00 1.023616842064897448e+00 9.749032397239444370e-01 8.429107625044754970e-01 9.811491986574196744e-01 9.761839406855498114e-01 8.245915544230066896e-01 9.535475030425732967e-01 9.394273458942611343e-01 9.376601136665869696e-01 18 | 1.001364611543438699e+00 1.013215259201288410e+00 8.899545195280549326e-01 9.831381515441390828e-01 1.063858809126176919e+00 9.767477251047209652e-01 1.032467122601780973e+00 1.016423518099939027e+00 9.743647553086755009e-01 9.924199261567235864e-01 1.060961004071133251e+00 1.023375010092210102e+00 9.771299139070632744e-01 8.587248996084524411e-01 9.434350098010135799e-01 9.095653749931399412e-01 1.025037044955536381e+00 9.105007126939728135e-01 8.960330847817367106e-01 8.780541135970564293e-01 9.382044221262753059e-01 19 | 1.086324512054398284e+00 1.053964337983779087e+00 1.042690410954668412e+00 9.605773155043182410e-01 1.037591877235550353e+00 9.678300885231788664e-01 9.846870769485991381e-01 9.529960813569463562e-01 9.639828306986417683e-01 1.013398291769749049e+00 9.672767500614574132e-01 9.628931256950606921e-01 9.186065459477018580e-01 9.283852170652761027e-01 9.716451803837927725e-01 8.345837908051846332e-01 8.548553840456357689e-01 9.781357623504701726e-01 9.667040565572535549e-01 9.385601378898146274e-01 8.623893033700047450e-01 20 | 1.009482273382813489e+00 9.325968746244015506e-01 9.422481977703791589e-01 9.858073951958670200e-01 9.976862559447600143e-01 1.034290698867445846e+00 1.004958111312111768e+00 1.010674936895545661e+00 9.872648234127588962e-01 9.860080519636629237e-01 1.050790729680406654e+00 9.936624097148416546e-01 8.579244119975315552e-01 8.486905544975433813e-01 9.176129423891885573e-01 9.378911255241625389e-01 1.002856220448080204e+00 9.371669013037560170e-01 9.735517417555856756e-01 9.114892937274479134e-01 1.054890623942052352e+00 21 | 9.701936311426225812e-01 1.062855862164249876e+00 9.822664752952390277e-01 9.569482303419728497e-01 1.032191862480579259e+00 1.017033229721965748e+00 1.047916925975014069e+00 1.069363995130635958e+00 9.531191902741138477e-01 9.336978660212172931e-01 1.031855634420882684e+00 9.884539033188342039e-01 9.119457369376766653e-01 9.004288444586640017e-01 9.178774123067495738e-01 9.804753025067974859e-01 8.671180991725023768e-01 8.248125661068650416e-01 8.912715298422073662e-01 7.413032374390362556e-01 9.762959447537242763e-01 22 | -------------------------------------------------------------------------------- /docs/source/Examples/Scc1-KO.10000.cool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/Examples/Scc1-KO.10000.cool -------------------------------------------------------------------------------- /docs/source/Examples/Scc1-control.10000-10.0K_over_CH12_loops_Rao_10-shifts_dist_100000-inf_unbalanced_covnorm.np.txt: -------------------------------------------------------------------------------- 1 | 8.710794769981831109e-01 8.837150328137727273e-01 8.725393759039745678e-01 8.138979936695183159e-01 9.050191831396211528e-01 8.477362484093490247e-01 9.764944576112598584e-01 1.007571376425091758e+00 8.988023997990111091e-01 1.288651679350710566e+00 1.159055209447247936e+00 1.292970884428084055e+00 1.135651083046583132e+00 1.047077101044110004e+00 9.293440143278630661e-01 8.074425670477121120e-01 9.792673205999460340e-01 8.350761705558855663e-01 9.103002170533446291e-01 8.881481668504529470e-01 9.302660760783691973e-01 2 | 7.644425039470625904e-01 8.383367454918725370e-01 8.214271858951852634e-01 9.875184170619811796e-01 7.154839360005381677e-01 9.394711247698896983e-01 8.848212045799250802e-01 1.005234618051355611e+00 8.437495102186995943e-01 1.141039719063321689e+00 1.216389996818094010e+00 1.283350254532485524e+00 9.063894018041644962e-01 1.079938696199468584e+00 1.128083452748944282e+00 8.732018557955831817e-01 1.000543486184778397e+00 9.039628028978526908e-01 1.058045502244322256e+00 8.056974605715679916e-01 7.073419192987300264e-01 3 | 7.910653089351084022e-01 8.328652519103691976e-01 8.775402272306769280e-01 8.961694700450658635e-01 9.512644520912153512e-01 9.050607626304204567e-01 8.861331991082097570e-01 1.032965992619925721e+00 9.992939147408045342e-01 1.134054355163666594e+00 1.075547560391919344e+00 1.003318698861601410e+00 1.082303391715161878e+00 1.006216053503633523e+00 1.226650175554378164e+00 9.621994682943669774e-01 1.050004055992879159e+00 8.434101332724914801e-01 9.526770498648521324e-01 8.821290884502470675e-01 1.086203861563391104e+00 4 | 8.716626471641026885e-01 8.167962331203058035e-01 8.776020995035004324e-01 8.915390908272697867e-01 8.504262356749868745e-01 9.413202458534329908e-01 1.048730017890727728e+00 9.555751802960595898e-01 1.097554900601985572e+00 9.405955507430057150e-01 9.472485265587146097e-01 1.071679245234356648e+00 1.177230773742827807e+00 8.690554928850490191e-01 1.141590983759028566e+00 8.733634802387890694e-01 9.072863620584300515e-01 1.046170511521685720e+00 1.077410569042973387e+00 1.119994527600967293e+00 8.320043043925208215e-01 5 | 8.667607935280881026e-01 9.588126878748479687e-01 8.567775745575246793e-01 8.898613966332202807e-01 9.624675957699505568e-01 7.821566707594209689e-01 8.783256526865296232e-01 1.081658081877565625e+00 1.166478100833679754e+00 1.023370748351774218e+00 1.096989662156635292e+00 1.114532107451873033e+00 9.487679883628711286e-01 8.403747228839181238e-01 1.068511609077321012e+00 8.694267105471383816e-01 8.375125280778753512e-01 1.099978381973866881e+00 1.043388260173583326e+00 6.384906928608112819e-01 6.750896457531924133e-01 6 | 9.292660638402149287e-01 9.040386842888242791e-01 9.142824961354180102e-01 7.676139855477444041e-01 9.666680644540398548e-01 9.415300135050239660e-01 1.047019396746645681e+00 9.994005128027499962e-01 1.088535411819776089e+00 1.019829816075555673e+00 1.186707399401197849e+00 1.137260531992127621e+00 1.027108652453813109e+00 9.029225112785204121e-01 8.130773052104818266e-01 9.324846270889345368e-01 1.136155475131550130e+00 1.255236851160624001e+00 1.120710794802453059e+00 8.019904224566720696e-01 7.522423514148426360e-01 7 | 8.866818707785317777e-01 9.099334272064159013e-01 8.319400867000099620e-01 9.408973622885885568e-01 1.039073468564832847e+00 9.642046549049777537e-01 9.992328183220380300e-01 1.011287569978548628e+00 1.103987489642222819e+00 1.164280354917726079e+00 1.021019846037869661e+00 1.117232120076176560e+00 9.854273008331559947e-01 1.224099802923140468e+00 1.005468268265043763e+00 8.580586841859154656e-01 1.090541317960147749e+00 8.547442133993784497e-01 9.136239849600673590e-01 8.369435072594119118e-01 9.422102100335926211e-01 8 | 7.850012884235810784e-01 8.069222582494962603e-01 9.408716071021790972e-01 9.042617062127769056e-01 1.096903691580816798e+00 1.063878034681094098e+00 1.008601637688456121e+00 1.149217665064545590e+00 1.101257749070163605e+00 1.091621100798410460e+00 1.167846991644794885e+00 1.121602294034869995e+00 1.125429313005023912e+00 1.037344343835956861e+00 9.913119315550927846e-01 1.137396398149481680e+00 1.134787990313320005e+00 8.804847662290835597e-01 7.512086987203591137e-01 8.215261624807987939e-01 1.111878720385510944e+00 9 | 9.185705818278706580e-01 9.644137236487390075e-01 1.033495270505699892e+00 1.043519652049865520e+00 1.024008911572361180e+00 9.601693058658953284e-01 9.593172147885258294e-01 1.199665164564071462e+00 1.098958662544735176e+00 1.155891308997275546e+00 1.364788740658314570e+00 1.303796049246097155e+00 1.108241619162622760e+00 1.145462134255182507e+00 1.036298519664498041e+00 1.062247890899904235e+00 1.002215984585229203e+00 1.025541522640403880e+00 1.061751451789098688e+00 1.089688187840833322e+00 1.051519598568688707e+00 10 | 9.406891444295570892e-01 1.057001263644429701e+00 1.066074366941635487e+00 1.010465444557585357e+00 1.057799521791214836e+00 1.048441645890683338e+00 1.069391969737094161e+00 1.154315354000574834e+00 1.426048576241274901e+00 1.179003384956147871e+00 1.452651877975540184e+00 1.215313351715773926e+00 1.028183619889023737e+00 1.247292994468388372e+00 1.092923402301151370e+00 1.070705419970227057e+00 9.683704996604690640e-01 1.259308289336141362e+00 1.030049979685861761e+00 1.240686923356038696e+00 1.163662106661894846e+00 11 | 1.045973939009637199e+00 1.080464351830192404e+00 1.190383006946026168e+00 1.098999422729905362e+00 1.153678955636101122e+00 1.063965560071298722e+00 1.106158828723606602e+00 1.332513861938245503e+00 1.326639501098080265e+00 1.448616725352760204e+00 1.599227811595756110e+00 1.478049216342406602e+00 1.271188242066162877e+00 1.390475014238318208e+00 1.053244306039337053e+00 1.063366433378239773e+00 1.057929601919326945e+00 9.607069751151419146e-01 1.009388761503536180e+00 1.027359484736787731e+00 1.017369037273190502e+00 12 | 1.120971921800951510e+00 1.192926755158841390e+00 1.023331902493517909e+00 1.207137028303778337e+00 1.165135893886575902e+00 1.035983141949034181e+00 1.085689175888896685e+00 1.300690209334317116e+00 1.486702559021697789e+00 1.333292156035033926e+00 1.342219762229340141e+00 1.513862425476944384e+00 1.072369803170794222e+00 1.209131213584005327e+00 1.143339254338728184e+00 1.034874487840539370e+00 1.058609864162328051e+00 1.056222450201160790e+00 9.055087242036197193e-01 9.583905392757895436e-01 1.053844101879257700e+00 13 | 1.055572380477703076e+00 1.171516856073207213e+00 1.007464150131253344e+00 1.142649988454045529e+00 1.054521565002750627e+00 1.212660745583659772e+00 1.232828877438636228e+00 1.207050079895759520e+00 1.206493543408644342e+00 1.247475629102699601e+00 1.382554491473082958e+00 1.158126099128427233e+00 1.109481629802266500e+00 9.128452648506815148e-01 1.128167094615528665e+00 1.065388507255576878e+00 1.060006213495797489e+00 1.066131501548958749e+00 9.695316283197678020e-01 8.925454698486842142e-01 9.102509156905804755e-01 14 | 1.146361746705649720e+00 1.189486726646848291e+00 1.022062801159310919e+00 1.066447504547028080e+00 1.002288037848614977e+00 1.083830048788255507e+00 1.045446888498459570e+00 1.048262568864152700e+00 1.154753706398015334e+00 1.163055678023255934e+00 1.247315910750715018e+00 1.040426031216245217e+00 1.031597024925012818e+00 9.822457914907081200e-01 9.752901572554822929e-01 1.071866633028395244e+00 1.009864250942850594e+00 9.070586522466372870e-01 7.886582508128935354e-01 8.711957339346348972e-01 8.154122539506122314e-01 15 | 1.004052197757341780e+00 1.172096039180631877e+00 9.599824081899920314e-01 9.921371345538895214e-01 1.051880499070381614e+00 1.011800233543961314e+00 1.048047692807939857e+00 1.144543594227834804e+00 1.199414698258205236e+00 1.129781136910553707e+00 1.248704065300527022e+00 1.251546567517572539e+00 8.943198054231079608e-01 9.729709423548712488e-01 1.080785048425945361e+00 9.409185792804372062e-01 9.343010602082559846e-01 1.073458179431324711e+00 1.002479984497035348e+00 1.020351342520586790e+00 7.892713391466849027e-01 16 | 1.051053226551523556e+00 1.090318766423632457e+00 1.062689545634800670e+00 9.923075908109620924e-01 1.022639835312844525e+00 1.068293366830118218e+00 1.048260762066293816e+00 1.062716677478971361e+00 1.270351818880159245e+00 1.061925698084686287e+00 1.216034767994305321e+00 1.075254188813289602e+00 9.212163477408223944e-01 8.672809527376749150e-01 9.031816907635950020e-01 1.013475865035969425e+00 9.214548826396201653e-01 9.145724310795536605e-01 9.011480964518665537e-01 9.730700618917427214e-01 7.820761243390678130e-01 17 | 1.053450984448990324e+00 1.134264725355620396e+00 1.120433758456690354e+00 1.062442486094938632e+00 9.501383447421384298e-01 1.185843531043800247e+00 1.062718891896472950e+00 9.597334185420099972e-01 1.016204085179779781e+00 1.076005591576952192e+00 1.184738831781674939e+00 1.108852862315972576e+00 9.444753182076530695e-01 9.205035203911627883e-01 8.483493644940097722e-01 8.837996895678944531e-01 9.313370237383417072e-01 1.090868134798846922e+00 9.379463852663094681e-01 7.979943480616933371e-01 9.888171777078563762e-01 18 | 9.770246718657745744e-01 1.143548325395011389e+00 1.116685763090889738e+00 1.064452901266142115e+00 9.499754418766259700e-01 1.001582563689088934e+00 9.639914723758383763e-01 1.018343523912951687e+00 1.087656469891357780e+00 1.030552005284978367e+00 1.149716320685491233e+00 1.026996038732893135e+00 9.601559063861582199e-01 9.524915803869739017e-01 9.126188562234051060e-01 8.870388843740072415e-01 9.132525490432131798e-01 9.337007118571984954e-01 8.958588916502582267e-01 9.097687265391678491e-01 8.818070846667394047e-01 19 | 1.085007449323501572e+00 1.041671686346247183e+00 9.216858657332113181e-01 9.864692182362370110e-01 9.582091432035086953e-01 1.063381349572107171e+00 1.004950035436852351e+00 1.091240253694166995e+00 1.075794357444215699e+00 1.096557224995159840e+00 1.063218240775664736e+00 1.032912356277783106e+00 1.003782683905620532e+00 9.404488873959795381e-01 8.172465023654096328e-01 8.263287444269573623e-01 8.528620466764961217e-01 7.252460880075839444e-01 7.713028526272074359e-01 8.337141340463778416e-01 9.721517541039624843e-01 20 | 9.747634861657717975e-01 1.012451554908949891e+00 9.607587068118400575e-01 1.008467725461416054e+00 9.981451242469014939e-01 1.015000274489525456e+00 1.018137317381826001e+00 9.878620482443296602e-01 1.072481562739657335e+00 1.088169358892525640e+00 1.086233677978896139e+00 8.509325284222266639e-01 9.328823586446751692e-01 9.571191172312271123e-01 8.310024060080324348e-01 8.182940967284993983e-01 8.651833800524039164e-01 8.022619198432360266e-01 8.442553953846305692e-01 7.897297513291268167e-01 8.807466258924335767e-01 21 | 1.082405802938771755e+00 1.042530170624111463e+00 9.738296246487759822e-01 1.052587969858797878e+00 1.137191978860917940e+00 1.057047703658171134e+00 1.066505701289397257e+00 9.825904970848704512e-01 1.076276946141504265e+00 1.131492914832940455e+00 1.023264107062801687e+00 8.823668908534576527e-01 8.964915441969676380e-01 8.452896509472712649e-01 7.797157230600322286e-01 8.754916301764711362e-01 9.010764117789483718e-01 7.915612746282670864e-01 7.132225206604885237e-01 9.229263964006705345e-01 7.937090280756685656e-01 22 | -------------------------------------------------------------------------------- /docs/source/Examples/Scc1-control.10000.cool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/Examples/Scc1-control.10000.cool -------------------------------------------------------------------------------- /docs/source/Examples/Scc1KO_loop.txt: -------------------------------------------------------------------------------- 1 | 9.884077280937061394e-01 8.924325014359474340e-01 9.130076437457899097e-01 8.972040837733646912e-01 8.782521997484921128e-01 1.021334940274714942e+00 1.164226247190884855e+00 8.942595184958158638e-01 1.014517380785403100e+00 8.270231814306876483e-01 1.070019433154066002e+00 9.958866664424941284e-01 7.060946291294046828e-01 7.824295218474666136e-01 6.815908632488533181e-01 1.246379786253529076e+00 9.829886198252838492e-01 9.466372674289907918e-01 9.016985696012776996e-01 8.679750717942088523e-01 7.311448920926943984e-01 2 | 9.535588846363921567e-01 8.358447495215676204e-01 1.008688735534184477e+00 9.153758912137476278e-01 9.446491060794967032e-01 1.042368129759424722e+00 1.179326710484303931e+00 8.794909087796768388e-01 9.367805193426321786e-01 9.877916338576201438e-01 1.081256476896700347e+00 1.012549064177990843e+00 8.209846726908276437e-01 1.055868199522901119e+00 8.081351987206827348e-01 1.052242451337888518e+00 8.993892789242314834e-01 8.121184653935146214e-01 9.764558346729472760e-01 9.510536007071063169e-01 8.186860323010477503e-01 3 | 9.660581755267447779e-01 8.941241295950798085e-01 9.844571291366747134e-01 8.595947998226182163e-01 9.917137284280850285e-01 1.031329464552577235e+00 8.819145420946539193e-01 9.578758189982516935e-01 9.685226160433345610e-01 9.465421529667422673e-01 1.140866438233487878e+00 1.067842709433177939e+00 8.251856286307673871e-01 7.982372905583452471e-01 8.987410784368925487e-01 9.468928355945437358e-01 8.478499825282385105e-01 8.586160994470585228e-01 9.239693698003870193e-01 8.794542664072776406e-01 7.679407549349960282e-01 4 | 8.930662950989278759e-01 1.017481266148870800e+00 9.891301849939555524e-01 1.008857846041363748e+00 1.065900544596677824e+00 1.092514643699031174e+00 9.058625093000717277e-01 1.000141833986449180e+00 1.186175560666674622e+00 1.080597514754892963e+00 9.582834379201865538e-01 7.378702434683559463e-01 8.586066615435083982e-01 8.563254849726757989e-01 1.059795056107381672e+00 1.015647662159101738e+00 8.761215764331773403e-01 9.157862633519729956e-01 6.759544160067835206e-01 1.057156355231602785e+00 8.516405299641273130e-01 5 | 9.647016213276631280e-01 9.270683092337351772e-01 1.002985247308252115e+00 8.780229891060545855e-01 8.083759802707023434e-01 1.023951027476291742e+00 1.025389362165888052e+00 9.864967023816235692e-01 1.032552838251423966e+00 1.060162613116898411e+00 1.026013719648239286e+00 8.574101226432144784e-01 9.102563350321362101e-01 9.167222303547973850e-01 9.399553377651324038e-01 7.612239028599734336e-01 8.096139580526396928e-01 9.543885463247961942e-01 8.043983433124308746e-01 8.563208913865065774e-01 8.563342282800212590e-01 6 | 9.897119575838030370e-01 9.529490534620825848e-01 8.543800702630302002e-01 8.450729585259831866e-01 9.855930850973805279e-01 8.824271281374783671e-01 7.355745379728296784e-01 9.162926939692851436e-01 9.841556049553139562e-01 1.134404653871289526e+00 9.167980050721884488e-01 1.010583835589147661e+00 1.113356005686597427e+00 1.003833963670046847e+00 9.079312498071194781e-01 9.689037686975999764e-01 8.828654129365410830e-01 8.693519795651667437e-01 8.928313011216247874e-01 8.162271192711653134e-01 8.034409573884339073e-01 7 | 1.003527474467689862e+00 9.100639197493272103e-01 9.275958545032106928e-01 9.072958147032852416e-01 8.943316166352662799e-01 1.023334994004462040e+00 9.634493900010507872e-01 8.765895754141065366e-01 8.222634606698036031e-01 9.597936896066798784e-01 9.042530923029989953e-01 8.427763547604099070e-01 9.686542752398000777e-01 9.202224516716944747e-01 9.421557715632374874e-01 9.375161088442738322e-01 9.611741749011535330e-01 9.774574976713990004e-01 8.810775704380535700e-01 8.943425793959024483e-01 1.005929302387082336e+00 8 | 9.622613377351757480e-01 9.296079391946839854e-01 9.125094679902606698e-01 9.793095718030931929e-01 8.951070858344339909e-01 9.156413706738171232e-01 1.015178915821389527e+00 9.041275511211266380e-01 9.008548662166698806e-01 9.388557016214558182e-01 9.685734794958419380e-01 1.085475868080232997e+00 1.000174021764680621e+00 9.205133778119369836e-01 1.013218537911855899e+00 9.860612152976375722e-01 1.064792868731499809e+00 1.034113583605765108e+00 8.988330424197008561e-01 7.874122315947251760e-01 7.722768065857938957e-01 9 | 9.378569052055354405e-01 1.010584116996643189e+00 1.048902798044490492e+00 9.413772505019710746e-01 9.032459011305941088e-01 9.557094947333086843e-01 1.008762445472921376e+00 9.184787127091107450e-01 9.422910352630174957e-01 1.009352272012710827e+00 1.062681950295421451e+00 1.296067034736156698e+00 1.016387288032056357e+00 8.897659390704716342e-01 9.587437148874221604e-01 7.737661687064226745e-01 8.661368028591126533e-01 9.091932217413866146e-01 8.276930248798031187e-01 8.966040467726481555e-01 8.640505210399583857e-01 10 | 9.966726701793851007e-01 1.026904186018717358e+00 9.772669213801314925e-01 9.898223002292499961e-01 1.029382157351730109e+00 9.757858895038811209e-01 8.815413189251116721e-01 9.420187618019288944e-01 9.330811830452192535e-01 1.150610280586979117e+00 9.526284032843468363e-01 9.579390134480452179e-01 8.164928155651953734e-01 9.593732585509512356e-01 9.268489596175938372e-01 1.000903558864288279e+00 9.781788838206600945e-01 9.704856504252727945e-01 8.693629510248165326e-01 9.128274800627291796e-01 7.426897238467117246e-01 11 | 9.824804395427135795e-01 9.561017361823295202e-01 9.431105032702892244e-01 9.637674235401451073e-01 1.022984187049917004e+00 1.019697434722369289e+00 1.020974726188294879e+00 1.129505518525161456e+00 9.617811314789396215e-01 9.731202025680972811e-01 1.284156911481669772e+00 9.534295652871868088e-01 1.147776123567784134e+00 1.063039686713598941e+00 9.191212298198668806e-01 9.931750282415369169e-01 9.692922730646399421e-01 1.009533938712656731e+00 9.405939941925017811e-01 8.326861626008726924e-01 1.000579405664509647e+00 12 | 9.895228598294624200e-01 9.651853741680975762e-01 9.568284792119988724e-01 1.035103152621903000e+00 1.071549739695000669e+00 9.522868248088640630e-01 9.951082644691562340e-01 1.015773625758079834e+00 9.909332453606629620e-01 9.441571711872944750e-01 1.134977434165026944e+00 9.916349387429947981e-01 1.040965753788019477e+00 9.695175187103924896e-01 9.486699388447269454e-01 1.078825542991955988e+00 9.263264960968088380e-01 9.430459922233012104e-01 8.429878826073466946e-01 7.957683783132398769e-01 1.172335545369959986e+00 13 | 1.034748398907092470e+00 1.022791009512676874e+00 9.902167527159058125e-01 1.020433989221380289e+00 9.722042647662658688e-01 1.022126261914410472e+00 9.390700781388273688e-01 9.954348708122664480e-01 1.179114008699619465e+00 9.839919881146262925e-01 9.680981597885859324e-01 9.228311118433444316e-01 8.772551179107085373e-01 9.539278857988352511e-01 8.965334667730068263e-01 1.146475386409167685e+00 1.018329364763860712e+00 8.008364882655385486e-01 1.037022615745784915e+00 9.619918004497753916e-01 9.191808441556597042e-01 14 | 1.026654775279464360e+00 9.677582534957996918e-01 1.020119296578154255e+00 9.714897551521005648e-01 9.803714228491402505e-01 1.023482071374436142e+00 9.333643366266427543e-01 9.569815711786413548e-01 1.006974510654783384e+00 9.422932191738940810e-01 9.469798318284676775e-01 9.922239860907455800e-01 9.594788297998174675e-01 1.008828705483875376e+00 9.058728879339311701e-01 8.692899445582563667e-01 8.370407321246495780e-01 8.840524864123631144e-01 8.592573576937764246e-01 8.277641593416025234e-01 9.391640896534834138e-01 15 | 9.840752418681567582e-01 1.014624694700677177e+00 1.009210270691365929e+00 9.450268066897292707e-01 1.042643810799274817e+00 9.852172007556400102e-01 1.014498580748592671e+00 9.247348151460929033e-01 1.045075768425653751e+00 1.062776600876089717e+00 1.066820397336610382e+00 9.407195501445322350e-01 1.101324570617536525e+00 9.100108556241646163e-01 8.797335974841548056e-01 7.872259466691544638e-01 9.943281575969482589e-01 8.303781977580860785e-01 8.159489931502253990e-01 9.694796437074156836e-01 9.990292737948803792e-01 16 | 1.005444832675437272e+00 1.131735791798638369e+00 9.677741334695277864e-01 1.087653908658740898e+00 1.012058516899708716e+00 9.548241810924869011e-01 1.015893892591888337e+00 9.614463356829202612e-01 9.820095095226057946e-01 1.065512665832554218e+00 1.024476101088948266e+00 9.132552104607279952e-01 9.646628844769297162e-01 8.431044282944618606e-01 8.413443837505266698e-01 9.004117583966054772e-01 9.282350667086468610e-01 9.532483241742567559e-01 9.011225217829280654e-01 9.468398404927341749e-01 8.806857185572799507e-01 17 | 1.091335760166853186e+00 1.069159541005125114e+00 9.333305984830679858e-01 9.904657355008775754e-01 1.077554688227388535e+00 1.027520531867535780e+00 9.975210350329110076e-01 9.806829452543185388e-01 9.669075609775107383e-01 9.865965593199659267e-01 9.748191596557337357e-01 1.044107451130522612e+00 1.034780035601060355e+00 9.659251436323442741e-01 8.366396966551985503e-01 9.721566801270141722e-01 1.020918243744776355e+00 8.221287222481885593e-01 9.517477372140941139e-01 9.457414116085341993e-01 9.066369720244110697e-01 18 | 9.610016158454270929e-01 9.739700640003345899e-01 8.855041903221015920e-01 9.788336884845588726e-01 1.084168467862538954e+00 9.692586167558101540e-01 1.008477104811232872e+00 1.004659997606812016e+00 9.601739096369140691e-01 9.978716850058972909e-01 1.074169528090066938e+00 1.021094477159527392e+00 1.000444233131390304e+00 8.927995086252455970e-01 9.324076391474280801e-01 9.044263869566252501e-01 1.037449633206644517e+00 9.306768662442762574e-01 8.920691584474784719e-01 8.359938003971503218e-01 9.413610116339115041e-01 19 | 1.051382586138163822e+00 1.041404824951877028e+00 9.932452386521144483e-01 9.844758922373556542e-01 1.006182431416279721e+00 9.591194290518970655e-01 9.869848743593954143e-01 9.537034662033977428e-01 9.394791777303872493e-01 9.903486697966490393e-01 9.556938776181095330e-01 9.760322585237467541e-01 9.560478002942340847e-01 9.189362434732730733e-01 9.571750430251401154e-01 8.101325528626389660e-01 8.706549937659412430e-01 9.867240278960461852e-01 9.103632440580901042e-01 9.296546160998732100e-01 8.670775812976146968e-01 20 | 1.039571941516771458e+00 9.532305795842230811e-01 9.472554826401893280e-01 1.002528064068729741e+00 1.018211868969552736e+00 1.039712382084428954e+00 1.003245164275362811e+00 9.740777603338222068e-01 9.923674341189580028e-01 9.820010829846647082e-01 1.058298724132579638e+00 9.811198453152080168e-01 9.081418154757554539e-01 8.537639652595868656e-01 8.985481662711011230e-01 9.186952581186951239e-01 9.988265403844317492e-01 9.333345758403930326e-01 9.278020733269329856e-01 9.558607345826038992e-01 1.004356056498527217e+00 21 | 9.851498967813904217e-01 1.100502704378193197e+00 1.012082958110190001e+00 9.649431629560321078e-01 1.049587712296415454e+00 1.046682681214851085e+00 1.038025493928568466e+00 1.043644397056409989e+00 9.266448699113069010e-01 9.313099707027817642e-01 1.058606628617121181e+00 9.717786353358310869e-01 9.263546690662590732e-01 9.050428133971344380e-01 9.066365039541827153e-01 9.833643608928545055e-01 8.742241141564296436e-01 8.410885873875683094e-01 8.927612140241897309e-01 7.187724055982123161e-01 9.672572295124457487e-01 22 | -------------------------------------------------------------------------------- /docs/source/Examples/TADs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/Examples/TADs.png -------------------------------------------------------------------------------- /docs/source/Examples/all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/Examples/all.png -------------------------------------------------------------------------------- /docs/source/Examples/loops.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/Examples/loops.png -------------------------------------------------------------------------------- /docs/source/Examples/stripes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/Examples/stripes.png -------------------------------------------------------------------------------- /docs/source/_static/my_theme.css: -------------------------------------------------------------------------------- 1 | .wy-nav-content { 2 | max-width: none !important; 3 | } 4 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | import mock 16 | 17 | sys.path.insert(0, os.path.abspath("../..")) 18 | sys.path.insert(0, os.path.abspath("..")) 19 | 20 | 21 | # -- Project information ----------------------------------------------------- 22 | 23 | project = "coolpup.py" 24 | copyright = "2020, Ilya M. Flyamer" 25 | author = "Ilya M. Flyamer" 26 | 27 | # The full version, including alpha/beta/rc tags 28 | import re 29 | 30 | VERSIONFILE = "../../coolpuppy/_version.py" 31 | verstrline = open(VERSIONFILE, "rt").read() 32 | VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]" 33 | mo = re.search(VSRE, verstrline, re.M) 34 | if mo: 35 | verstr = mo.group(1) 36 | else: 37 | raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,)) 38 | release = verstr 39 | 40 | 41 | # -- General configuration --------------------------------------------------- 42 | 43 | # Add any Sphinx extension module names here, as strings. They can be 44 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 45 | # ones. 46 | extensions = [ 47 | "myst_nb", 48 | # 'sphinx_argparse_cli', 49 | # 'myst_parser', 50 | "sphinx.ext.napoleon", 51 | "sphinx.ext.autodoc", 52 | # "sphinx.ext.viewcode", 53 | # "sphinx.ext.githubpages", 54 | # "sphinx.ext.mathjax", 55 | "sphinxarg.ext", 56 | # 'm2r2' 57 | ] 58 | napoleon_numpy_docstring = True 59 | 60 | MOCK_MODULES = [ 61 | "Cython", 62 | "bioframe", 63 | "cooler", 64 | "cooltools", 65 | "cooltools.lib", 66 | "cooltools.api", 67 | "h5py", 68 | "h5sparse", 69 | "matplotlib", 70 | "matplotlib.colors", 71 | "matplotlib.font_manager", 72 | "matplotlib.pyplot", 73 | "matplotlib.ticker", 74 | "matplotlib.gridspec", 75 | "more_itertools", 76 | "mpl_toolkits.axes_grid1", 77 | "natsort", 78 | "numpy", 79 | "pandas", 80 | "pysam", 81 | "scipy", 82 | "scipy.linalg", 83 | "seaborn", 84 | "multiprocessing_logging", 85 | ] 86 | 87 | for mod_name in MOCK_MODULES: 88 | sys.modules[mod_name] = mock.Mock() 89 | 90 | autodoc_mock_imports = MOCK_MODULES 91 | 92 | # Add any paths that contain templates here, relative to this directory. 93 | templates_path = ["_templates"] 94 | 95 | # List of patterns, relative to source directory, that match files and 96 | # directories to ignore when looking for source files. 97 | # This pattern also affects html_static_path and html_extra_path. 98 | exclude_patterns = ["_build", "**.ipynb_checkpoints"] 99 | 100 | 101 | # -- Options for HTML output ------------------------------------------------- 102 | 103 | # The theme to use for HTML and HTML Help pages. See the documentation for 104 | # a list of builtin themes. 105 | # 106 | html_theme = "sphinx_rtd_theme" 107 | 108 | # Add any paths that contain custom static files (such as style sheets) here, 109 | # relative to this directory. They are copied after the builtin static files, 110 | # so a file named "default.css" will overwrite the builtin "default.css". 111 | html_static_path = ["_static"] 112 | 113 | add_module_names = True 114 | 115 | # master_doc = 'index' 116 | 117 | 118 | def skip(app, what, name, obj, would_skip, options): 119 | if name == "__init__": 120 | return False 121 | return would_skip 122 | 123 | 124 | def setup(app): 125 | app.connect("autodoc-skip-member", skip) 126 | app.add_css_file("my_theme.css") 127 | 128 | 129 | source_suffix = [".rst", ".md", ".ipynb"] 130 | html_favicon = "favicon.ico" 131 | 132 | autodoc_docstring_signature = True 133 | nbsphinx_execute = "never" 134 | jupyter_execute_notebooks = "off" 135 | -------------------------------------------------------------------------------- /docs/source/coolpup_py_cli.md: -------------------------------------------------------------------------------- 1 | # coolpup.py CLI 2 | 3 | Use `coolpup.py` command to perform pileups, and `plotpup.py` to visualize them. 4 | 5 | ## Submodules 6 | 7 | ## coolpup.py command 8 | 9 | ```{eval-rst} 10 | .. argparse:: 11 | :module: coolpuppy.CLI 12 | :func: parse_args_coolpuppy 13 | :prog: coolpup.py 14 | ``` 15 | 16 | ## dividepups.py command 17 | 18 | ```{eval-rst} 19 | .. argparse:: 20 | :module: coolpuppy.divide_pups_CLI 21 | :func: parse_args_divide_pups 22 | :prog: dividepups.py 23 | ``` 24 | 25 | ## plotpup.py command 26 | 27 | ```{eval-rst} 28 | .. argparse:: 29 | :module: coolpuppy.plotpuppy_CLI 30 | :func: parse_args_plotpuppy 31 | :prog: plotpup.py 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/source/coolpuppy.rst.bak: -------------------------------------------------------------------------------- 1 | coolpuppy package 2 | ================= 3 | 4 | Submodules 5 | ---------- 6 | 7 | coolpuppy.coolpup module 8 | ------------------------ 9 | 10 | .. automodule:: coolpuppy.coolpup 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | coolpuppy.plotpup module 16 | ------------------------ 17 | 18 | .. automodule:: coolpuppy.plotpup 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | 24 | Module contents 25 | --------------- 26 | 27 | .. automodule:: coolpuppy 28 | :members: 29 | :undoc-members: 30 | :show-inheritance: 31 | -------------------------------------------------------------------------------- /docs/source/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/favicon.ico -------------------------------------------------------------------------------- /docs/source/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/favicon.png -------------------------------------------------------------------------------- /docs/source/figs/chip_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/figs/chip_profile.png -------------------------------------------------------------------------------- /docs/source/figs/example_local_pileup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/figs/example_local_pileup.png -------------------------------------------------------------------------------- /docs/source/figs/example_local_rescaled_pileup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/figs/example_local_rescaled_pileup.png -------------------------------------------------------------------------------- /docs/source/figs/example_loop_pileup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/figs/example_loop_pileup.png -------------------------------------------------------------------------------- /docs/source/figs/example_pileup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/figs/example_pileup.png -------------------------------------------------------------------------------- /docs/source/figs/local_quant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/figs/local_quant.png -------------------------------------------------------------------------------- /docs/source/figs/local_quant_borders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/figs/local_quant_borders.png -------------------------------------------------------------------------------- /docs/source/figs/local_quant_tads.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/figs/local_quant_tads.png -------------------------------------------------------------------------------- /docs/source/figs/loop_quant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/figs/loop_quant.png -------------------------------------------------------------------------------- /docs/source/figs/loopability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/figs/loopability.png -------------------------------------------------------------------------------- /docs/source/figs/new_grid_loop_quant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/docs/source/figs/new_grid_loop_quant.png -------------------------------------------------------------------------------- /docs/source/index.md: -------------------------------------------------------------------------------- 1 | # Welcome to coolpup.py's documentation! 2 | 3 | Project homepage with code and issues is on [GitHub](https://github.com/open2c/coolpuppy). 4 | 5 | Please feel free to report any problems or contribute. 6 | 7 | ```{include} ../../README.md 8 | :relative-images: 9 | ``` 10 | 11 | ```{toctree} 12 | :caption: 'Tutorials:' 13 | :maxdepth: 2 14 | walkthrough.md 15 | Examples/Walkthrough_API.ipynb 16 | Examples/Walkthrough_CLI.ipynb 17 | Examples/TAD_score.ipynb 18 | ``` 19 | ```{toctree} 20 | :caption: 'API reference:' 21 | :maxdepth: 2 22 | coolpup_py_cli.md 23 | modules.md 24 | ``` 25 | 26 | # Indices and tables 27 | 28 | - {ref}`genindex` 29 | - {ref}`modindex` 30 | - {ref}`search` 31 | -------------------------------------------------------------------------------- /docs/source/modules.md: -------------------------------------------------------------------------------- 1 | # coolpuppy Python API 2 | 3 | While coolpup.py was designed with CLI in mind, it's possible to use the classes and 4 | functions directly in Python code to perform pileups. 5 | 6 | ```{toctree} 7 | :maxdepth: 4 8 | ``` 9 | 10 | ## coolpuppy.coolpup module 11 | 12 | ```{eval-rst} 13 | .. automodule:: coolpuppy.coolpup 14 | :members: 15 | :undoc-members: 16 | :show-inheritance: 17 | ``` 18 | 19 | ## coolpuppy.lib.io module 20 | 21 | ```{eval-rst} 22 | .. automodule:: coolpuppy.lib.io 23 | :members: 24 | :undoc-members: 25 | :show-inheritance: 26 | ``` 27 | 28 | ## coolpuppy.lib.numutils module 29 | 30 | ```{eval-rst} 31 | .. automodule:: coolpuppy.lib.numutils 32 | :members: 33 | :undoc-members: 34 | :show-inheritance: 35 | ``` 36 | 37 | ## coolpuppy.lib.puputils module 38 | 39 | ```{eval-rst} 40 | .. automodule:: coolpuppy.lib.puputils 41 | :members: 42 | :undoc-members: 43 | :show-inheritance: 44 | ``` 45 | 46 | ## coolpuppy.plotpup module 47 | 48 | ```{eval-rst} 49 | .. automodule:: coolpuppy.plotpup 50 | :members: 51 | :undoc-members: 52 | :show-inheritance: 53 | ``` 54 | -------------------------------------------------------------------------------- /docs/source/walkthrough.md: -------------------------------------------------------------------------------- 1 | # Guide to pileup analysis 2 | 3 | Coolpup.py is a tool for pileup analysis. But what are pile-ups? 4 | 5 | If you don't know, you might have seen average ChIP-seq or ATAC-seq profiles which look something like this: 6 | 7 | ![ChIP profile](figs/chip_profile.png) 8 | 9 | Pile-ups in Hi-C are essentially the same as average profiles, but in 2 dimensions, since 10 | Hi-C data is a a matrix, not a linear track! 11 | 12 | Therefore instead of a linear plot, pileups are usually represented as heatmaps - by mapping values of different pixels in the average matrix to specific colours. 13 | 14 | ## Pile-ups of interactions between a set of regions 15 | 16 | For example, we can again start with ChIP-seq peaks, but instead of averaging ChIP-seq data around them, combine them with Hi-C data and check whether these regions are often found in proximity to each other. The algorithm is simple: we find intersections of all peaks in the Hi-C matrix (with some padding around the peak), and average them. If the peaks often interact, we will detect an enrichment in the centre of the average matrix: 17 | 18 | ![Grid averaging](figs/new_grid_loop_quant.png) 19 | 20 | Here is a real example: 21 | 22 | ![Example pileup](figs/example_pileup.png) 23 | 24 | Here I averaged all (intra-chromosomal) interactions between highly enriched ChIP-seq peaks of RING1B in mouse ES cells. I added 100 kbp padding to each bin containing the peak, and since I used 5 kbp resolution Hi-C data, the total length of each side of this heatmap is 205 kbp. I also normalizes the result by what we would expect to find by chance, and therefore the values indicate observed/expected enrichment. Because of that, the colour is log-scaled, so that the neutral grey colour corresponds to 1 - no enrichment or depletion, while red and blue correspond to value above and below 1, respectively. 25 | 26 | What is important, is that in the center we see higher values than on the edges: this means that regions bound by RING1B tend to stick together more, than expected! The actual value in the central pixel is displayed on top left for reference. 27 | 28 | This analysis is the default mode when coolpup.py is run with a .bed file, e.g. `coolpup.py my_hic_data.cool my_protein_peaks.bed` (with optional `--expected my_hic_data_expected.tsv` for normalization to the background level of interactions). 29 | 30 | ## Pile-ups of predefined regions pairs, e.g. loops 31 | 32 | A similar approach is based on averaging predefined 2D regions corresponding to interactions of specific pairs of regions. A typical example would be averaging loop annotations. This is very useful to quantify global perturbations of loop strength (e.g. annotate loops in WT, compare their strength in WT vs KO of an architectural protein), or to quantify them in data that are too sparse, such as single-cell Hi-C. 33 | The algorithm is very simple: 34 | 35 | ![Loop averaging](figs/loop_quant.png) 36 | 37 | And here is a real example of CTCF-associated loops in ES cells: 38 | 39 | ![Example loop pileup](figs/example_loop_pileup.png) 40 | 41 | Comparing with the previous example, you can clearly see that if you average loops that have been previously identified you, of course, get much higher enrichment of interactions, than if you are looking for a tendency of some regions to interact. 42 | 43 | This analysis is performed with coolpup.py when instead of a bed file you provide a .bedpe file, so simply `coolpup.py my_hic_data.cool my_loops.bedpe` (with optional `--expected my_hic_data_expected.tsv` for normalization to the background level of interactions). `bedpe` is a simple tab-separated 6-column file with chrom1, start1, end1, chrom2, start2, end2. 44 | 45 | ## Local pileups 46 | 47 | A very similar approach can be used to quantify local properties in Hi-C maps, such as insulation. Valleys of insulation score can be identified (e.g. using `cooltools diamond-insulation`), or another way of identifying potential TAD boundaries can be used. Then regions around their positions can be averaged, and this can be used to visualize and quantify insulation in the same or another sample: 48 | 49 | ![Boundary averaging](figs/local_quant_borders.png) 50 | 51 | Here is an example of averaged insulation score valleys in mouse ES cells: 52 | 53 | ![Example local pileup](figs/example_local_pileup.png) 54 | 55 | One can easily observe that these regions on average indeed have some insulating properties, and moreover the stripes emanating from the boundaries are very clear - they are a combination of real stripes found on edges of TADs in many cases, and loops found at different distances from the boundary in different TADs. 56 | 57 | Average insulation can be quantiifed by dividing signal in two red squares (top left and bottom right corners) by the signal in the more blue squares (top right and bottom left corners), and here it is shown in the top left corner. 58 | 59 | This analysis is very easily performed using coolpup.py: simply run `coolpup.py my_hic_data.cool my_insulating_regions.bed --local` (with optional `--expected my_hic_data_expected.tsv` for normalization to the background level of interactions; note that for local analyses in my experience random shift controls work better). 60 | 61 | ### Rescaled pileups 62 | 63 | If instead of boundary regions you have, for example, annotation of long domains, such as TADs, you can also average them to analyse internal interactions within these domains. The problem with simply applying the previous analysis to this case is that these domains can be of different length, and direct averaging will produce nonsensical results. However the submatrices corresponding to interactions within each domain (with some padding around) can all be individually rescaled to the same size, and then averaged. This way boundaries of these domains would be aligned in the final averaged matrices, and the pileups would make sense! here is a visual explanation of this idea: 64 | 65 | ![Local rescaled averaging](figs/local_quant_tads.png) 66 | 67 | And here is an example of such local rescaled pileups of TADs annotated using insulation score valleys used above in ES cells: 68 | 69 | ![Example local rescaled pileup](figs/example_local_rescaled_pileup.png) 70 | 71 | Each TAD was padded with the flanks of the same length as the TAD, and then they were all rescaled to 99x99 pixels. The pattern of the average TAD is very clear, in particular the corner loop at the top of the domain is highly enriched. Also the stripes, indicative of loop extrusion, both on the TAD borders and outside the TADs, are clearly visible. 72 | 73 | You might notice that I removed the few central diagonals of the matrix here. That is because they are often noisy after this rescaling procedure, depending on the data you use. 74 | 75 | To perform this analysis, you simply need to call `coolpup.py my_hic_data.cool my_domains.bed --rescale --local` (with optional `--expected my_hic_data_expected.tsv` for normalization to the background level of interactions). To specify the side of the final matrix as 99 bins add `--rescale_size 99`. Another useful option here is `--rescale_pad`, which defines the fraction of the original regions to use when padding them; the default value is 1, so each TAD is flanked on each side by a region of the same size. 76 | -------------------------------------------------------------------------------- /loop_quant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/loop_quant.png -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | addopts = 3 | --cov cooltools 4 | --cov-config .coveragerc 5 | --cov-report term-missing 6 | --cov-report html 7 | --cov-report xml 8 | filterwarnings = 9 | ignore::PendingDeprecationWarning 10 | testpaths = 11 | tests 12 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | -r requirements.txt 2 | pytest 3 | pytest-flake8 4 | pytest-cov 5 | nbval -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | h5py>=3.0 2 | Cython 3 | cooler 4 | numpy>=1.16.5 5 | pandas<=2.2.2 6 | scipy 7 | cooltools>=0.5.2 8 | pyyaml 9 | more_itertools 10 | bioframe>=0.3.3 11 | matplotlib<=3.8.0 12 | seaborn 13 | natsort 14 | h5sparse 15 | multiprocessing_logging 16 | tables -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | import os 3 | from os import path 4 | import io 5 | 6 | this_directory = path.abspath(path.dirname(__file__)) 7 | with open(path.join(this_directory, "README.md"), encoding="utf-8") as f: 8 | long_description = f.read() 9 | 10 | import re 11 | 12 | VERSIONFILE = "coolpuppy/_version.py" 13 | verstrline = open(VERSIONFILE, "rt").read() 14 | VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]" 15 | mo = re.search(VSRE, verstrline, re.M) 16 | if mo: 17 | verstr = mo.group(1) 18 | else: 19 | raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,)) 20 | 21 | 22 | def _read(*parts, **kwargs): 23 | filepath = os.path.join(os.path.dirname(__file__), *parts) 24 | encoding = kwargs.pop("encoding", "utf-8") 25 | with io.open(filepath, encoding=encoding) as fh: 26 | text = fh.read() 27 | return text 28 | 29 | 30 | def get_requirements(path): 31 | content = _read(path) 32 | return [ 33 | req 34 | for req in content.split("\n") 35 | if req != "" and not (req.startswith("#") or req.startswith("-")) 36 | ] 37 | 38 | 39 | setup_requires = [ 40 | "cython", 41 | "numpy", 42 | ] 43 | 44 | on_rtd = os.environ.get("READTHEDOCS") == "True" 45 | if on_rtd: 46 | INSTALL_REQUIRES = [] 47 | else: 48 | INSTALL_REQUIRES = get_requirements("requirements.txt") 49 | 50 | setup( 51 | name="coolpuppy", 52 | version=verstr, 53 | packages=["coolpuppy", "coolpuppy.lib"], 54 | entry_points={ 55 | "console_scripts": [ 56 | "coolpup.py = coolpuppy.CLI:main", 57 | "plotpup.py = coolpuppy.plotpuppy_CLI:main", 58 | "dividepups.py = coolpuppy.divide_pups_CLI:main", 59 | ] 60 | }, 61 | setup_requires=setup_requires, 62 | install_requires=INSTALL_REQUIRES, 63 | python_requires=">=3.8", 64 | description="A versatile tool to perform pile-up analysis on Hi-C data in .cool format.", 65 | long_description=long_description, 66 | long_description_content_type="text/markdown", 67 | project_urls={ 68 | "Source": "https://github.com/open2c/coolpuppy", 69 | "Issues": "https://github.com/open2c/coolpuppy/issues", 70 | }, 71 | author="Open2C", 72 | author_email="flyamer@gmail.com", 73 | classifiers=[ 74 | "Programming Language :: Python", 75 | "Programming Language :: Python :: 3", 76 | "Programming Language :: Python :: 3.8", 77 | "Programming Language :: Python :: 3.9", 78 | "Programming Language :: Python :: 3.10", 79 | "License :: OSI Approved :: MIT License", 80 | "Operating System :: OS Independent", 81 | ], 82 | zip_safe=False, 83 | ) 84 | -------------------------------------------------------------------------------- /tests/Scc1-control.10000.cool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/tests/Scc1-control.10000.cool -------------------------------------------------------------------------------- /tests/Scc1-control.10000.numeric_chroms.cool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/tests/Scc1-control.10000.numeric_chroms.cool -------------------------------------------------------------------------------- /tests/bed2_ref.np.txt: -------------------------------------------------------------------------------- 1 | # anchor: null 2 | # baselist: tests/Bonev_CTCF+.bed 3 | # bed2: tests/Bonev_CTCF-.bed 4 | # bed2_ordered: true 5 | # bed_ordered: true 6 | # by_window: false 7 | # coolfile: tests/Scc1-control.10000.cool 8 | # coverage_norm: true 9 | # excl_chrs: chrY,chrM 10 | # expected: null 11 | # incl_chrs: all 12 | # local: false 13 | # logLevel: INFO 14 | # maxdist: null 15 | # maxshift: 1000000 16 | # maxsize: null 17 | # mindist: 0 18 | # minshift: 100000 19 | # minsize: null 20 | # n_proc: 2 21 | # nshifts: 10 22 | # outdir: tests 23 | # outname: testing_bed2.txt 24 | # pad: 100 25 | # post_mortem: false 26 | # rescale: false 27 | # rescale_pad: 1.0 28 | # rescale_size: 99 29 | # save_all: false 30 | # seed: 0 31 | # subset: 1000 32 | # unbalanced: true 33 | # weight_name: weight 34 | 1.191774571909626435e+00 7.582461439214820409e-01 1.069791820375177949e+00 1.447146888428999967e+00 1.032399883251982731e+00 8.250184084258790351e-01 1.190875081335256658e+00 1.254220640716348090e+00 5.206429656647000304e-01 1.163452824895052862e+00 1.059306153274307327e+00 5.503634114198475702e-01 1.015602989749989193e+00 8.804763837176691199e-01 1.337320041226072842e+00 9.627023315880223198e-01 1.386579525153335712e+00 8.416111127677362580e-01 1.019793102904745563e+00 4.935308374295102052e-01 1.434544649845540532e+00 35 | 8.336874537371994354e-01 7.760798993166727611e-01 9.880443969927329428e-01 1.270380923262338868e+00 6.813466559491524466e-01 1.368436453223164317e+00 9.482509771148812661e-01 7.585991761701875724e-01 6.010259842149656695e-01 1.057094656324267579e+00 1.276155638698719619e+00 7.616976704544085042e-01 1.104979294089602160e+00 9.886654845689015758e-01 8.357118550713688032e-01 8.735371207996501797e-01 9.952733633814567771e-01 9.722709346366815719e-01 8.029034155847312171e-01 6.759013139291045746e-01 5.134558723090397736e-01 36 | 8.950777776481090298e-01 1.051804209704934490e+00 9.321550908105731281e-01 7.325467991423855185e-01 8.696247842547597529e-01 8.096784914088165364e-01 9.063606934675052518e-01 9.475829678839923220e-01 7.960948345626236433e-01 1.005297763320082804e+00 1.171922513177655611e+00 1.130324984161479973e+00 1.641615990316784846e+00 1.018181198672012622e+00 1.577519329406140036e+00 1.049040177202618995e+00 1.642923362961203670e+00 1.443408406830188673e+00 8.901272787315995805e-01 1.031172699451914587e+00 1.134023726436096391e+00 37 | 9.400671970039534697e-01 1.068316616112576112e+00 8.250234911390259551e-01 9.243071021236346496e-01 1.165930834362121526e+00 9.926859231067731715e-01 1.229822723941239593e+00 7.611912016036705975e-01 9.404875887884065477e-01 6.002190272975865826e-01 9.845185222119664514e-01 1.149226463648794549e+00 1.283346066010762954e+00 8.928963352466557923e-01 8.281831071290477464e-01 1.071350008537815812e+00 8.912829310784051717e-01 9.511559539231302374e-01 9.063342182922169421e-01 6.399248369100729583e-01 1.241481057927381393e+00 38 | 8.570102343779609777e-01 1.834498833577380861e+00 1.209698311729748399e+00 7.576190239478562960e-01 1.165876369017955216e+00 1.144199324918322214e+00 7.299937632802778742e-01 7.641244378645123403e-01 9.781538194806742581e-01 1.104324203289442030e+00 1.358117542777007802e+00 9.855990182752709661e-01 1.061066593404123903e+00 5.332604970239736009e-01 1.155285590316366573e+00 1.015902209056210426e+00 1.259860194017548007e+00 1.059061081332568266e+00 1.395501738159880434e+00 1.423418220714990579e+00 1.161640217021882471e+00 39 | 7.176818297786345946e-01 1.052439564332374289e+00 7.229272244721576257e-01 1.024406145276408830e+00 1.227558059736371554e+00 1.169967635221884850e+00 5.769105074027808255e-01 1.050319365641600333e+00 1.286496284410974189e+00 1.050453619643372472e+00 1.118225604959171893e+00 6.214478168482178155e-01 9.944801505146551035e-01 3.269183210945053597e-01 9.013998959942067790e-01 1.150112858113002234e+00 6.694655705707507343e-01 1.246954075613451840e+00 9.023468872728990231e-01 1.295475936710809961e+00 6.921467185076273232e-01 40 | 7.502836851349361513e-01 7.983452417805469992e-01 1.215091292012536517e+00 1.835653674401756197e+00 1.279509756122526598e+00 7.385241109640185986e-01 8.670484786270269417e-01 9.144757224954244146e-01 1.114630531047025475e+00 1.572007191510357504e+00 1.150617319487425405e+00 1.052751956542987699e+00 8.740473096726021351e-01 8.120545089602531075e-01 6.644032891434132893e-01 9.580261931205891202e-01 1.427689997754968187e+00 1.277363271905642028e+00 7.233687458452521257e-01 6.070657794728804291e-01 1.564128421402319891e+00 41 | 1.105871962782156270e+00 6.978010339638118786e-01 9.674221705173762231e-01 7.992980994451478471e-01 1.021532128182113475e+00 1.019801184543851491e+00 9.220534132685055395e-01 1.043566356527062533e+00 1.287567541974937946e+00 1.264481553655280033e+00 1.329373913127142037e+00 1.100079819913285073e+00 8.053935895721686666e-01 7.476662571907838339e-01 6.156813097649163069e-01 9.965584213902061173e-01 1.026802350177890455e+00 1.079545292238308196e+00 6.521506705913928670e-01 7.980712099267592841e-01 1.490634896954825095e+00 42 | 6.558610774017489264e-01 1.196901332040382071e+00 1.024325283559971655e+00 8.185574778823901942e-01 1.021056663878898707e+00 7.794431551922608170e-01 1.138861629548047594e+00 1.136377627661149470e+00 1.171039900201601869e+00 1.486961111250399536e+00 1.238492549637604911e+00 9.722217241012397482e-01 1.020085350887809161e+00 1.137191302529771075e+00 9.361084269601051000e-01 7.966685541698262929e-01 9.880941193528389732e-01 8.459157872931856170e-01 5.787935823368793864e-01 8.087894406565366845e-01 8.419599285303832614e-01 43 | 7.839856513534835258e-01 1.023316758809185822e+00 6.757796606109417459e-01 1.192225339004272744e+00 7.915230127025311146e-01 1.019507823821445891e+00 8.541379557089341379e-01 8.005115778954615680e-01 9.378245947357479739e-01 8.602458524427458730e-01 9.669356602761868258e-01 1.034279098059429636e+00 1.302574334478593610e+00 8.904356044327446096e-01 1.106289769056714389e+00 9.869261602910309739e-01 6.597065251892771931e-01 1.107240255722759192e+00 8.304094631458465159e-01 1.192116745289995672e+00 9.971204104138495783e-01 44 | 8.478363521449051587e-01 5.570512309816482155e-01 9.363549533732394847e-01 1.250788320283784394e+00 8.109862262588750648e-01 7.780139360564420903e-01 1.516363374650954166e+00 1.379013558334986289e+00 1.229674803329505295e+00 1.345500093308844569e+00 6.136417694581618454e-01 6.577890184852728250e-01 1.308446307047478330e+00 5.127407633618492611e-01 1.190773213174567413e+00 1.236920479526089967e+00 8.078315844231453990e-01 8.684673822859477754e-01 6.919029589980619788e-01 7.616648830997685415e-01 1.072816276781317635e+00 45 | 8.668776303568843655e-01 1.553230098529889913e+00 1.265289161374790750e+00 1.198762087081932215e+00 1.070898133311458000e+00 1.209728474932064701e+00 1.035680303193641905e+00 9.179891385501318668e-01 1.069222265419243367e+00 1.073985758765028331e+00 8.639596674609253402e-01 7.222091979404766660e-01 7.990712823011809629e-01 6.764051538511465234e-01 1.071269247521704937e+00 9.217040414219949129e-01 1.520399003973360585e+00 9.100983790062732171e-01 1.078926177592370417e+00 7.383943370143938312e-01 1.646886829702270960e+00 46 | 9.923150153502835469e-01 1.184493933118382358e+00 1.652789368841879325e+00 1.242847427873235100e+00 1.011516785504591676e+00 1.263574779477444121e+00 6.753124909170215018e-01 1.204755421254434689e+00 8.588649649716323387e-01 8.669330905582971480e-01 1.028363225831586236e+00 9.315292371145101891e-01 8.535488197627829621e-01 6.256072138438928398e-01 7.932355238498726147e-01 9.535487148758138298e-01 1.622973944429293436e+00 9.134540343656366579e-01 1.224514889214012969e+00 6.354137221678110015e-01 7.762540668096907792e-01 47 | 7.230589507106933711e-01 1.277026250901497795e+00 1.513503837160561138e+00 1.126426767254227856e+00 8.004859023406746266e-01 9.046740797026672221e-01 9.615196142326475348e-01 1.208265912692958244e+00 1.055963352349073237e+00 8.991143140276055545e-01 5.695288457644539504e-01 8.590858483074651497e-01 1.641282972291612019e+00 1.449157078522349540e+00 1.037717281591012730e+00 7.451905593104888315e-01 1.289399583203775901e+00 7.172464378392684470e-01 1.122252113963312592e+00 1.312429161889987705e+00 6.641948723953871037e-01 48 | 9.637084370193107485e-01 1.134180374739714781e+00 1.036554273973831819e+00 9.530153362829714148e-01 7.412737823492842049e-01 1.394009085908962886e+00 1.159442369882137003e+00 1.252366254200594664e+00 1.503962629760697611e+00 1.142844507405416321e+00 1.003417838847836974e+00 9.376542509146940096e-01 9.139452774792010681e-01 9.645142546372335035e-01 1.072415175517828390e+00 9.197802020954866098e-01 1.349342879591728162e+00 8.389127001388916316e-01 6.698634280197234281e-01 1.206862577767291000e+00 1.419831699061545827e+00 49 | 7.260286375917365254e-01 1.313910755031346245e+00 1.103188165185211567e+00 1.056560907296362872e+00 9.775152053956147613e-01 1.064629944383124638e+00 1.009035194007099179e+00 1.093381367705181129e+00 1.117876604484312253e+00 6.726150899083340740e-01 7.676685432733183490e-01 8.645415512710018513e-01 1.033715842126458950e+00 6.314483958659602436e-01 9.397359855729034983e-01 8.187286932659605387e-01 9.725522408012184927e-01 5.424262934934276359e-01 8.265008774097774014e-01 9.536106573799859598e-01 1.142341200387090527e+00 50 | 1.011449092072265410e+00 1.336120405635380370e+00 1.189321626386056652e+00 9.354133174246485050e-01 9.628277406430292285e-01 1.135191044421384188e+00 1.079658095139637286e+00 9.567930990293979088e-01 1.056505211300807767e+00 1.045480856872441855e+00 1.408862622248806318e+00 1.271850849726252175e+00 1.382087273642014225e+00 9.685489892437664228e-01 9.119069891449047560e-01 1.146222283801436204e+00 1.044171302570792381e+00 1.172435959942738970e+00 9.403760653520415458e-01 6.369994216944198095e-01 1.028594119148399377e+00 51 | 1.036071725972169011e+00 1.065938995904720965e+00 1.202840339025157190e+00 9.585129613015412886e-01 8.203182757713767259e-01 8.963696353514144510e-01 1.599435905680951509e+00 1.498872802446576280e+00 1.180537162527130812e+00 1.014970234412529315e+00 8.989556960358452420e-01 9.984201626229155524e-01 1.303095402954122184e+00 9.379072847034133353e-01 1.171439464580263490e+00 9.336666808245639437e-01 9.935203786313814289e-01 7.771794988038135399e-01 7.507095850987325347e-01 7.925906415206925848e-01 9.316246609865223016e-01 52 | 8.430041525836674543e-01 7.929099033361914906e-01 1.044954841954371938e+00 1.367586378448960582e+00 9.716826917557686016e-01 9.325690318227088937e-01 1.310274642754069685e+00 7.964681128504436103e-01 9.973504991183782531e-01 1.337881912846085930e+00 6.100736863296729595e-01 8.595273137278930387e-01 8.800738801353030771e-01 9.912312375776201057e-01 1.167882391935864961e+00 7.695008168987584884e-01 8.317149001331770597e-01 9.019188617181455037e-01 6.897267234044637263e-01 7.361793295353203925e-01 1.160976905664158121e+00 53 | 8.272651572958839017e-01 9.754426284926515089e-01 6.854550366144045448e-01 1.235673403027537587e+00 1.052607459593947636e+00 9.790969845446177988e-01 1.152413418109243359e+00 1.375066373382359375e+00 1.210033033293935301e+00 7.953277955732889204e-01 1.418042756987145880e+00 9.247510030227885647e-01 9.762867085390846134e-01 8.700468135602226205e-01 9.041481056473560374e-01 5.021544727469293701e-01 8.270987255508696068e-01 8.576593209685760000e-01 5.692300308100237682e-01 7.168883664313280280e-01 9.702058776982348531e-01 54 | 7.995822638483340850e-01 1.504859142640812442e+00 8.420126168788013565e-01 1.326203751745398618e+00 1.488387052845736580e+00 1.414269220510405045e+00 9.552713804429872058e-01 1.396839471339985650e+00 9.433350605163773883e-01 9.688940374727450511e-01 1.280893992932857994e+00 1.289985210921438696e+00 9.999978860666017821e-01 1.054203913915473301e+00 1.376712417627461216e+00 8.077984202737283903e-01 7.844705742750840427e-01 4.160044699759773423e-01 8.553030681054355489e-01 9.362692876643312623e-01 1.074755433571857433e+00 55 | -------------------------------------------------------------------------------- /tests/data/CN.mm9.1000kb.cool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/open2c/coolpuppy/592673c099ddded729c1b0c1b408d7e4b538e4c8/tests/data/CN.mm9.1000kb.cool -------------------------------------------------------------------------------- /tests/data/CN.mm9.toy_expected.tsv: -------------------------------------------------------------------------------- 1 | region1 region2 dist n_valid count.sum balanced.sum balanced.avg 2 | foo foo 0 50 3 | foo foo 1 49 4 | foo foo 2 48 448255.0 2.3205076553434987 0.04834390948632289 5 | foo foo 3 47 271497.0 1.38339695992966 0.02943397787084383 6 | foo foo 4 46 179491.0 0.900655795691491 0.01957947381938024 7 | foo foo 5 45 135426.0 0.6826130105698165 0.015169178012662588 8 | foo foo 6 44 96841.0 0.48167647260294866 0.010947192559157925 9 | foo foo 7 43 74458.0 0.36747755422094075 0.008545989633045134 10 | foo foo 8 42 56431.0 0.2767897183400133 0.0065902313890479364 11 | foo foo 9 41 46579.0 0.23020444753273792 0.005614742622749705 12 | foo foo 10 40 42800.0 0.21407619204942857 0.005351904801235714 13 | foo foo 11 39 38893.0 0.1931769021342914 0.0049532539008792665 14 | foo foo 12 38 35915.0 0.1760485882134026 0.004632857584563227 15 | foo foo 13 37 31507.0 0.15432815796541483 0.0041710312963625625 16 | foo foo 14 36 28275.0 0.13916825128679033 0.003865784757966398 17 | foo foo 15 35 26582.0 0.13214461875460215 0.0037755605358457756 18 | foo foo 16 34 24080.0 0.1200420079045525 0.0035306472913103674 19 | foo foo 17 33 22554.0 0.1123809167677425 0.0034054823262952274 20 | foo foo 18 32 21069.0 0.10519693902501005 0.003287404344531564 21 | foo foo 19 31 19565.0 0.09730388315158268 0.003138834940373635 22 | foo foo 20 30 18830.0 0.09344118037915836 0.003114706012638612 23 | foo foo 21 29 18180.0 0.09181365603513099 0.003165988139142448 24 | foo foo 22 28 16817.0 0.0857312761411997 0.003061831290757132 25 | foo foo 23 27 15637.0 0.08088906104487427 0.0029958911498101583 26 | foo foo 24 26 13554.0 0.0696931607808895 0.0026805061838803654 27 | foo foo 25 25 12151.0 0.062133968853916574 0.002485358754156663 28 | foo foo 26 24 10641.0 0.053908741063492124 0.002246197544312172 29 | foo foo 27 23 9371.0 0.04780835937733471 0.002078624320753683 30 | foo foo 28 22 8684.0 0.04565538936132342 0.0020752449709692464 31 | foo foo 29 21 7883.0 0.04194264489363847 0.0019972688044589747 32 | foo foo 30 20 7602.0 0.04117335917285604 0.002058667958642802 33 | foo foo 31 19 6783.0 0.03642786791651601 0.0019172562061324217 34 | foo foo 32 18 6220.0 0.033609930607101324 0.0018672183670611847 35 | foo foo 33 17 5752.0 0.03126540105125592 0.0018391412383091717 36 | foo foo 34 16 5236.0 0.02870993254323146 0.0017943707839519663 37 | foo foo 35 15 4806.0 0.026732726358511393 0.0017821817572340928 38 | foo foo 36 14 4562.0 0.025516336044875902 0.0018225954317768502 39 | foo foo 37 13 4484.0 0.025173064987642168 0.001936389614434013 40 | foo foo 38 12 4322.0 0.024324300745100825 0.0020270250620917354 41 | foo foo 39 11 3797.0 0.02095540632794532 0.00190503693890412 42 | foo foo 40 10 3403.0 0.018630663941423948 0.0018630663941423947 43 | foo foo 41 9 3044.0 0.016810995031025552 0.001867888336780617 44 | foo foo 42 8 2716.0 0.015316241229781234 0.0019145301537226542 45 | foo foo 43 7 2461.0 0.014124488058201323 0.002017784008314475 46 | foo foo 44 6 2060.0 0.011782977088540664 0.0019638295147567774 47 | foo foo 45 5 1629.0 0.009356770724295723 0.0018713541448591446 48 | foo foo 46 4 1325.0 0.007777107004193509 0.0019442767510483773 49 | foo foo 47 3 950.0 0.005574745304582236 0.0018582484348607453 50 | foo foo 48 2 629.0 0.003669007156579109 0.0018345035782895544 51 | foo foo 49 1 326.0 0.0020415942196967394 0.0020415942196967394 52 | bar bar 0 49 53 | bar bar 1 48 54 | bar bar 2 47 450107.0 2.1180050802546933 0.04506393787775943 55 | bar bar 3 46 238644.0 1.1182026520831783 0.02430875330615605 56 | bar bar 4 45 151877.0 0.7065426657897472 0.01570094812866105 57 | bar bar 5 44 105862.0 0.4889639900117408 0.01111281795481229 58 | bar bar 6 43 84565.0 0.3886687958491317 0.00903880920579376 59 | bar bar 7 42 67656.0 0.305587801420597 0.007275900033823738 60 | bar bar 8 41 56605.0 0.2536802573536893 0.006187323350089984 61 | bar bar 9 40 49125.0 0.21940452543596367 0.005485113135899092 62 | bar bar 10 39 43256.0 0.19302073776471373 0.004949249686274711 63 | bar bar 11 38 38908.0 0.17213966992023477 0.0045299913136903885 64 | bar bar 12 37 33613.0 0.1494114335367291 0.00403814685234403 65 | bar bar 13 36 29008.0 0.1286862020151156 0.0035746167226421 66 | bar bar 14 35 28208.0 0.1257340707416353 0.0035924020211895802 67 | bar bar 15 34 26130.0 0.11682046178278417 0.0034358959347877698 68 | bar bar 16 33 24355.0 0.10848220502658447 0.0032873395462601354 69 | bar bar 17 32 21902.0 0.09720413992092795 0.0030376293725289986 70 | bar bar 18 31 19754.0 0.08921457365055102 0.00287788947259842 71 | bar bar 19 30 17506.0 0.0798108423392565 0.00266036141130855 72 | bar bar 20 29 16951.0 0.07831020324831016 0.002700351836148626 73 | bar bar 21 28 16124.0 0.07470713314986098 0.0026681118982093206 74 | bar bar 22 27 16237.0 0.07516147832181286 0.002783758456363439 75 | bar bar 23 26 15583.0 0.07144738725071081 0.0027479764327196466 76 | bar bar 24 25 14864.0 0.06801519019393452 0.0027206076077573808 77 | bar bar 25 24 14174.0 0.06516873511627985 0.002715363963178327 78 | bar bar 26 23 14169.0 0.06554949528961256 0.002849978056070111 79 | bar bar 27 22 13561.0 0.06221042530718225 0.0028277466048719207 80 | bar bar 28 21 12073.0 0.055813578961226296 0.0026577894743441094 81 | bar bar 29 20 11032.0 0.05118868034313225 0.0025594340171566127 82 | bar bar 30 19 10723.0 0.050269590871060296 0.0026457679405821207 83 | bar bar 31 18 10646.0 0.04998712073522266 0.0027770622630679254 84 | bar bar 32 17 10320.0 0.04943531274185869 0.002907959573050511 85 | bar bar 33 16 9664.0 0.04604888783607321 0.0028780554897545755 86 | bar bar 34 15 9227.0 0.04425307710295975 0.0029502051401973164 87 | bar bar 35 14 9111.0 0.04421548066666439 0.0031582486190474567 88 | bar bar 36 13 9923.0 0.04945120961837048 0.003803939201413114 89 | bar bar 37 12 9219.0 0.04674824569212995 0.0038956871410108294 90 | bar bar 38 11 8027.0 0.04077733321358686 0.0037070302921442602 91 | bar bar 39 10 6756.0 0.03230495094148628 0.0032304950941486276 92 | bar bar 40 9 5996.0 0.027699878189309274 0.003077764243256586 93 | bar bar 41 8 5280.0 0.023833680900535406 0.0029792101125669258 94 | bar bar 42 7 4560.0 0.019837282406156377 0.002833897486593768 95 | bar bar 43 6 3911.0 0.01627847374007839 0.0027130789566797314 96 | bar bar 44 5 3155.0 0.012966661266117605 0.002593332253223521 97 | bar bar 45 4 2335.0 0.008792759755829107 0.0021981899389572766 98 | bar bar 46 3 1518.0 0.005519380548429014 0.0018397935161430046 99 | bar bar 47 2 1142.0 0.003471630969823881 0.0017358154849119406 100 | bar bar 48 1 756.0 0.0019403909506671992 0.0019403909506671992 101 | bar bar 49 0 361.0 0.0 -------------------------------------------------------------------------------- /tests/data/CN.mm9.toy_regions.bed: -------------------------------------------------------------------------------- 1 | chr1 100000000 150000000 foo 2 | chr2 100000000 150000000 bar 3 | -------------------------------------------------------------------------------- /tests/data/toy_features.bed: -------------------------------------------------------------------------------- 1 | chr1 102000000 102500000 toy 0 + 2 | chr1 105000000 105500000 toy 0 - 3 | chr1 108000000 108500000 toy 0 + 4 | chr2 102000000 102500000 toy 0 + 5 | chr2 105000000 105500000 toy 0 - 6 | chr2 108000000 108500000 toy 0 - -------------------------------------------------------------------------------- /tests/loop_ref.np.txt: -------------------------------------------------------------------------------- 1 | # anchor: null 2 | # baselist: tests/CH12_loops_Rao.bed 3 | # bed2: null 4 | # bed2_ordered: true 5 | # bed_ordered: true 6 | # by_window: false 7 | # coolfile: tests/Scc1-control.10000.cool 8 | # coverage_norm: true 9 | # excl_chrs: chrY,chrM 10 | # expected: null 11 | # incl_chrs: all 12 | # local: false 13 | # logLevel: INFO 14 | # maxdist: null 15 | # maxshift: 1000000 16 | # maxsize: null 17 | # mindist: 0 18 | # minshift: 100000 19 | # minsize: null 20 | # n_proc: 2 21 | # nshifts: 10 22 | # outdir: tests 23 | # outname: testing_loop.txt 24 | # pad: 100 25 | # post_mortem: false 26 | # rescale: false 27 | # rescale_pad: 1.0 28 | # rescale_size: 99 29 | # save_all: false 30 | # seed: 0 31 | # subset: 0 32 | # unbalanced: true 33 | # weight_name: weight 34 | 8.714406011549307163e-01 8.646652864056548760e-01 8.649782817805575785e-01 7.863410252320972571e-01 8.922162070380377230e-01 8.198837809207940586e-01 9.454572186277252488e-01 1.028220325642554611e+00 8.403116473637437522e-01 1.184421697554219888e+00 1.200953497689089433e+00 1.306849196609102037e+00 1.159174421297344937e+00 9.807502234994865953e-01 8.679473146653826632e-01 8.126299488109605118e-01 1.044118962585557142e+00 8.770661499309425624e-01 8.592042556448286073e-01 9.002826068741008880e-01 8.952249786289482314e-01 35 | 7.842739410009516021e-01 8.047417884797375409e-01 8.335716235383019423e-01 8.985770722020848256e-01 7.213940803703607907e-01 9.343102928022863907e-01 8.448636094149810649e-01 9.379762863003408002e-01 8.487048728185542235e-01 1.085794714103603731e+00 1.205343740751551262e+00 1.163176495722232362e+00 9.030785153891509598e-01 1.000979068666090654e+00 1.066603847923784709e+00 8.271873578015092043e-01 9.878316037744995226e-01 9.780303760375801403e-01 1.059477587892182715e+00 7.186603765272550071e-01 6.026411479753426281e-01 36 | 7.860654925337874355e-01 7.950829191450533573e-01 8.253098250266027724e-01 9.019118129044028098e-01 9.673254166968359158e-01 8.584403866652531301e-01 8.524552590755065662e-01 9.164734599006149063e-01 9.781002840425132572e-01 1.205454248670569939e+00 1.104111967717997578e+00 1.061205328476123366e+00 1.160162041753055595e+00 1.046020638166856642e+00 1.267031693370818779e+00 9.149611274698992158e-01 9.404961023530202802e-01 8.507348573529242008e-01 9.456057585371810958e-01 8.445103934911827315e-01 1.015998448145277511e+00 37 | 9.287417635473091959e-01 8.289632404703396462e-01 9.057076081823021152e-01 8.958070097727761638e-01 8.905072379110247072e-01 9.004621606459171090e-01 1.015998765228532719e+00 9.584502812982591546e-01 1.065046157736160293e+00 9.109422645676023000e-01 1.048178063407149141e+00 1.129196403882069211e+00 1.237517868229938589e+00 8.813140597782698205e-01 1.130600272185784627e+00 8.972039657544831348e-01 9.225227898497608825e-01 1.116286526030171977e+00 1.007973297737348561e+00 1.096473983537601171e+00 8.117008090749502358e-01 38 | 9.035689798696101560e-01 9.937514186870196609e-01 8.635372556444728120e-01 9.025092886279032500e-01 9.431238537745916251e-01 7.589216972351306989e-01 9.491024518886912453e-01 1.024353174190552940e+00 1.145547614349333054e+00 9.917702450756017418e-01 1.212878568498266141e+00 1.159849149021555004e+00 9.908208487824546884e-01 8.225202280343107963e-01 1.045305642053871553e+00 8.344781862047832011e-01 8.364689438072255845e-01 1.079458628620106664e+00 1.079981781234372162e+00 6.785059065790934874e-01 7.061794729903473344e-01 39 | 9.200494370512916076e-01 8.573259321350724660e-01 8.543094097634350570e-01 7.725021060226349157e-01 9.652472291464999632e-01 9.094517419527029523e-01 1.005769386443031710e+00 9.360958496174159871e-01 1.007036926799312671e+00 9.740085687518846846e-01 1.209865953930576943e+00 9.948698863346262522e-01 9.750731648440791322e-01 8.785851089429682625e-01 8.385768686797271387e-01 9.108496533131131834e-01 1.177149759930057993e+00 1.259644571368060406e+00 1.102239841206833715e+00 7.742863333105941548e-01 7.899418180452774108e-01 40 | 8.786695774598051178e-01 9.129196215451962360e-01 8.369850987322379199e-01 9.591576054425177134e-01 1.064192755283529745e+00 9.541475616843186902e-01 9.569857580830671839e-01 1.007964334919756899e+00 1.111297029029270744e+00 1.099471279667276091e+00 1.081207817543283545e+00 9.839562585624762603e-01 9.423314336985061379e-01 1.180040915342630781e+00 9.122779570254645476e-01 8.327400156083990534e-01 1.090031611702485748e+00 8.523138406907397879e-01 8.771116084758253661e-01 8.547202511260807434e-01 9.520811334689486261e-01 41 | 7.647671638923977389e-01 7.596107960736274700e-01 9.003147766941840269e-01 9.002826067303192348e-01 1.092227357359617290e+00 9.919397881472177270e-01 9.667137331544619627e-01 1.084302755724023459e+00 1.101047801029085393e+00 1.080237458517937288e+00 1.267276790596917779e+00 1.089845962265119317e+00 1.092286261030648520e+00 9.883032185707215644e-01 9.332197752107159738e-01 1.062883589814549889e+00 1.191445339324094244e+00 8.845050787768936607e-01 8.441975124327166791e-01 8.477550396076004580e-01 1.147694971869265723e+00 42 | 9.126074440235639740e-01 9.017804466494686588e-01 9.919510930651725955e-01 1.022583642228149126e+00 1.006449545584482630e+00 9.169654234450999031e-01 9.938677737174357318e-01 1.108365268999582209e+00 1.040531433056249844e+00 1.073413367899928916e+00 1.280686305977759787e+00 1.304362190982472969e+00 1.048709597820425277e+00 1.075561279642537560e+00 1.024984236926899328e+00 1.042524101136024450e+00 9.443406131794392921e-01 1.107705981666887496e+00 1.016311875687988309e+00 1.107456040269047648e+00 1.040013847921104295e+00 43 | 9.391482050298820550e-01 9.512962712759921446e-01 9.990789845553031956e-01 9.818653996198987155e-01 1.072228110357897890e+00 1.010400450961943308e+00 1.104313132162569211e+00 1.155740371443234604e+00 1.405279183850243863e+00 1.176974085117917568e+00 1.485780040689645309e+00 1.244756865771383225e+00 1.066054052096659266e+00 1.206829406551194861e+00 1.056589016895680855e+00 9.787490993674151651e-01 9.376461140964620355e-01 1.146215038794035301e+00 9.903501409457916571e-01 1.244399529158985773e+00 1.137186004085720903e+00 44 | 9.993980997213030015e-01 1.103697391479485646e+00 1.204121639327969007e+00 1.194107931430277159e+00 1.175011417208074782e+00 1.099492642957040855e+00 1.140410686230391324e+00 1.409197844627724905e+00 1.376925933059801155e+00 1.466904797188270715e+00 1.798801683139743757e+00 1.550810973822245531e+00 1.346259331853870256e+00 1.441848736661848207e+00 1.105191272487210385e+00 1.149284857532860471e+00 1.054867861490244252e+00 1.082511643044816285e+00 1.097784463268574040e+00 1.183422775998598686e+00 9.969304728603617383e-01 45 | 9.994248457132581809e-01 9.993980995322533367e-01 1.044165825937678704e+00 1.201697708819009058e+00 1.170166624891133988e+00 1.057166100788849761e+00 1.095645636387767796e+00 1.288677644313228177e+00 1.393580631021418936e+00 1.320128813480814234e+00 1.413267730178419557e+00 1.470572926965343585e+00 1.052102066148839610e+00 1.161969958755983967e+00 1.124086308377463261e+00 1.071976819257051128e+00 1.073371235025481152e+00 1.052225783919609858e+00 9.107302446358734871e-01 8.808673172410638186e-01 1.118587691197868050e+00 46 | 1.001415068682653287e+00 9.994248457467439506e-01 9.993980997682423428e-01 1.128980146770696580e+00 1.027057833202760895e+00 1.143896480511869207e+00 1.235137158356150788e+00 1.188409090218180753e+00 1.201420737430253682e+00 1.255867555122972545e+00 1.482704401161213381e+00 1.228249396051020348e+00 1.128443973873824113e+00 9.317358494319605278e-01 1.115366731590039295e+00 1.028285947664006050e+00 1.031952317642704564e+00 1.190711227755209878e+00 9.946052814112958940e-01 9.410424540585157205e-01 9.364425564034031257e-01 47 | 1.001044818949243576e+00 1.001415068527840679e+00 9.994248458210343022e-01 9.993980996405092965e-01 9.985453245948816559e-01 1.028515250905916112e+00 1.055074853650401989e+00 9.829211427498008025e-01 1.123691539125560634e+00 1.058599154227350514e+00 1.375108928726360924e+00 1.056820775988642769e+00 1.057810789700454279e+00 9.928442425143066963e-01 9.869006851498713928e-01 1.016623475003039845e+00 1.035138332195279176e+00 9.164380914624723484e-01 7.906529186324354752e-01 8.182255006609734371e-01 7.790732783419083152e-01 48 | 9.989956939130614222e-01 1.001044818920795887e+00 1.001415068816630782e+00 9.994248457787887618e-01 9.993980996005280559e-01 9.967993507317142177e-01 1.021290425398829749e+00 1.085608434241723153e+00 1.180130996360210016e+00 1.110399590092933098e+00 1.277186722366979055e+00 1.199404007596067023e+00 9.069215093065683408e-01 9.854524491558508403e-01 1.078434032977316104e+00 9.107979651774045227e-01 9.609416698462405204e-01 9.949807428725042646e-01 1.022964491553311150e+00 9.914103821909512337e-01 7.793445467383028902e-01 49 | 9.990939600937914777e-01 9.989956938889452687e-01 1.001044819018593213e+00 1.001415068716277501e+00 9.994248457284128362e-01 9.993980996711860909e-01 1.024316386178200089e+00 1.015706242808171123e+00 1.181736234325095447e+00 1.089083497633797526e+00 1.235981206172702018e+00 1.081772222325689370e+00 9.153134900426811438e-01 8.642871488345749142e-01 8.764713494943319194e-01 1.015112351471877616e+00 9.470881897744619637e-01 9.194357147131007046e-01 8.767162668918992985e-01 9.688085120240593762e-01 7.768742496260419017e-01 50 | 9.981394120379845081e-01 9.990939601104459333e-01 9.989956939256043889e-01 1.001044819028589439e+00 1.001415068747613102e+00 9.994248457726546686e-01 9.993980996589444388e-01 9.492070281818988375e-01 9.961364565792334425e-01 1.110829978353898406e+00 1.238087305935363869e+00 1.105397869375293496e+00 1.006822966615558590e+00 9.208872072697817934e-01 8.490111539925682127e-01 8.521781094153667580e-01 9.044836573671859448e-01 1.096202231372403579e+00 9.391096617310362715e-01 8.049511387010811481e-01 9.946036804872151471e-01 51 | 9.992255266431468996e-01 9.981394118033050100e-01 9.990939603189394891e-01 9.989956939033509675e-01 1.001044819058144464e+00 1.001415068820526777e+00 9.994248457961684151e-01 9.993980996297131547e-01 1.035389397960632119e+00 1.032191076138588626e+00 1.273877440311841358e+00 1.042331274504495475e+00 1.005526956843137310e+00 9.663187461104058018e-01 9.199441583849492510e-01 8.763505181011042033e-01 9.155327142517919459e-01 9.152268729058652408e-01 8.981560072757153179e-01 8.752409896543004164e-01 9.059217036084185048e-01 52 | 1.002463765274784535e+00 9.992255266983450790e-01 9.981394121427026311e-01 9.990939603448589779e-01 9.989956939398687563e-01 1.001044819158475541e+00 1.001415068723038759e+00 9.994248457205917591e-01 9.993980996328915012e-01 1.080202066409234440e+00 1.136791563962964435e+00 1.052023544677290978e+00 1.063865109752851312e+00 9.713164472096547097e-01 8.285134077688863785e-01 7.991916926419401213e-01 9.053482657050048177e-01 7.600366454217212242e-01 8.343265216513223725e-01 8.452402593621448634e-01 1.015622009108652746e+00 53 | 1.002604452013244885e+00 1.002463765584061139e+00 9.992255267105690786e-01 9.981394119384398023e-01 9.990939603225770238e-01 9.989956939855618723e-01 1.001044819112297590e+00 1.001415068773125361e+00 9.994248457554449905e-01 9.993980995200918427e-01 1.167949047545402408e+00 8.778687135330873748e-01 9.419970186098921561e-01 9.581849090491252330e-01 8.734728482984346343e-01 8.183308295911099206e-01 9.111538981511038138e-01 8.523119517501295261e-01 8.670466874597891893e-01 8.390157375980752397e-01 9.092861039486496155e-01 54 | 1.001268375585372405e+00 1.002604451963738708e+00 1.002463765581952604e+00 9.992255265034670764e-01 9.981394119134502363e-01 9.990939602394244279e-01 9.989956937909811874e-01 1.001044819034950573e+00 1.001415068771318584e+00 9.994248456020130567e-01 9.993980997762863527e-01 8.827979566854030624e-01 8.900521225965923877e-01 8.646058427831838644e-01 7.718701484620813513e-01 9.394253287987793799e-01 9.437651266970991104e-01 8.324311541244696633e-01 7.591798501601348947e-01 8.973051237869591468e-01 8.267495880436622757e-01 55 | -------------------------------------------------------------------------------- /tests/test.bed: -------------------------------------------------------------------------------- 1 | chr1 1000 2000 2 | chr1 2000 22000 3 | chr2 1000 3000 4 | chr3 1000 2000 5 | -------------------------------------------------------------------------------- /tests/test.bedpe: -------------------------------------------------------------------------------- 1 | chr1 1000 1200 chr1 3000 3200 2 | chr1 20000 22000 chr1 50000 52000 3 | chr2 1000 1300 chr2 1400 1500 4 | chr3 100000 102000 chr3 200000 202000 5 | -------------------------------------------------------------------------------- /tests/test_coolpup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Fri Jul 5 13:24:55 2019 5 | 6 | @author: Ilya Flyamer 7 | """ 8 | 9 | from matplotlib.pyplot import ioff 10 | from coolpuppy.coolpup import PileUpper, CoordCreator, pileup 11 | from cooltools.lib import io, common 12 | import pandas as pd 13 | import numpy as np 14 | import cooler 15 | import bioframe as bf 16 | import os.path as op 17 | 18 | 19 | def test_bystrand_pileups_with_expected(request): 20 | """ 21 | Test the snipping on matrix: 22 | """ 23 | # Read cool file and create regions out of it: 24 | clr = cooler.Cooler(op.join(request.fspath.dirname, "data/CN.mm9.1000kb.cool")) 25 | regions = io.read_viewframe_from_file( 26 | op.join(request.fspath.dirname, "data/CN.mm9.toy_regions.bed"), 27 | verify_cooler=clr, 28 | ) 29 | exp = io.read_expected_from_file( 30 | op.join(request.fspath.dirname, "data/CN.mm9.toy_expected.tsv"), 31 | expected_value_cols=["balanced.avg"], 32 | verify_view=regions, 33 | verify_cooler=clr, 34 | ) 35 | 36 | features = bf.read_table( 37 | op.join(request.fspath.dirname, "data/toy_features.bed"), schema="bed" 38 | ) 39 | cc = CoordCreator( 40 | features, 41 | 1_000_000, 42 | features_format="bed", 43 | local=False, 44 | flank=2_000_000, 45 | mindist=0, 46 | ) 47 | # Test with ooe=True 48 | pu = PileUpper(clr, cc, expected=exp, view_df=regions, ooe=True) 49 | pup = pu.pileupsByStrandWithControl() 50 | assert np.all(pup.sort_values("orientation")["n"] == [1, 3, 1, 1, 6]) 51 | # Test with ooe=False 52 | pu = PileUpper(clr, cc, expected=exp, view_df=regions, ooe=False) 53 | pup = pu.pileupsByStrandWithControl() 54 | assert np.all(pup.sort_values("orientation")["n"] == [1, 3, 1, 1, 6]) 55 | # No regions provided without expected 56 | pu = PileUpper(clr, cc, expected=False, ooe=False) 57 | pup = pu.pileupsByStrandWithControl() 58 | assert np.all(pup.sort_values("orientation")["n"] == [1, 3, 1, 1, 6]) 59 | # Unbalanced 60 | pu = PileUpper( 61 | clr, cc, expected=False, ooe=False, clr_weight_name=None, coverage_norm=True 62 | ) 63 | pup = pu.pileupsByStrandWithControl() 64 | assert np.all(pup.sort_values("orientation")["n"] == [1, 3, 1, 1, 6]) 65 | # Test ignore_group_order 66 | pu = PileUpper( 67 | clr, cc, expected=False, ooe=False, control=False 68 | ) 69 | pup = pu.pileupsByStrandWithControl(ignore_group_order=True) 70 | assert not pup[pup["orientation"] == "+-"].empty 71 | assert pup[pup["orientation"] == "-+"].empty 72 | assert np.all(pup.sort_values("orientation")["n"] == [1, 4, 1, 6]) 73 | 74 | 75 | def test_bystrand_pileups_with_controls(request): 76 | """ 77 | Test the snipping on matrix: 78 | """ 79 | # Read cool file and create regions out of it: 80 | clr = cooler.Cooler(op.join(request.fspath.dirname, "data/CN.mm9.1000kb.cool")) 81 | regions = bf.read_table( 82 | op.join(request.fspath.dirname, "data/CN.mm9.toy_regions.bed"), schema="bed4" 83 | ) 84 | features = bf.read_table( 85 | op.join(request.fspath.dirname, "data/toy_features.bed"), schema="bed" 86 | ) 87 | cc = CoordCreator( 88 | features, 89 | 1_000_000, 90 | features_format="bed", 91 | local=False, 92 | flank=2_000_000, 93 | mindist=0, 94 | ) 95 | pu = PileUpper(clr, cc, expected=False, view_df=regions, control=True) 96 | pup = pu.pileupsByStrandWithControl() 97 | assert np.all(pup.sort_values("orientation")["n"] == [1, 3, 1, 1, 6]) 98 | 99 | 100 | def test_bystrand_bydistance_pileups_with_controls(request): 101 | """ 102 | Test the snipping on matrix: 103 | """ 104 | # Read cool file and create regions out of it: 105 | clr = cooler.Cooler(op.join(request.fspath.dirname, "data/CN.mm9.1000kb.cool")) 106 | regions = bf.read_table( 107 | op.join(request.fspath.dirname, "data/CN.mm9.toy_regions.bed"), schema="bed4" 108 | ) 109 | features = bf.read_table( 110 | op.join(request.fspath.dirname, "data/toy_features.bed"), schema="bed" 111 | ) 112 | 113 | pup = pileup( 114 | clr=clr, 115 | features=features, 116 | features_format="bed", 117 | view_df=regions, 118 | mindist=0, 119 | flank=2_000_000, 120 | nshifts=1, 121 | by_strand=True, 122 | by_distance=True, 123 | ) 124 | assert np.all( 125 | pup.sort_values(["orientation", "distance_band"])["n"] == [1, 2, 1, 1, 1, 6] 126 | ) 127 | 128 | distance_bins = np.append([0], 50000 * 2 ** np.arange(30)) 129 | pup = pileup( 130 | clr=clr, 131 | features=features, 132 | features_format="bed", 133 | view_df=regions, 134 | mindist=0, 135 | flank=2_000_000, 136 | nshifts=1, 137 | by_strand=True, 138 | by_distance=distance_bins, 139 | ) 140 | assert np.all( 141 | pup.sort_values(["orientation", "distance_band"])["n"] == [1, 2, 1, 1, 1, 6] 142 | ) 143 | def test_pileups_with_stripes(request): 144 | """ 145 | Test the snipping on matrix: 146 | """ 147 | # Read cool file and create regions out of it: 148 | clr = cooler.Cooler(op.join(request.fspath.dirname, "data/CN.mm9.1000kb.cool")) 149 | regions = bf.read_table( 150 | op.join(request.fspath.dirname, "data/CN.mm9.toy_regions.bed"), schema="bed4" 151 | ) 152 | features = bf.read_table( 153 | op.join(request.fspath.dirname, "data/toy_features.bed"), schema="bed" 154 | ) 155 | cc = CoordCreator( 156 | features, 157 | 1_000_000, 158 | features_format="bed", 159 | local=False, 160 | flank=2_000_000, 161 | mindist=0, 162 | ) 163 | #Generate pileup with stripes 164 | pu = PileUpper(clr, cc, expected=False, view_df=regions, control=False, 165 | store_stripes=True, clr_weight_name=None, ignore_diags=0) 166 | pup = pu.pileupsWithControl() 167 | assert np.all( 168 | pup["coordinates"][0][0] == ['chr1', '102000000', '102500000', 'chr1', '105000000', '105500000'] 169 | ) 170 | assert np.all( 171 | pup["vertical_stripe"][0][0] == np.array([22015, 11287, 10852, 11376, 9998]) 172 | ) 173 | --------------------------------------------------------------------------------