# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['ngsderive', 'ngsderive.commands', 'ngsderive.readers']

package_data = \
{'': ['*']}

install_requires = \
['colorlog>=4.0.2,<5.0.0',
 'pysam>=0.15.3,<0.16.0',
 'pytabix>=0.0.2,<0.0.3',
 'rstr>=2.2.6,<3.0.0']

entry_points = \
{'console_scripts': ['ngsderive = ngsderive.__main__:run']}

setup_kwargs = {
    'name': 'ngsderive',
    'version': '1.0.2',
    'description': 'Forensic analysis tool useful in backwards computing information from next-generation sequencing data.',
    'long_description': '# ngsderive\n\n[![PyPI Version](https://img.shields.io/pypi/v/ngsderive.svg)](https://pypi.python.org/pypi/ngsderive/)\n[![PyPI Python Versions](https://img.shields.io/pypi/pyversions/ngsderive.svg)](https://pypi.python.org/pypi/ngsderive/)\n[![PyPI Project Status](https://img.shields.io/pypi/status/ngsderive.svg)](https://pypi.python.org/pypi/ngsderive/)\n\n\n[![CI\nstatus](https://github.com/claymcleod/ngsderive/workflows/CI/badge.svg)](https://github.com/claymcleod/ngsderive/actions)\n\n`ngsderive` is a forensic analysis tool useful in backwards computing information \nfrom next-generation sequencing data. Notably, results are provided as a \'best guess\' — the tool does \nnot claim 100% accuracy and results should be considered with that understanding.\n\nNote that this utility only implements commands which were not available at the \ntime of writing in common NGS utilities (e.g. [Picard](https://broadinstitute.github.io/picard/)).\n\n## Getting Started\n\nThese instructions will get you a copy of the project up and running on your\nlocal machine for development and testing purposes. See deployment for notes on\nhow to deploy the project on a live system.\n\n### Installing\n\nTo get started with `ngsderive`, you can install it using pip:\n\n```bash\npip install git+https://github.com/claymcleod/ngsderive.git\n```\n\n### Development\n\nTo get started on a development version of the code, just run the following:\n\n```bash\nconda create -n ngsderive-dev python=3.7 poetry -y\nconda activate ngsderive-dev\ngit clone git@github.com:claymcleod/ngsderive.git\ncd ngsderive\npoetry install\n```\n## Usage\n\n### Illumina machine type\n\nThe `instrument` subcommand will attempt to backward compute the machine that\ngenerated a NGS file using (1) the instrument id(s) and (2) the flowcell id(s). \n\n### Limitations\n\n* This command may not comprehensively detect the correct machines as there is\n  no published catalog of Illumina serial numbers. As we encounter more serial\n  numbers in practice, we update this code.\n\n### Read length calculation\n\nThe `readlen` subcommand can be used to compute the read length used during\nsequencing can be estimated (or reported as inconclusive). At the time of\nwriting, the algorithm used is roughly:\n\n1. Compute distribution of read lengths for the first `--n-samples` reads in a\n   file.\n2. Assuming read length in the file can only decrease from the actual read\n   length (from adapter trimming or similar), the putative maximum read length\n   is considered to be the highest detected read length.\n3. If the percentage of reads that are evidence for the putative maximum read\n   length makes up at least `--majority-vote-cutoff`% of the reads, the putative\n   read length is considered to be confirmed. If not, the consensus read length\n   will be return as -1 (could not determine).\n   1. For example, if 100bp is the maximum read length detected and 85% percent\n      of the reads support that claim, then we considered 100bp as the consensus\n      read length. If only 30% of the reads indicated 100bp, the tool cannot\n      report a consensus).\n\n### Strandedness inference\n\nThe `strandedness` subcommand can be used to determine strandedness of RNA-Seq\nsamples. Note that due to the need to (1) to examine the alignment status of a\nread [not included in FASTQ] and (2) fetch regions using random access [not\navailable with SAM files], only BAM files are currently supported for this\nsubcommand.\n\nStrandedness can estimated by observing the following characteristics of a\nparticular read:\n\n* Whether the read is read 1 or read 2 ("read ordinal").\n* Whether the read was aligned to the + or - strand ("read strand")\n* Given a gene model, whether a feature of interest (usually a gene) falls on\n  the + or - strand ("gene strand").\n\nA shorthand notation for the state of a read can be achieved by simply\nconcatenating the three characteristics above (e.g., `1+-` means that a read 1\nwas aligned to the positive strand and a gene was observed at the same location\non the negative strand).\n\nGiven the notation above, the following lookup table can be used to see whether\na read is evidence for forward-strandedness or reverse-strandedness:\n\n| Patterns                   | Evidence for strandedness type |\n| -------------------------- | ------------------------------ |\n| `1++`, `1--`, `2+-`, `2-+` | Forward                        |\n| `2++`, `2--`, `1+-`, `1-+` | Reverse                        |\n\nBy default, the strandedness check is designed to work with the\n[GENCODE][gencode-website] geneset. Either a GTF or GFF file can be used as the\ngene model — you can use the following one liner to prepare the latest geneset\nfor hg38.\n\n```bash\n\n# hg38\ncurl ftp://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_32/gencode.v32.annotation.gff3.gz | gunzip -c | sort -k1,1 -k4,4n -k5,5n | bgzip > gencode.v32.annotation.gff3.gz\ntabix -p gff gencode.v32.annotation.gff3.gz\n```\n\nIf you would like to use the script on hg19, it takes a little more finesse (given the different formats of the attribute column between versions):\n\n```bash\n# hg19\ncurl ftp://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_32/GRCh37_mapping/gencode.v32lift37.annotation.gtf.gz | gunzip -c | sort -k1,1 -k4,4n -k5,5n | python <(cat \n<<END    \nimport re \nimport sys\n\nfor line in [l.strip() for l in sys.stdin]:\n  if line.startswith("#"):\n    print(line)                     \n  else:                       \n    columns = line.split(\'\\t\')\n    if len(columns) != 9:                                                    \n      raise RuntimeError("Unexpected column number: {}".format(len(columns)))\n    \n    print(\'\\t\'.join(columns[0:8]), end="\\t")\n    \n    attrs_post = []\n    for attr in columns[8].split(";"):                        \n      groups = re.match(r"\\s?(\\S+) (\\S+)\\s?", attr)\n      if groups:             \n        key = groups.group(1)                    \n        value = groups.group(2).replace("\\"", "").replace(" ", ",")\n        attrs_post.append(key + "=" + value)\n\n    print(";".join(attrs_post))\nEND\n) | sed \'s/^chrM/chrMT/g\' | sed \'s/^chr//g\' | bgzip > gencode.v32lift37.annotation.gtf.gz\ntabix -p gff gencode.v32lift37.annotation.gtf.gz\n```\n\nAt the time of writing, the algorithm works roughly like this:\n\n1. The gene model is read in and only `gene` features are retained.\n2. For `--n-genes` times, a randomly sampled gene is selected from the gene\n   model. The gene must pass a quality check. Of particular interest,\n   1. The gene must not be an overlapping feature on the opposite strand which\n      would present ambiguous results.\n   2. *Optionally*, the gene must be a protein coding gene.\n   3. *Optionally*, the gene must have at least `--minimum-reads-per-gene`\n      minimum reads per gene.\n3. All of the reads from that region of the genome are extracted and put through\n   several quality filters including but not limited to:\n   1. The read must not be marked as QC-failed.\n   2. The read must not be marked as a duplicate.\n   3. The read must not be marked as secondary.\n   4. The read must not be unmapped.\n   5. *Optionally*, the read have a minimum MAPQ score.\n4. For all reads that pass the above filters, compute the evidence and tally\n   results.\n\nThis lookup table is used for the classification of strandedness based on the evidence:\n\n| Lookup                            | Value              |\n| --------------------------------- | ------------------ |\n| 40% <= `forward_reads_pct` <= 60% | `Unstranded`       |\n| 80% <= `forward_reads_pct`        | `Stranded-Forward` |\n| 80% <= `reverse_reads_pct`        | `Stranded-Reverse` |\n| Else                              | `Inconclusive`     |\n\nThe tool will repeat the strandedness test at most `--max-tries` times to try to find a\nnon-`Inconclusive`prediction.\n\n### Differences from popular methods\n\nThe most popular strandedness inference tool that the author is aware of is\nRSeQC\'s\n[infer_experiment.py](http://rseqc.sourceforge.net/#infer-experiment-py). The\nmain difference is that RSeQC starts at the beginning of the BAM file and takes\nthe first `n` reads that match its criteria. If the BAM is coordinate sorted,\nthis would mean its not uncommon to have all of the evidence at the beginning of\n`chr1`. Anecdotally, this method differs in that it is slightly slower than\n`infer_experiment.py` but is expected to be more robust to biases caused by\nwhich reads are sampled.\n\n\n### Limitations\n\n* Does not yet work with single-end data (simply because the author doesn\'t have\n  any on hand). The tool will throw an error if any unpaired reads are\n  discovered (let us know in the issues if you need this supported).\n* Though hundreds of Unstranded and Stranded-Reverse data has been tested and\n  verified, Stranded-Forward data has not been tested to work with this tool\n  (simply because the author doesn\'t have on hand). We do not anticipate any\n  issues since Stranded-Reverse is working well.\n\n## Running the tests\n\n```bash\n> py.test\n```\n\n## Contributing\n\nPlease read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of\nconduct, and the process for submitting pull requests to us.\n\n\n## Versioning\n\nWe use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/your/project/tags).\n\n## License\n\nThis project is licensed as follows:\n* All code related to the `instrument` subcommand is licensed under the [AGPL\n  v2.0][agpl-v2]. This is not due any strict requirement, but out of deference\n  to some [code][10x-inspiration] I drew inspiration from (and copied patterns\n  from), the decision was made to license this code consistently.\n* The rest of the project is licensed under the MIT License - see the\n  [LICENSE.md](LICENSE.md) file for details.\n\n[10x-inspiration]:\nhttps://github.com/10XGenomics/supernova/blob/master/tenkit/lib/python/tenkit/illumina_instrument.py\n[agpl-v2]: http://www.affero.org/agpl2.html\n[gencode-website]:\nhttps://www.gencodegenes.org/\n',
    'author': 'Clay McLeod',
    'author_email': 'Clay.McLeod@STJUDE.org',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://github.com/claymcleod/ngsderive',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'entry_points': entry_points,
    'python_requires': '>=3.7,<4.0',
}


setup(**setup_kwargs)
