From e49833e496e5a96993749ccb835d5a8987e8c74d Mon Sep 17 00:00:00 2001 From: James Li Date: Fri, 10 May 2024 16:26:54 -0400 Subject: [PATCH 01/79] change cleavage profile intersect_policy to any --- src/finaletoolkit/frag/cleavage_profile.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/finaletoolkit/frag/cleavage_profile.py b/src/finaletoolkit/frag/cleavage_profile.py index b73ee34b..ce32acbf 100644 --- a/src/finaletoolkit/frag/cleavage_profile.py +++ b/src/finaletoolkit/frag/cleavage_profile.py @@ -55,7 +55,8 @@ def cleavage_profile( start=start, stop=stop, fraction_low=fraction_low, - fraction_high=fraction_high + fraction_high=fraction_high, + intersect_policy="any" ) positions = np.arange(start, stop) From 718657d57d4da845f97ff6871e355cf632e5c885 Mon Sep 17 00:00:00 2001 From: James Li Date: Fri, 10 May 2024 16:27:06 -0400 Subject: [PATCH 02/79] fix typo in docstring --- src/finaletoolkit/utils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/finaletoolkit/utils/utils.py b/src/finaletoolkit/utils/utils.py index 1153153b..4681394b 100644 --- a/src/finaletoolkit/utils/utils.py +++ b/src/finaletoolkit/utils/utils.py @@ -335,7 +335,7 @@ def frag_array( given interval. Default is "midpoint". Policies include: - midpoint: the average of end coordinates of a fragment lies in the interval. - - any: any part of the fragment is in the interval.v + - any: any part of the fragment is in the interval. verbose : bool, optional Returns From facc6b4cc193b560f35e79421e6a88a48a44e463 Mon Sep 17 00:00:00 2001 From: James Li Date: Mon, 13 May 2024 14:50:09 -0400 Subject: [PATCH 03/79] mask for zeros when calculating proportions to avoid errors --- src/finaletoolkit/frag/cleavage_profile.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/finaletoolkit/frag/cleavage_profile.py b/src/finaletoolkit/frag/cleavage_profile.py index ce32acbf..cb5fa0a6 100644 --- a/src/finaletoolkit/frag/cleavage_profile.py +++ b/src/finaletoolkit/frag/cleavage_profile.py @@ -80,7 +80,11 @@ def cleavage_profile( ), np.logical_not(frags['strand'][:, np.newaxis]) ) ends = np.sum(np.logical_or(forward_ends, reverse_ends), axis=0) - proportions = ends/depth*100 + + proportions = np.zeros_like(depth, dtype=np.float64) + non_zero_mask = depth != 0 + proportions[non_zero_mask] = ends[non_zero_mask] / depth[non_zero_mask] * 100 + results = np.zeros_like(proportions, dtype=[ ('contig', 'U16'), From ff727c4805ef5a7a77000b1ea1d9c34ddb6b479d Mon Sep 17 00:00:00 2001 From: James Li Date: Mon, 13 May 2024 16:10:21 -0400 Subject: [PATCH 04/79] remove _get_contigs and add _parse_chrom_sizes --- src/finaletoolkit/frag/coverage.py | 2 +- src/finaletoolkit/utils/utils.py | 39 ++++++++---------------------- 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/src/finaletoolkit/frag/coverage.py b/src/finaletoolkit/frag/coverage.py index 1b85ff52..a88a1507 100644 --- a/src/finaletoolkit/frag/coverage.py +++ b/src/finaletoolkit/frag/coverage.py @@ -10,7 +10,7 @@ from tqdm import tqdm from finaletoolkit.utils.utils import ( - _not_read1_or_low_quality, _get_contigs, _get_intervals, frag_generator + _get_intervals, frag_generator ) diff --git a/src/finaletoolkit/utils/utils.py b/src/finaletoolkit/utils/utils.py index 4681394b..1fb79fe8 100644 --- a/src/finaletoolkit/utils/utils.py +++ b/src/finaletoolkit/utils/utils.py @@ -2,7 +2,7 @@ import time import gzip import tempfile as tf -from typing import Union, TextIO, Tuple, List, Generator +from typing import Union, TextIO, Tuple, List, Generator, Iterable from sys import stderr, stdout from pathlib import Path @@ -13,36 +13,17 @@ from tqdm import tqdm -def _get_contigs( - input_file: Union[str, pysam.AlignmentFile], - verbose: bool=False - ) -> list: +def _parse_chrom_sizes( + chrom_sizes_file: Union[str, Path]) -> List[Tuple[str][int]]: """ - Retrieves contigs from input_file and returns lists of contig names - and lengths + Reads from a chrom.size """ - - input_is_file = False - try: - # handling input types - if (type(input_file) == pysam.AlignmentFile): - sam_file = input_file - elif input_file.endswith('bam'): - input_is_file = True - if (verbose): - stderr.write(f'Opening {input_file}\n') - sam_file = pysam.AlignmentFile(input_file) - else: - raise ValueError( - 'Invalid input_file type. Only BAM or SAM files are allowed.' - ) - contigs = sam_file.references - lengths = sam_file.lengths - finally: - if input_is_file: - sam_file.close() - - return zip(contigs, lengths) + chrom_sizes = [] + with open(chrom_sizes_file, 'r') as file: + for line in file: + chrom, size = line.strip().split('\t') + chrom_sizes.append((chrom, int(size))) + return chrom_sizes def frag_bam_to_bed(input_file: Union[str, pysam.AlignmentFile], From 5044c82fecbf9fede743016367a30c09ecea58b5 Mon Sep 17 00:00:00 2001 From: James Li Date: Mon, 13 May 2024 16:12:54 -0400 Subject: [PATCH 05/79] fix coverage verbose log --- src/finaletoolkit/frag/coverage.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/finaletoolkit/frag/coverage.py b/src/finaletoolkit/frag/coverage.py index a88a1507..99f17dac 100644 --- a/src/finaletoolkit/frag/coverage.py +++ b/src/finaletoolkit/frag/coverage.py @@ -54,15 +54,15 @@ def single_coverage( start_time = time.time() tqdm.write( f""" -input_file: -contig: {contig} -start: {start} -stop: {stop} -name: {name} -intersect_policy: {intersect_policy} -quality_threshold: {quality_threshold} -verbose: {verbose} -""" + input_file: {input_file} + contig: {contig} + start: {start} + stop: {stop} + name: {name} + intersect_policy: {intersect_policy} + quality_threshold: {quality_threshold} + verbose: {verbose} + """ ) # initializing variable for coverage tuple outside of with statement From 1c092f9746bbbcdaaf0562240336b8df6645a612 Mon Sep 17 00:00:00 2001 From: James Li Date: Mon, 13 May 2024 16:17:56 -0400 Subject: [PATCH 06/79] add numerous util functions related to merging overlapping bins --- src/finaletoolkit/utils/utils.py | 77 ++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 4 deletions(-) diff --git a/src/finaletoolkit/utils/utils.py b/src/finaletoolkit/utils/utils.py index 1fb79fe8..0a1726e9 100644 --- a/src/finaletoolkit/utils/utils.py +++ b/src/finaletoolkit/utils/utils.py @@ -13,19 +13,88 @@ from tqdm import tqdm -def _parse_chrom_sizes( +def chrom_sizes_to_list( chrom_sizes_file: Union[str, Path]) -> List[Tuple[str][int]]: """ - Reads from a chrom.size + Reads chromosome names and sizes from a CHROMSIZE file into a list. """ chrom_sizes = [] with open(chrom_sizes_file, 'r') as file: for line in file: - chrom, size = line.strip().split('\t') - chrom_sizes.append((chrom, int(size))) + if line != '\n': + chrom, size = line.strip().split('\t') + chrom_sizes.append((chrom, int(size))) return chrom_sizes +def _merge_overlapping_intervals(intervals): + intervals.sort(key=lambda x: x[0]) + merged = [] + for interval in intervals: + if not merged or interval[0] > merged[-1][1]: + merged.append(interval) + else: + merged[-1] = (merged[-1][0], max(merged[-1][1], interval[1])) + return merged + +def _reduce_overlaps_in_file(interval_file): + intervals_dict = {} + with open(interval_file, 'r') as file: + for line in file: + chrom, start, end = line.strip().split('\t')[:3] + start, end = int(start), int(end) + if chrom not in intervals_dict: + intervals_dict[chrom] = [] + intervals_dict[chrom].append((start, end)) + + reduced_intervals = {} + for chrom, intervals in intervals_dict.items(): + reduced_intervals[chrom] = _merge_overlapping_intervals(intervals) + return reduced_intervals + +def _convert_to_list(reduced_intervals): + converted_intervals = {} + for chrom, intervals in reduced_intervals.items(): + converted_intervals[chrom] = [[chrom, start, end] for start, end in intervals] + return converted_intervals + +def _merge_all_intervals(converted_intervals): + all_intervals = [] + for intervals in converted_intervals.values(): + all_intervals.extend(intervals) + return all_intervals + +def get_contig_lengths( + input_file: Union[str, pysam.AlignmentFile], + verbose: bool +) -> List[Tuple[str, int]]: + + input_is_file = False + sam_file = None + + try: + if isinstance(input_file, pysam.AlignmentFile): + sam_file = input_file + elif isinstance(input_file, str) and input_file.endswith(('bam', 'sam')): + input_is_file = True + if verbose: + stderr.write(f'Opening {input_file}\n') + sam_file = pysam.AlignmentFile(input_file) + else: + raise ValueError('Invalid input_file type. Only BAM or SAM files are allowed.') + + contigs = sam_file.references + lengths = sam_file.lengths + + contig_lengths = list(zip(contigs, lengths)) + + finally: + if input_is_file and sam_file is not None: + sam_file.close() + + return contig_lengths + + def frag_bam_to_bed(input_file: Union[str, pysam.AlignmentFile], output_file: str, contig: str=None, From 000c2be7684e3d402a829e43bebd291618ca8f20 Mon Sep 17 00:00:00 2001 From: James Li Date: Mon, 13 May 2024 16:30:31 -0400 Subject: [PATCH 07/79] Changed _cli_cleavage_profile - simplify internal calculations with helper functions - add option for chrom_sizes file to allow compatability with frag.gz files. --- src/finaletoolkit/cli/main_cli.py | 8 ++++ src/finaletoolkit/frag/cleavage_profile.py | 56 ++++++---------------- 2 files changed, 23 insertions(+), 41 deletions(-) diff --git a/src/finaletoolkit/cli/main_cli.py b/src/finaletoolkit/cli/main_cli.py index fd6b4111..c8a5d942 100644 --- a/src/finaletoolkit/cli/main_cli.py +++ b/src/finaletoolkit/cli/main_cli.py @@ -846,6 +846,14 @@ def main_cli_parser(): 'writes in gzip compressed bed file if ".bed.gz" or ".bedGraph.gz" ' 'suffixes used. Default is "-".', ) + parser_command13.add_argument( + '-c', + '--chrom-sizes', + default=None, + help='Tab-delimited file with two columns, one with names of ' + 'chromosomes or contigs, and the other with the size of ' + 'chromosomes.' + ) parser_command13.add_argument( '-lo', '--fraction_low', diff --git a/src/finaletoolkit/frag/cleavage_profile.py b/src/finaletoolkit/frag/cleavage_profile.py index cb5fa0a6..e32c8ddb 100644 --- a/src/finaletoolkit/frag/cleavage_profile.py +++ b/src/finaletoolkit/frag/cleavage_profile.py @@ -9,6 +9,7 @@ from __future__ import annotations from typing import Union +from pathlib import Path from sys import stderr, stdout, stdin from multiprocessing import Pool import gzip @@ -19,7 +20,10 @@ from pybedtools import BedTool import pysam -from finaletoolkit.utils.utils import frag_array, overlaps +from finaletoolkit.utils.utils import ( + frag_array, overlaps, chrom_sizes_to_list, _reduce_overlaps_in_file, + _convert_to_list, _merge_all_intervals + ) def cleavage_profile( @@ -110,6 +114,7 @@ def _cli_cleavage_profile( fraction_high: int=10000000, quality_threshold: int=30, output_file: str='-', + chrom_sizes: Union[str, Path]=None, workers: int=1, verbose: Union[bool, int]=0 ): @@ -151,8 +156,11 @@ def _cli_cleavage_profile( or input_file.endswith('.frag') or input_file.endswith('.frag.gz') ): - with pysam.TabixFile(input_file, 'r') as tbx: - raise NotImplementedError('tabix files not yet supported!') + if chrom_sizes is None: + raise ValueError( + '--chrom_sizes must be specified for BED/Fragment files' + ) + header = chrom_sizes_to_list(chrom_sizes) else: raise ValueError("Not a supported file type.") @@ -161,44 +169,10 @@ def _cli_cleavage_profile( # reading intervals from bed and removing overlaps # NOTE: assumes that bed file is sorted. - contigs = [] - starts = [] - stops = [] - try: - if interval_file == '-': - bed = stdin - else: - bed = open(interval_file) - - # for overlap checking - prev_contig = None - prev_start = 0 - prev_stop = 0 - for line in bed: - contents = line.split() - contig = contents[0].strip() - start = int(contents[1]) - stop = int(contents[2]) - - # cut off part of previous interval if overlap - if contig == prev_contig and start < prev_stop: - prev_stop = start - - if prev_contig is not None: - contigs.append(prev_contig) - starts.append(prev_start) - stops.append(prev_stop) - - prev_contig = contig - prev_start = start - prev_stop = stop - # appending last interval - contigs.append(prev_contig) - starts.append(prev_start) - stops.append(prev_stop) - finally: - if interval_file != '-': - bed.close() + reduced_intervals = _reduce_overlaps_in_file(interval_file) + converted_intervals = _convert_to_list(reduced_intervals) + all_intervals = _merge_all_intervals(converted_intervals) + contigs, starts, stops = zip(*all_intervals) count = len(contigs) From 4376521cdd0889d92b553dde4cbb5402015daf0c Mon Sep 17 00:00:00 2001 From: James Li Date: Wed, 15 May 2024 02:24:17 -0400 Subject: [PATCH 08/79] update cleavage_profile docstring --- src/finaletoolkit/frag/cleavage_profile.py | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/finaletoolkit/frag/cleavage_profile.py b/src/finaletoolkit/frag/cleavage_profile.py index e32c8ddb..a02eaac7 100644 --- a/src/finaletoolkit/frag/cleavage_profile.py +++ b/src/finaletoolkit/frag/cleavage_profile.py @@ -36,6 +36,32 @@ def cleavage_profile( quality_threshold: int=30, verbose: Union[bool, int]=0 ) -> np.ndarray: + """ + Cleavage profile calculated over a single interval. + + Parameters + --------- + input_file: str + SAM, BAM, CRAM, or FRAG file with fragment information. + contig: str + Chromosome or contig + start: int + 0-based start coordinate + stop: int + 1-based end coordinate + fraction_low: int + Minimum fragment size to include + fraction_high: int + Maximum fragment size to include + quality_threshold: int + Minimum MAPQ + verbose: bool or in + + Return + ------ + cleavage_proportions: NDArray + Array of cleavage proportions over given interval. + """ if (verbose): start_time = time.time() stderr.write( From e8ad5383211602982773dad7c969e561e3613547 Mon Sep 17 00:00:00 2001 From: James Li Date: Wed, 15 May 2024 02:32:58 -0400 Subject: [PATCH 09/79] added chrom_sizes_to_dict --- src/finaletoolkit/utils/utils.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/finaletoolkit/utils/utils.py b/src/finaletoolkit/utils/utils.py index 0a1726e9..4ed0e21a 100644 --- a/src/finaletoolkit/utils/utils.py +++ b/src/finaletoolkit/utils/utils.py @@ -27,6 +27,20 @@ def chrom_sizes_to_list( return chrom_sizes +def chrom_sizes_to_dict( + chrom_sizes_file: Union[str, Path]) -> List[Tuple[str][int]]: + """ + Reads chromosome names and sizes from a CHROMSIZE file into a list. + """ + chrom_sizes = {} + with open(chrom_sizes_file, 'r') as file: + for line in file: + if line != '\n': + chrom, size = line.strip().split('\t') + chrom_sizes[chrom] = size + return chrom_sizes + + def _merge_overlapping_intervals(intervals): intervals.sort(key=lambda x: x[0]) merged = [] From 4ffc98ae1d1b07369ae0fdf4413bb682808b6321 Mon Sep 17 00:00:00 2001 From: James Li Date: Wed, 15 May 2024 02:41:50 -0400 Subject: [PATCH 10/79] left and right option added to cleavage_profile --- src/finaletoolkit/frag/cleavage_profile.py | 32 +++++++++++++++------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/finaletoolkit/frag/cleavage_profile.py b/src/finaletoolkit/frag/cleavage_profile.py index a02eaac7..52f93136 100644 --- a/src/finaletoolkit/frag/cleavage_profile.py +++ b/src/finaletoolkit/frag/cleavage_profile.py @@ -28,9 +28,12 @@ def cleavage_profile( input_file: str, + chrom_size: int, contig: str, start: int, stop: int, + left: int=0, + right: int=0, fraction_low: int=1, fraction_high: int=10000000, quality_threshold: int=30, @@ -43,12 +46,19 @@ def cleavage_profile( --------- input_file: str SAM, BAM, CRAM, or FRAG file with fragment information. + chrom_size: int + length of contig. contig: str Chromosome or contig start: int 0-based start coordinate stop: int 1-based end coordinate + left: int + Amount to subtract from start coordinate. Useful if only given + coordinates of CpG. + right: int + Amount to add to stop coordinate. fraction_low: int Minimum fragment size to include fraction_high: int @@ -82,8 +92,8 @@ def cleavage_profile( input_file=input_file, contig=contig, quality_threshold=quality_threshold, - start=start, - stop=stop, + start=max(start-left, 0), + stop=min(stop+right, chrom_size), fraction_low=fraction_low, fraction_high=fraction_high, intersect_policy="any" @@ -134,13 +144,15 @@ def _cleavage_profile_star(args): def _cli_cleavage_profile( - input_file: str, - interval_file: str, + input_file: Union[str, Path], + interval_file: Union[str, Path], + chrom_sizes: Union[str, Path], + left: int=0, + right: int=0, fraction_low: int=1, fraction_high: int=10000000, quality_threshold: int=30, output_file: str='-', - chrom_sizes: Union[str, Path]=None, workers: int=1, verbose: Union[bool, int]=0 ): @@ -168,6 +180,11 @@ def _cli_cleavage_profile( if (input_file == '-' and interval_file == '-'): raise ValueError('input_file and site_bed cannot both read from stdin') + if chrom_sizes is None: + raise ValueError( + '--chrom_sizes must be specified' + ) + # get header from input_file if (input_file.endswith('.sam') or input_file.endswith('.bam') @@ -176,16 +193,11 @@ def _cli_cleavage_profile( references = bam.references lengths = bam.lengths header = list(zip(references, lengths)) - # TODO: get a header when reading tabix elif (input_file.endswith('.bed') or input_file.endswith('.bed.gz') or input_file.endswith('.frag') or input_file.endswith('.frag.gz') ): - if chrom_sizes is None: - raise ValueError( - '--chrom_sizes must be specified for BED/Fragment files' - ) header = chrom_sizes_to_list(chrom_sizes) else: raise ValueError("Not a supported file type.") From 35efd7175c8ef1dfd1462ed01d9394ff2539612f Mon Sep 17 00:00:00 2001 From: James Li Date: Wed, 15 May 2024 02:49:14 -0400 Subject: [PATCH 11/79] update cleavage-profile cli to have laft and right coordinate --- src/finaletoolkit/cli/main_cli.py | 26 +++++++++++++++++----- src/finaletoolkit/frag/cleavage_profile.py | 11 ++++++++- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/finaletoolkit/cli/main_cli.py b/src/finaletoolkit/cli/main_cli.py index c8a5d942..aca10793 100644 --- a/src/finaletoolkit/cli/main_cli.py +++ b/src/finaletoolkit/cli/main_cli.py @@ -837,6 +837,12 @@ def main_cli_parser(): help='BED file containing intervals to calculate cleavage profile ' 'over.' ) + parser_command13.add_argument( + 'chrom-sizes', + help='Tab-delimited file with two columns, one with names of ' + 'chromosomes or contigs, and the other with the size of ' + 'chromosomes.' + ) parser_command13.add_argument( '-o', '--output_file', @@ -847,12 +853,20 @@ def main_cli_parser(): 'suffixes used. Default is "-".', ) parser_command13.add_argument( - '-c', - '--chrom-sizes', - default=None, - help='Tab-delimited file with two columns, one with names of ' - 'chromosomes or contigs, and the other with the size of ' - 'chromosomes.' + '-l', + '--left', + default=0, + type=int, + help='Amount to subtract from start coordinate. Useful when ' + 'dealing with BED files with only CpG coordinates.', + ) + parser_command13.add_argument( + '-r', + '--right', + default=0, + type=int, + help='Amount to add to stop coordinate. Useful when ' + 'dealing with BED files with only CpG coordinates.', ) parser_command13.add_argument( '-lo', diff --git a/src/finaletoolkit/frag/cleavage_profile.py b/src/finaletoolkit/frag/cleavage_profile.py index 52f93136..f5b15300 100644 --- a/src/finaletoolkit/frag/cleavage_profile.py +++ b/src/finaletoolkit/frag/cleavage_profile.py @@ -22,7 +22,7 @@ from finaletoolkit.utils.utils import ( frag_array, overlaps, chrom_sizes_to_list, _reduce_overlaps_in_file, - _convert_to_list, _merge_all_intervals + _convert_to_list, _merge_all_intervals, chrom_sizes_to_dict ) @@ -211,6 +211,12 @@ def _cli_cleavage_profile( converted_intervals = _convert_to_list(reduced_intervals) all_intervals = _merge_all_intervals(converted_intervals) contigs, starts, stops = zip(*all_intervals) + + # reading chrom.sizes file + + size_dict = chrom_sizes_to_dict(chrom_sizes) + + sizes = [size_dict[contig] for contig in contigs] count = len(contigs) @@ -219,9 +225,12 @@ def _cli_cleavage_profile( interval_list = zip( count*[input_file], + sizes, contigs, starts, stops, + count*[left], + count*[right], count*[fraction_low], count*[fraction_high], count*[quality_threshold], From 2d43669d1ce4040e377b1c7171caeef312b218c1 Mon Sep 17 00:00:00 2001 From: James Li Date: Wed, 15 May 2024 02:52:58 -0400 Subject: [PATCH 12/79] files for cleavage_profile tests --- tests/data/12.34443200.b37.bed | 1 + tests/data/b37.chrom.sizes | 85 ++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 tests/data/12.34443200.b37.bed create mode 100644 tests/data/b37.chrom.sizes diff --git a/tests/data/12.34443200.b37.bed b/tests/data/12.34443200.b37.bed new file mode 100644 index 00000000..47a8271f --- /dev/null +++ b/tests/data/12.34443200.b37.bed @@ -0,0 +1 @@ +1 34443200 34443201 diff --git a/tests/data/b37.chrom.sizes b/tests/data/b37.chrom.sizes new file mode 100644 index 00000000..81aa33a9 --- /dev/null +++ b/tests/data/b37.chrom.sizes @@ -0,0 +1,85 @@ +1 249250621 +2 243199373 +3 198022430 +4 191154276 +5 180915260 +6 171115067 +7 159138663 +8 146364022 +9 141213431 +10 135534747 +11 135006516 +12 133851895 +13 115169878 +14 107349540 +15 102531392 +16 90354753 +17 81195210 +18 78077248 +19 59128983 +20 63025520 +21 48129895 +22 51304566 +X 155270560 +Y 59373566 +MT 16569 +GL000207.1 4262 +GL000226.1 15008 +GL000229.1 19913 +GL000231.1 27386 +GL000210.1 27682 +GL000239.1 33824 +GL000235.1 34474 +GL000201.1 36148 +GL000247.1 36422 +GL000245.1 36651 +GL000197.1 37175 +GL000203.1 37498 +GL000246.1 38154 +GL000249.1 38502 +GL000196.1 38914 +GL000248.1 39786 +GL000244.1 39929 +GL000238.1 39939 +GL000202.1 40103 +GL000234.1 40531 +GL000232.1 40652 +GL000206.1 41001 +GL000240.1 41933 +GL000236.1 41934 +GL000241.1 42152 +GL000243.1 43341 +GL000242.1 43523 +GL000230.1 43691 +GL000237.1 45867 +GL000233.1 45941 +GL000204.1 81310 +GL000198.1 90085 +GL000208.1 92689 +GL000191.1 106433 +GL000227.1 128374 +GL000228.1 129120 +GL000214.1 137718 +GL000221.1 155397 +GL000209.1 159169 +GL000218.1 161147 +GL000220.1 161802 +GL000213.1 164239 +GL000211.1 166566 +GL000199.1 169874 +GL000217.1 172149 +GL000216.1 172294 +GL000215.1 172545 +GL000205.1 174588 +GL000219.1 179198 +GL000224.1 179693 +GL000223.1 180455 +GL000195.1 182896 +GL000212.1 186858 +GL000222.1 186861 +GL000200.1 187035 +GL000193.1 189789 +GL000194.1 191469 +GL000225.1 211173 +GL000192.1 547496 +NC_007605 171823 \ No newline at end of file From 37677b7c0725df0de372927b32ad797ae609e641 Mon Sep 17 00:00:00 2001 From: James Li Date: Wed, 15 May 2024 03:21:01 -0400 Subject: [PATCH 13/79] fix cleavage profile with left and right options --- src/finaletoolkit/frag/cleavage_profile.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/finaletoolkit/frag/cleavage_profile.py b/src/finaletoolkit/frag/cleavage_profile.py index f5b15300..de9f9381 100644 --- a/src/finaletoolkit/frag/cleavage_profile.py +++ b/src/finaletoolkit/frag/cleavage_profile.py @@ -87,19 +87,21 @@ def cleavage_profile( verbose: {verbose} """ ) + adj_start = max(start-left, 0) + adj_stop = min(stop+right, chrom_size) frags = frag_array( input_file=input_file, contig=contig, quality_threshold=quality_threshold, - start=max(start-left, 0), - stop=min(stop+right, chrom_size), + start=adj_start, + stop=adj_stop, fraction_low=fraction_low, fraction_high=fraction_high, intersect_policy="any" ) - positions = np.arange(start, stop) + positions = np.arange(adj_start, adj_stop) # finding depth at sites fragwise_overlaps = np.logical_and( @@ -132,7 +134,7 @@ def cleavage_profile( ('proportion', 'f8'), ]) results['contig'] = contig - results['pos'] = np.arange(start, stop) + results['pos'] = positions results['proportion'] = proportions From 73cdbeb881e50f5d1c282e3a93810cb535df5c8a Mon Sep 17 00:00:00 2001 From: James Li Date: Wed, 15 May 2024 03:21:22 -0400 Subject: [PATCH 14/79] add basic test for cleavage profile --- tests/test_cleavage_profile.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tests/test_cleavage_profile.py diff --git a/tests/test_cleavage_profile.py b/tests/test_cleavage_profile.py new file mode 100644 index 00000000..c394097b --- /dev/null +++ b/tests/test_cleavage_profile.py @@ -0,0 +1,25 @@ +""" +Tests for finaletoolkit.frag.end_motifs module and associated +subcommands, which calculate cleavage profile. +""" + +import os +import filecmp +import difflib + +import pytest +import numpy as np + +from finaletoolkit.frag.cleavage_profile import * + +class TestIntervalCleavageProfile: + def test_cpg_34443200(self, request): + bam = request.path.parent / 'data' / '12.3444.b37.bam' + results = cleavage_profile( + bam, 133851895, '12', 34443200, 34443201, 5, 5, + quality_threshold=0) + + assert np.all('12' == results['contig']) + assert np.all(np.arange(34443195, 34443206) == results['pos']), str(results) + assert np.all(np.zeros(11, np.int64) == results['proportion']), str(results) + From 5766b3ff3c60edab25736817881cf915f8d52164 Mon Sep 17 00:00:00 2001 From: James Li Date: Wed, 15 May 2024 03:26:21 -0400 Subject: [PATCH 15/79] remove unnecessary comments --- src/finaletoolkit/frag/coverage.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/finaletoolkit/frag/coverage.py b/src/finaletoolkit/frag/coverage.py index 99f17dac..ce659888 100644 --- a/src/finaletoolkit/frag/coverage.py +++ b/src/finaletoolkit/frag/coverage.py @@ -48,8 +48,6 @@ def single_coverage( coverage : int Fragment coverage over contig and region. """ - # TODO: determine if reference (like as found in pysam) is necessary - # TODO: consider including region string (like in pysam) if verbose: start_time = time.time() tqdm.write( From 60b82f0cb0130354991cd2e8135a02240325cf21 Mon Sep 17 00:00:00 2001 From: James Li Date: Wed, 15 May 2024 03:28:13 -0400 Subject: [PATCH 16/79] update changelog --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d30c870..002d0e71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [UNRELEASED VERSION] + +### Fixed +- Fixed intersect policy for cleavage_profile +- Clean up some comments +- Fixed logging from coverage function + +### Added +- Added numerous util functions +- Added `left` and `right` options to `cleavage_profile` and CLI +`cleavage-profile`. +- Added tests for cleavage profiling. + + ## [0.5.2] - 2024-05-08 ### Fixed From 5290becfbff71e5678bd771a4c41861be1328ac2 Mon Sep 17 00:00:00 2001 From: jamesli124 <58196853+jamesli124@users.noreply.github.com> Date: Wed, 15 May 2024 14:20:01 -0400 Subject: [PATCH 17/79] remove vague TODOs --- src/finaletoolkit/cli/main_cli.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/finaletoolkit/cli/main_cli.py b/src/finaletoolkit/cli/main_cli.py index aca10793..909c9c0b 100644 --- a/src/finaletoolkit/cli/main_cli.py +++ b/src/finaletoolkit/cli/main_cli.py @@ -18,8 +18,6 @@ from finaletoolkit.frag.cleavage_profile import _cli_cleavage_profile from finaletoolkit.genome.gaps import _cli_gap_bed -# TODO: implement subcommands read from stdin -# TODO: implement pipelining def main_cli_parser(): parser = argparse.ArgumentParser( From fab7676b4d49455f9eca9b5a619000f281a3572d Mon Sep 17 00:00:00 2001 From: jamesli124 <58196853+jamesli124@users.noreply.github.com> Date: Wed, 15 May 2024 14:22:38 -0400 Subject: [PATCH 18/79] update type hints for coverage --- src/finaletoolkit/frag/coverage.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/finaletoolkit/frag/coverage.py b/src/finaletoolkit/frag/coverage.py index ce659888..67adc657 100644 --- a/src/finaletoolkit/frag/coverage.py +++ b/src/finaletoolkit/frag/coverage.py @@ -2,6 +2,7 @@ import sys import time from typing import Union, Tuple +from pathlib import Path from multiprocessing import Pool @@ -15,7 +16,7 @@ def single_coverage( - input_file: Union[str, pysam.AlignmentFile], + input_file: Union[str, pysam.TabixFile, pysam.AlignmentFile, Path], contig: str=None, start: int=0, stop: int=None, @@ -66,8 +67,6 @@ def single_coverage( # initializing variable for coverage tuple outside of with statement coverage = 0 - input_type = type(input_file) - frags = frag_generator( input_file=input_file, contig=contig, @@ -101,7 +100,7 @@ def _single_coverage_star(args): def coverage( - input_file: Union[str, pysam.AlignmentFile], + input_file: Union[str, pysam.TabixFile, pysam.AlignmentFile, Path], interval_file: str, output_file: str, scale_factor: float=1e6, From 01d988fc0909a453bdc9a5a477ee2f27b5205eff Mon Sep 17 00:00:00 2001 From: jamesli124 <58196853+jamesli124@users.noreply.github.com> Date: Wed, 15 May 2024 14:30:28 -0400 Subject: [PATCH 19/79] update docstring for single_coverage --- src/finaletoolkit/frag/coverage.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/finaletoolkit/frag/coverage.py b/src/finaletoolkit/frag/coverage.py index 67adc657..cd141301 100644 --- a/src/finaletoolkit/frag/coverage.py +++ b/src/finaletoolkit/frag/coverage.py @@ -37,16 +37,28 @@ def single_coverage( input_file : str or pysam.AlignmentFile BAM, SAM, CRAM, or Frag.gz file containing paired-end fragment reads or its path. `AlignmentFile` must be opened in read mode. - contig : string - start : int - stop : int - name : str + contig : string, optional + Default is None. + start : int, optional + 0-based start coordinate to get coverage from. Default is 0. + stop : int, optional + 1-based stop coordinate to get coverage from. Default is None + and goes to end of chromosome/contig. + name : str, optional + Name of interval. Default is '.'. + intersect_policy: str, optional + Specifies how to determine whether fragments are in interval. + 'midpoint' (default) calculates the central coordinate of each fragment + and only selects the fragment if the midpoint is in the + interval. 'any' includes fragments with any overlap with the + interval. quality_threshold : int, optional + Minimum MAPQ to filter for. Default is 30. verbose : bool, optional - + Prints messages to stderr. Default is false. Returns ------- - coverage : int + (contig, start, stop, name, coverage) : tuple[str, int, int, str, float] Fragment coverage over contig and region. """ if verbose: From e6200b223d9a4fe174d250bc6e2a41b88627ad57 Mon Sep 17 00:00:00 2001 From: jamesli124 <58196853+jamesli124@users.noreply.github.com> Date: Wed, 15 May 2024 14:38:09 -0400 Subject: [PATCH 20/79] add intersect_policy option to coverage --- src/finaletoolkit/frag/coverage.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/finaletoolkit/frag/coverage.py b/src/finaletoolkit/frag/coverage.py index cd141301..b6293bb8 100644 --- a/src/finaletoolkit/frag/coverage.py +++ b/src/finaletoolkit/frag/coverage.py @@ -110,12 +110,13 @@ def _single_coverage_star(args): """ return single_coverage(*args) - +# TODO: add normalized coverage def coverage( input_file: Union[str, pysam.TabixFile, pysam.AlignmentFile, Path], interval_file: str, output_file: str, scale_factor: float=1e6, + intersect_policy: str="midpoint", quality_threshold: int=30, workers: int=1, verbose: Union[bool, int]=False @@ -155,8 +156,10 @@ def coverage( sys.stderr.write( f""" input_file: {input_file} - interval file: {interval_file} + interval_file: {interval_file} output_file: {output_file} + scale_factor: {scale_factor} + intersect_policy: {intersect_policy} quality_threshold: {quality_threshold} workers: {workers} verbose: {verbose}\n @@ -180,7 +183,7 @@ def coverage( intervals = _get_intervals( input_file, interval_file, - intersect_policy="midpoint", + intersect_policy=intersect_policy, quality_threshold=quality_threshold, verbose=verbose) From 40c8c842f9837225fdfb495ecfedc843be49ed3e Mon Sep 17 00:00:00 2001 From: jamesli124 <58196853+jamesli124@users.noreply.github.com> Date: Wed, 15 May 2024 14:41:46 -0400 Subject: [PATCH 21/79] add cli option to frag-coverage and remove TODO comment --- src/finaletoolkit/cli/main_cli.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/finaletoolkit/cli/main_cli.py b/src/finaletoolkit/cli/main_cli.py index 909c9c0b..40b2989d 100644 --- a/src/finaletoolkit/cli/main_cli.py +++ b/src/finaletoolkit/cli/main_cli.py @@ -32,13 +32,9 @@ def main_cli_parser(): # Subcommand 1: frag-coverage parser_command1 = subparsers.add_parser( 'coverage', - description=( - 'Calculates fragmentation coverage over intervals in a BED file given ' - 'a SAM, BAM, CRAM, or Frag.gz file' - ) + description='Calculates fragmentation coverage over intervals ' + 'in a BED file given a SAM, BAM, CRAM, or Frag.gz file' ) - # TODO: accept tabix - parser_command1.add_argument( 'input_file', help='SAM, BAM, CRAM, or Frag.gz file containing fragment data' @@ -62,10 +58,17 @@ def main_cli_parser(): ) parser_command1.add_argument( '-q', - '--quality_threshold', + '--quality-threshold', default=30, type=int ) + parser_command1.add_argument( + '-i', + '--intersect-policy', + default='midpoint', + choices=['midpoint', 'any'], + type=str + ) parser_command1.add_argument( '-w', '--workers', From d24052acf26b35087e0aa99ea64d5f4ecdf2fb49 Mon Sep 17 00:00:00 2001 From: jamesli124 <58196853+jamesli124@users.noreply.github.com> Date: Wed, 15 May 2024 14:47:44 -0400 Subject: [PATCH 22/79] update typing annotations and docstring for coverage --- src/finaletoolkit/frag/coverage.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/finaletoolkit/frag/coverage.py b/src/finaletoolkit/frag/coverage.py index b6293bb8..42d3a9bf 100644 --- a/src/finaletoolkit/frag/coverage.py +++ b/src/finaletoolkit/frag/coverage.py @@ -1,7 +1,7 @@ from __future__ import annotations import sys import time -from typing import Union, Tuple +from typing import Union, Tuple, Iterable from pathlib import Path from multiprocessing import Pool @@ -120,7 +120,7 @@ def coverage( quality_threshold: int=30, workers: int=1, verbose: Union[bool, int]=False - ): + ) -> Iterable[Tuple[str, int, int, str, float]]: """ Return estimated fragment coverage over intervals specified in `intervals`. Fragments are read from `input_file` which may be @@ -138,19 +138,28 @@ def coverage( BED4 file containing intervals over which to generate coverage statistics. output_file : string, optional - Path for bed file to print coverages to. If output_file = `_`, + Path for bed file to print coverages to. If output_file = `-`, results will be printed to stdout. scale_factor : int, optional Amount to multiply coverages by. Default is 10^6. + intersect_policy: str, optional + Specifies how to determine whether fragments are in interval. + 'midpoint' (default) calculates the central coordinate of each fragment + and only selects the fragment if the midpoint is in the + interval. 'any' includes fragments with any overlap with the + interval. quality_threshold : int, optional + Minimum MAPQ. Default is 30. + workers : int, optional + Number of subprocesses to spawn. Increases speed at the expense + of memory. verbose : int or bool, optional Returns ------- - coverage : int - Fragment coverage over contig and region. + coverages : Iterable[Tuple[str, int, int, str, float]] + Fragment coverages over intervals. """ - #FIXME update docstring if (verbose): start_time = time.time() sys.stderr.write( From 5989ffdf36f263d667f57649aca6242489b608b9 Mon Sep 17 00:00:00 2001 From: jamesli124 <58196853+jamesli124@users.noreply.github.com> Date: Wed, 15 May 2024 14:51:37 -0400 Subject: [PATCH 23/79] replace genome2_list with chrom_sizes_to_list --- src/finaletoolkit/frag/adjust_wps.py | 4 ++-- src/finaletoolkit/utils/utils.py | 25 ------------------------- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/src/finaletoolkit/frag/adjust_wps.py b/src/finaletoolkit/frag/adjust_wps.py index 3c9eadcc..9323da43 100644 --- a/src/finaletoolkit/frag/adjust_wps.py +++ b/src/finaletoolkit/frag/adjust_wps.py @@ -11,7 +11,7 @@ import pyBigWig as pbw from scipy.signal import savgol_filter -from finaletoolkit.utils import genome2list +from finaletoolkit.utils import chrom_sizes_to_list def _median_filter(positions: NDArray, data: NDArray, window_size: int): """locally adjusted running median""" @@ -255,7 +255,7 @@ def adjust_wps( # write to output with pbw.open(output_file, 'w') as output_bw: - output_bw.addHeader(genome2list(genome_file)) + output_bw.addHeader(chrom_sizes_to_list(genome_file)) for scores in processed_scores: contigs, starts, stops, values = scores if len(contigs) == 0: diff --git a/src/finaletoolkit/utils/utils.py b/src/finaletoolkit/utils/utils.py index 4ed0e21a..c8607156 100644 --- a/src/finaletoolkit/utils/utils.py +++ b/src/finaletoolkit/utils/utils.py @@ -537,31 +537,6 @@ def _get_intervals( return intervals -def genome2list(genome_file: str) -> list: - """ - Reads a GENOME text file into a list of tuples (chrom, length) - - Parameters - ---------- - genome_file : str - String containing path to GENOME format file - - Returns - _______ - chroms : str - List of tuples containing chrom/contig names and lengths - """ - chroms = [] - with open(genome_file) as file: - for line in file: - if line != '\n': - chroms.append(( - (contents:=line.split('\t'))[0], - int(contents[1]) - )) - return chroms - - def overlaps( contigs_1: NDArray, starts_1: NDArray, From 7282a5dfc82913ba75dc4727547993e4fddbbdad Mon Sep 17 00:00:00 2001 From: jamesli124 <58196853+jamesli124@users.noreply.github.com> Date: Wed, 15 May 2024 14:55:03 -0400 Subject: [PATCH 24/79] frag_generator raises exception if contig not specified but start or stop is --- src/finaletoolkit/utils/utils.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/finaletoolkit/utils/utils.py b/src/finaletoolkit/utils/utils.py index c8607156..98608d15 100644 --- a/src/finaletoolkit/utils/utils.py +++ b/src/finaletoolkit/utils/utils.py @@ -294,7 +294,11 @@ def frag_generator( else: raise ValueError(f'{intersect_policy} is not a valid policy') - #FIXME: raise exception if start and stop specified but not contig + # Raise exception if start and stop specified but not contig + if contig is None and not (start is None and stop is None): + raise ValueError("contig should be specified if start or " + "stop given.") + if is_sam: for read in sam_file.fetch(contig, start, stop): # Only select read1 and filter out non-paired-end From 0394189f9c0e62e28f40894bb41a8cdd2fc30e68 Mon Sep 17 00:00:00 2001 From: Ravi Bandaru <80599578+ravibandaru-lab@users.noreply.github.com> Date: Wed, 15 May 2024 16:27:41 -0500 Subject: [PATCH 25/79] temp files --- README.md | 2 +- banana.txt | 26 + .../api_reference/basicfeatures.doctree | Bin 55511 -> 55349 bytes .../api_reference/cleavageprofile.doctree | Bin 11527 -> 11500 bytes .../api_reference/delfi.doctree | Bin 38342 -> 38207 bytes .../api_reference/endmotifs.doctree | Bin 142353 -> 141543 bytes .../api_reference/fragfile.doctree | Bin 33805 -> 33643 bytes .../api_reference/genomeutils.doctree | Bin 79238 -> 78401 bytes .../_documentation/api_reference/wps.doctree | Bin 65916 -> 65754 bytes .../cli_reference/index.doctree | Bin 640035 -> 623102 bytes docs/_build/doctrees/environment.pickle | Bin 921148 -> 909278 bytes docs/_build/doctrees/index.doctree | Bin 10002 -> 9902 bytes docs/_build/html/.nojekyll | 1 - .../_documentation/cli_reference/index.html | 376 ++++---- .../api_reference/index.rst.txt | 2 +- .../cli_reference/index.rst.txt | 3 +- docs/_build/html/_sources/index.rst.txt | 2 +- docs/_build/html/index.html | 3 +- docs/_build/html/searchindex.js | 2 +- docs/_documentation/cli_reference/index.rst | 3 +- docs/conf.py | 3 +- docs/index.rst | 2 +- pyproject.toml | 4 +- src/finaletoolkit/cli/main_cli.py | 897 +++--------------- 24 files changed, 318 insertions(+), 1008 deletions(-) create mode 100644 banana.txt delete mode 100644 docs/_build/html/.nojekyll diff --git a/README.md b/README.md index 7cf42e7e..9439108d 100644 --- a/README.md +++ b/README.md @@ -66,4 +66,4 @@ We encourage you to use our comprehensive database, FinaleDB, to access relevant - Yaping Liu: yaping@northwestern.edu ## License -For academic research, please refer to MIT license. For commerical usage, please contact the authors. +For academic research, please refer to MIT license. \ No newline at end of file diff --git a/banana.txt b/banana.txt new file mode 100644 index 00000000..4910d743 --- /dev/null +++ b/banana.txt @@ -0,0 +1,26 @@ +Usage: finaletoolkit [OPTIONS] COMMAND [ARGS]... + +Options: + -h, --help Show this message and exit. + +Commands: + adjust-wps Adjusts raw Windowed Protection Score (WPS) by + applying a median filter and Savitsky-Golay filter. + agg-bw Aggregates a bigWig signal over constant-length + intervals defined in a BED file. + cleavage-profile Calculates cleavage proportion over intervals defined + in a BED file based on alignment data from a + BAM/SAM/CRAM/Fragment file. + coverage Calculates fragmentation coverage over intervals + defined in a BED file based on alignment data from a + BAM/SAM/CRAM/Fragment file. + filter-bam Filters a BAM file for mapped read pairs meeting + specified criteria. + frag-length-bins Retrieves fragment lengths given a + BAM/SAM/CRAM/Fragment file. + frag-length-intervals Retrieves fragment length summary statistics over + intervals defined in a BED file based on alignment + data from a BAM/SAM/CRAM/Fragment file. + wps Calculates Windowed Protection Score over intervals + defined in a BED file based on alignment data from a + BAM/SAM/CRAM/Fragment file. diff --git a/docs/_build/doctrees/_documentation/api_reference/basicfeatures.doctree b/docs/_build/doctrees/_documentation/api_reference/basicfeatures.doctree index 0e5ec3b941708bfd9a88edc4427589ed6cb1a9cf..d51231d19dfa62d9fa72b0114144c6f90b075668 100644 GIT binary patch delta 125 zcmcb{u9^CI>U>F&7slZ|-MdR7P+o_p^j;HrCiG#@G#0G5JhJ o{N^e4uQd=to6lr$Ni$ABQV})z+#asY?JWz;QH3|3+rudX0F%8fod5s; delta 540 zcmdnGf%*DIW|julsb@B_*s=J|)ekLBEh^T}tt_!Hu(Z_A&CJV8%P&e#HP%nfD=XGd z%gjs6NiE6G&nebT$xklU&&f>EFQ_cZ$j>v@Gc?jK&MZmQEl5nxPE1cNo}7>&GI_VU z)8v$g#i>Qb`ni=Q76z7<`nj2TnQ8e&>8Zy0sd;6^`e~VY zi8-ky`T04;x+(d|#rip!N%{qqB^mj7#(IWE`o)kXp)!Dm1wvHE8p?^smAQ;mseauSo&`M?EV0 delta 438 zcmdnLis{&DCYA=)sk=9_JYn&jq90nET2!o`TUlaZU}>qJo0*rHmS2>fYOJ4{S5~Z_ zmYJ8BlUkCWpHr-xlAm0xpOcxSUr=&9BX7aWgJNQGLcmZt}9N@{?1XkD*LJFH~~pv{N_2)N`h!YS-CGcQJj-7sp1v70Q=^7mB$4bXCWDuF!@af=Vs|{ zZ+Vk}<6&Heq__g;^M44D%^$a&A71OdAD0iGfp)| zmE8`My)DDofubXS9wR?Q$Il$bI|it-+kvt^VvG|}baZ@Tl-LfmqtOOcVmnY`DKAIu s6pak&tSzRK0~Z-jul>r%zO{ns0u%exlNuoJOgD^Y6x$xd%(PVl0J4z4l78UE~R+d;8SX%1mX69w4;Ci0PejC^)*DZZTJJUBa zE!XGqJxBw`D+9|B`N_RroRd8-a!=;la+>RJpUrw=7NLjg0wS! za=}5?%_f&8bNOzknGfRcxeC(G_{s72xHh|e$mgO>AWfI!WMtdy`#YM6b1FXrBLfIb z{@9?k`O;rYrs=vYjGU9_o$%k9!?=Z(4%ohfo6&~HcNLZ6$anfGA4ak1ahn)tDtTOp}deMW&mqWX#?=m&r>50D#gU Au>b%7 diff --git a/docs/_build/doctrees/_documentation/api_reference/fragfile.doctree b/docs/_build/doctrees/_documentation/api_reference/fragfile.doctree index ca6cbe5b4be6d9c3a27b6169771f7f5e5b1be22b..e2cfa119b0bf24edf31b23703e6f8b4fae8726d2 100644 GIT binary patch delta 134 zcmeC}V0zug#M;0*HKBPUs|5>V*W_46J?7$~qnmnJyb90#HLr%s< oWR;VptQFpk{hZ7s{esGpjQl)fJwqe?;>?m%-GapA?8Nlc;?4OiiYnAK za&kUP+-3#Mhn&81sOeImv7(dLSvqX)Fuu=9eWN$8vy|iVok>*}zmE&r9N>~GMO|Yz JzmKa?0RV+M!@~do diff --git a/docs/_build/doctrees/_documentation/api_reference/genomeutils.doctree b/docs/_build/doctrees/_documentation/api_reference/genomeutils.doctree index 7eef916f8966ae38c66541c48208d07e8996b581..51987b19f433a376327f47926c9a656670c78631 100644 GIT binary patch delta 733 zcmZpB&2sPw3rhp*)U1sxj4X@|lfxPHn2U>&Cw~<8-@K3|h6_z-CjT!+#ug-15t}W9 za##^Un?H)rXJhO@QV}qDpBB$#sja+|?Q)7X?~u>rLY3aUPs@{^aRQ2tEPMXVo2|C6 zVi6X0)Z$=lMOMA}mZt+Fn$ULdFKmom$f_pS#BffYeoqMOimSn!I5DL+>&AugGWH_t z+N_Xc%Y`a5Ss_PoGk3WnFJn8h%E|Iw+?%hotYbkH-Ynns1I;Cyw@fTzMzwwO;i76duvf01X9VpS?lyBb`%GJg(qvB=HA?L zIhPB?6%Z-@=X{&z+`Gn(DYcpZxhglpu+5F1N?8%y$&H_)H_!W#&C1w_6fCZrXa6f^ zoLa&tJtYqIOpTKq@ gR>oRXt9+)v5@6(?eCLzsb{}p=Ry4`&K*>2O0ETu74gdfE delta 2841 zcmX^3gr)5@3rhp*ROXE=j4Zyh^+StOi;DGgD@!a4EG_kOGxIXj@{7__jrCLW%8K>V zGV>C1QcLplbBc9S@{^18b25|k3o1)8^7D-K42|@QGfPr+3lfvF6Vp?RCl_Y&&3zo1_-`L6b1vxg~6?bRzT}*8kPnOZ*nfz}P@8}+%yQF^{Ihi8GvB&K`Z0U-hZ{2r`9q4qrP2}m;V;n&dkJEOM~ERrb905FF+WdHyG delta 567 zcmccB$nvL&g{6UYD#J#Weiq+8{m|mnqGJ8r$`T6$OH2LS%)HFB{G#+!WBt^;vSR(T z%)G>$)RO%CoMPRS{N!T&oXjNsg36MN{5)elLnHm-%#u{yg2d$P#PrnS$rp{?H}kMg z)}yYmn=cxllkiU8PZu(q$V%?AwSiIaUK9!@6^r! diff --git a/docs/_build/doctrees/_documentation/cli_reference/index.doctree b/docs/_build/doctrees/_documentation/cli_reference/index.doctree index 3ffcf75fe1fce3fe6c3d2681b04b9bbe87fa3e9f..47247f1d4b28f2cf090995687a777adc5ccb1ab8 100644 GIT binary patch literal 623102 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

*E+j2fay_Kfa=4xsE;}dpoG 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̽pJ#5$rU1hrbFV z1kF=}0|sSd1k#__$O`Af8z~3*rJ)|O0A4R;D63oHKC1uaIuqQw*R@O*BW5vmENTf2 zJQ|bW_sDvdt{X+3+v!ZRxmm|%`s)4`R(o|TFHA)kiY=O(Ncx;hsu_A7ygh|RF(AWQ z-sg2-z8F!0vQzjyA}mW+_jtLie#-n;)r0c~^E+OBMiV7q83s;O^^6b=nRddEQ1@1| z_o?$iGxS#Da!L3bF@xux$e1lYg`=q|#!0p?qqi+r4sIdPpf6>&cr2$RCt85lJ{~Q) zB*5=$CZUupuL75N9>CYYn1BJ1Mm5oRr^2aXgn>ClK-Yu ztx2mkT(lUfY1V*QDKOD7UZV!e$Y3PS%M*a%y3$IRYpoyz<}%kqbfNUK6{o6WVG~O( zb>)R&NVWdW+T!qD|Lc zGI8ZoFS!!0UVH7ul`?r!wbxdYllBN^Y%>(|fpys_Od4>7v>L)#$8XC4iP@BFRvWEX z?kIR=#^{wUPnqceTMkpSjWM)^B_&q)ATOMGU?%vbA$|!iNa!{LZ^R(5hqv-O1bY12 zEGDt=b5z>1)y`3)w)D&qfIsFS{QAlKjaIGBR$|~JWp*|#nh3g^_!G&2!zfm>NETOX zqFNjIi|ihaMwnE<*x~Q3<@e-r5fG1G-@>nJe4W=$Y zDxT2sH@2!f(#F)art2Z*Y5`Kh3#>O@gDWp?ypK(sc%cL6A;P9XgY$m2#^`5QLosbd z0uXZG74|QR`_&pMMro_i##89(Y~f%@sy}(tAov=_Z}G^+Cb~qW#D{rle}#|HhoAN6 z=xk9#Z`|~%^0^!HEchY-x%!!gzv{J4i36TJ%bZBAK1`-C_fw5cl&YHhJD++eY{4P!$;s z;p;HW9yuKw#4;p#mRc>{eX*`cE1p_}pEek6Aon~BjCpPk74zJ>KUkVWr(r>X!_f-3 zpAqFpT(WPqX>bG7!ouMS8fYstNDR=l538887Qd2wLU4P+<$=X>wkSYhg$=B_tZrd- zxG=@n;9v)hz>_L#|M*0X2kV{H@NwKInY*djcr*VytN@1Gm#O@4zZ4J~X* zWjL8H{$ueS3$$?LvgiV~$gTNPPUp)tc^aYG)jKd6l3QUa-<|wN(};RB z#S(}>I(kK)R&Pe%K-Vo*uw09^5#gZ~>lp*_P3D@}82^;d!kU=~N0)F5Xp_1M=o4x`U!cd(>lV)njZ~B9+d;NvJ0r%e3BRBHXAdX-JiX=gEdn zEvr#N{2pJgR`*X-?{asm#Pg#uKPRh4u=IwNxyGzmA=l_=qHDsQ;JOcQla!rSN4`cu zt|)nPouVM-?;A`szY5K#_}!`=r?nqaEp%A&MWGuj*0gqrALE{1^k+$Wiz!vU7cqaBG7Qeyp~%nZ*uQ7-YYSvQ21 zQbd8tr1=PDoILQmo3QyHi%{)E!`9NU`cs=Ni4e6UBbq3byhg0$$pBTfGGSXMdQ9SR zt;{>xSb>8*MRt^>VdF*TPIP9XFq2^lzvo1g64Zzy>Cxb4_Xghz z{xx`TBKWu9yTL;f!TW;u2mf_6c=%}W^P|B#F$w8!kGvp!S^VpfFHMH8 zihup|MF+z_mcObeoc_h|HR{(5uMA%r|6021FT$6^zXm^5Y)6P{&|^eb!9P;r(=K%T zRRVC~P-6R`*a|5YcyMb8smgtw=X7omJP;NJV`Jm-|NTW_8FtDz^`mhaB#-FHPING) zgD(qCis%UwmZ-guwF_}rKc-|QRFO$fu)%4Q77*>yF{RD0nTht;^2q4G4ucmrPrHzg z8_Ag>dOh2!#KlV8iNqQnQ?X)f#A+z*isDqM+Y;58V?~t>oa5N+k)J%wWIKIqDKUDC z&@tD>EL>bJ%;9}xDwtC5T2IVEO z@-bzJtvENqn`AZgkz`<7%*2?tK%Ruq>P7)?P|Rcq!O=6FP-xdU~Klz3Ms+G>p8?CO|&otzGEx?}GXt5#Aj zV)H9vqG;l(wlu{XxKF^Q0o>8%(TcO^Q<4g5NE>u$Al;jT$)39__pJI{6ZnDnZ%p_x z38$ETHqc%oe_es6)m}ICGIlTX{XTJVBe^CmS?8y*re14cA1-znv~o|%?b*%#8{0jS zV}8mOB4Xi@#U!~hwU>6$;hA%BQ!JUtOM6CgutO)Y*=28zJin+dfA$LOmnrRH`Zye% zKn5E)hgX{gmT7!%OcA)$;?#Rel}}viP~~Cl7%R_Uhb|9i!wwBpf_X<+ElT>X=iuqV z&D64+snD(AdcExEB?*mRaLY|LJ|J{2+1SkCLTe={(utpyUuf_9BI+&JEk{yLig=}Z zkTL~qK?(w~(He#@%Mt*F&(axA!v!ozk}z4}a3+Az{6ZW~5n{NLF3Os2U^T_01vvsR zKC+!#npS+|e^4ig`vC9#G0z%8M5lH0YxM2745q?_AYH9IsEUyNN57<6`YKmTM~kXh z&NMRugjet;y%Zlz)i$vPq>9ujh`h~b+FBDX+AFJpZ;JXYZtC@J>Q7HlkAYNd`O@j; zV!AnvZs?|axSMXE(+#i0FF7=0=NQB0^k%{~I?U8DV?Tlb0j;6MfW8G2(N;sN-LqY_ z)0+bsMM~3rp5F;yM7}-jznCT$XeXS-NX_oY4pSn8{eXy5sF#XZek#ICFaVh0qagN6 zt;7%Rc%C2tyqmK;hYxsT$~w!7(nWiptMXwRPjqRNkgXtevq9*txDD^pr1Wwpp{X=N zLU}T9^m->D500LtaTK@v8dG0Xzj(KcWX~FKrkC~5yN;BMOd{cpX-#0DhxvlemmGvI zCShz1pNJ3W;3fEoyWIx1rxv@Ml##=9W!UVUYmCRFHYKhq>3@|7+N@$LTVLe$G*vhq z{=VxZWK&^5$fr~O)Je#u!h(A|3;Xq*$G5jx6C0?z1@!sqOC%Wl4&tKnzb)& z9ZH(tX}Y>fdq`@kaZTyzxh|<%85(C22z~VQ5+@;>o(e)fdioS6A)B5GLVf6I!A1YL z>*)d3N@f}kk7n&lPfv493e(hfwf>IOTl1n)+~>H&Y~}D*m`J=7_dX{fo8k&WK8pKt zCn1~S3POhBE@N|XCdqV&6%Qz>zS&iWo|RXS>cMb)J!`8B>YG94A9L|*wKO>)Oq18g za~JHV;F)Ih3B;46GB0|PW_*6pMLSwl>z+V-p5EFTX5jHVE;>Fu4zNuG8dC$Ye@8N> zT~P}4h>JM+Q22ggw$a>V7;_@*eWj>1Z3koLD9tKpPeUw+zMyKW#XZG%OIU*IyPlU4 zNV%gVv3a?}ez5}9db|zG)n}wV!%4^nSb~rbVC``dvH_MLWB}F@7}-pi>2SqvD~Vp_ zqTe%EF+x2+)stB(Wq_&-(mvqg*4m8)p)a62#xozFk;r~$;L<@Sp$Ab)*X&yWQwEOa zoP<2|=V6_r#pmvpEYVk`D$jG0T8<|Sp4`~OS?vpZhLYZIR{aFvtPl@L*5coazn3}r zv(2JkjJG|(sU_5R)$9a*qZr8=QoCfELbZU(mAEvW%9BGU9p3B&Fq{ zWjKx1vz@HkP-Z9I_C%Q{I0@NMMiBBrnJb-yY+51+87MQT7A=L8Q=MCUSBnDhTU-_C z8E(Y>nd}bxr}Fml5#y|@_Ez{1giPBu-C=*HlaNg@GH`U%Nyw%cf>3J9CydzNcM;2Ikt<0KZgj}<>zAS z2)n_95Rf4cgB~_v5AUM1;^8`~{;wUpL^y{y?Homm zp|sj;4iCv_pWAbXgK{y*%@*czlcm7|KYf6mLvR^8k|22yLGG#8?UF0t%!0}cQr5JB zS(JcCv>f&%L=?#&1ve?`i2vb7Axz=rDaA~=nZtH-c1VJ#9SRy$1+}nA zBR7pOaN@Yes3?Z{uEDX~M6H!;wh?(xc?_}FMx%{zmS*{xCE798s39B<>*G`sOW@D$ z@cjA1h){WQpR(7iph2XnN-XUm5BoZvlNHP25ExF9(AMaqRa(o*emx*7+SH2P)Lpb` z@9Q0bG;{;Kur;JAK_9n7r_8Sy8krOh!i^{*_6)4nwMf=DJ^16XeOCGA#poFSr>OSU zQ9wD**&2_AfHLUm3Z*PiS4$M?;Po<)D?Xt?zobUPOI3;f(Wg(=UkWdxU)%Q&phoD% z@J1tTF75JR34*k4EHQl`La37QQ1bYO=v4}Yb3En}P|KqxjBt%Xb{@?9hzux2)-cou zz*a9H+rrc+!hqDUF-W)%K*o>(T&BIXW4YT63b*HGabOAHKS!CK*f_!m3rbBU;Sopu z05tUjD3HK59!Bi_|9~#bv@pLUWZg#5qmOFz_*A3ggQqjk4LHy(qEXn=K3w^+^LWL-ihWvk5_ zyL4}NiC*I%)dVfHCE8|Jd!-U7b$5cTuDf?LiuTIgN!&;^x0W70l^!)Z#|?}?_%wXP z!}Bww?Z85oIKm8GdilQd=+F}!r=mbZJ_w8;!;;&BFtxC!gVrhOS#I$Tvg{c!Op8r{ z3gK-!$wZ)&aD*kUDzUzS_^^dP*->FF#PvGPctx*895I9@PJ{=&Co4tKw~0*Lx5K+M zY9ho=9awYC0*e?-EM$>N`XA3I3p$-kDm97zqj*0V*pzHAq13#UvM4nXAf=9{QKoL+ zqs1<9&Bow|T?gzqp+W^#Kr5hW0ERRSgrx3JXQU;@egdh>n03^~a#v65TNSX`;P(9O zBN#B7Nc+{y9WGZh77rK;ABrgvk~qX9DZRIdSy=QypwZdxqUn)BnJ<|p54!QTxzE@Bf~_mG%qSyJ~3fjZ^7aBttx3$R% zFV8TCsBmR6co;VAYPEAt0GPU<_1m^`zT*j)y=v_pdgPRycsbyZ_K|mlYOKszl{n}r&PtJF|v$e`7%;BQ?e2)%JAc1 z%oUyRF1Uchhe0-4ffXOV@9Yu!$##WmzgJYT0zt`tjz+7+SK6SB{G-vjYE3M|;H(LD ziTvY(YP|-cX1mVC9`*2HY-}^Txv}j?pYIskz{BMzGh&AZi_|C{yTG@1FIBPiDw!Y9 zXCrvH3WUuX4~IkAwVUav8Csc<^-?~(Y#YDL9pYGdDIXcTiT?6k;T+j`kx#<>FjpB5@ZI6YH6^@Zo$0hu zZ8$uig!j1lgg2Zbyl^L#${;AbP_Nj}|Ce_Lq4~zv$FsX-Vk{m22jXro-Zx{N)cfo< z#%O)rKsEJ6uBNuem+Zyco`GZ6Itkh0g9IU;h^Jq660(JT2ttN1Poq_iyK=4uNRKI^ zJ=sd!6<6hq!R>f#{tkE(`bhR3SLLlCLV}P_EZGa3glxK!fuk2Y3E6Z-5K3+Lc^6P# z<09F!1{}N1-x(zO9v6EHr6V785?UY~`J9tbuR1cIAY38DgD!GC>&M9|IY7d2>?I)p z*9mhn;W1X2FX+5T!%HLtcpT(_p~V;#H+0*#X@eh~1da*59QfoD+5m;mQN7rLz^ z`XLwn-qD2!^{}1v{j8NTpi2g6f7!*Y6-bzNytNg{Gp}eB-aD9aCZBG zmK|;fej3;eC0~=k(|tpM(4RYHU<097<84n6dZ&|+4TJ2|^|a(e#K` zD(10o%-PfDUG#egAtKa+ee)UCN*O>XgS3C>;?@d6f{+ggEm`BT18g9afur?KLLT~K zfY6{?c#~aHzoa_jX-?8T01{`tFF-nRp4GxM6f)v9#qyqUO|g4{lU*D3oQJnPvF8dW zAshAxLO$4Ylar85cLbq6uxHvu|F~n%Bx|J%*porp_qe#VVviu?gFP>B60%`W2993r zB;=t#2KHDzH?MJ$>j7^#yM5u!aY_~T0Vn%5{CO|l_QaombP}@Rk09iOKVNndvgwZ? zWa1C`R4ld+-ByVHeHZ=S@rMZYVEa78S}6nmWRUi%wJwvyL)t$0bF!0=4SzClw9`q* zgChff=1moLzLQiB*uz=v3wt)F#yF)}I&tP6VdccXRezXpGHFAYYw)%w!rbO0WJ4H1 z$OmCUCn1}L2to$J@WeUuLrgM-&t0w>^o%h*r|>z#8Y%$^Y!{!%BLk4N{o89(VldM^ z7As_!rb4Q(x@6RIuUcb9hW0Rqe-U-F?UR(j2A?M$5>cL-?3D1sA;cr_G&tdpDM`)4 z_+tc)hCjmXQ7;M5q(>l*b5OSE~u2MGp&Hq#>9yWn%EC!WU3itsbDCRO<@u{ zl36Mk5%7!e;?yX%mx7)_wil#X9_1MkSULl_X&DiSVt>Ccf(WsHJG3I`Cb9KC;mWdQ@J8Va7Wb)8jBt@3-=oEI*5G z4rp)2qbfQYJ!z>DxqY9Lp5H_mZu%u9wI`_(1_rd-X|MiL_yqd3eg85TaoxL} zhRy9xFHzcs4Nvg&&XbB`kfkwUnI^E!?J^{o>dHotmcm44Fd6J8gNeDPO4ofUNyUWL zwQkUbk`{rU?8{0^~qv{z2- z`R1x?EnRL`(-eL`BVaxc}h6un0NR6XS7SsTXe!2^)kOE^PD5AIH?AZpNkL)GQ=S?eNtD^13Qo2gg(6bEkXi$0>QNdT*rsfe8fQ?X>7gSQ?@OvOUL&&1`5^>GIj}y*1ZIvS zi8KO21rt|Qn|&v1Erk9NX;1wd&Ll)=pZ^PrkDq4bL)X345aq*6lwP{WrJhCisIBa} zSF3la-X5WPjq*&8S@*1=T3d(WZqSS7tpPVDqKKpglh84j=IzQ_3!!;L+Eep(Ws@OP zFT)#3_x5JwMAtn^Z1i|0OfTKza?hfB)LQfF-pyOE`3w!@YW$r=jY$j|IVn%BdW ze3kFRr8FyT!bS|t;z)9BaK==f(zec&50$DhN*XCzcF6s^JH~R?)6U*9$`=Lg9UP5Q z$L?kG`U1~5Mwm;<3>6A97eOJWoU5Q1*z)WpiOypvu299!Vf;bD!$ymWq4c!Um>^z~ z@1#L`ckGcI;*&DeEX$iSsz(CoDG$j_OhXbtk6D#!Bk6xwV_sECI-Ru^qPr1k&+hia z|Gjzw==kw5;r?s)yjb>=uif*KU(lYSwCr$3Ez_ZJ2#VffitYu4yia6-Lh4Bd6xv@F z`7`$FmW7x#nHha<(E^InrZZhh2)f34mGCD$)6X%apxW;D`)E7L0Hg^@&jS)IDNpS& zQ~!j&g*+Vvk=-O9(_eFV39ungQ=C<#&s0CJ&&nA&zh0-mBxlQ~q&mOMiS5nOcfB`f zEEWvjE*2_o*S*@9T5wM{OT^A{6Y_NEED=z7dN59Io|?~Wg?L@!fBaju>j!m4vOBC! zg)H8OBD%~ygE>h*u|A?|@yV>U5aSP#_8fmMULXM*SrD@2Wlm)I`#O^= z29L-0suD`TR90fW!isM?^imsth1JCidbv7SOHVj~h`_r&2nftg>w9L-B7n*{2~hd2 z7pR;PgNnWWB2|&LrUfljc|y#WeNq*jz8-68KSv$I9rW!4T5MzA7UA2`a54M4g#I4W z97KDxmAw39x!UwdM0AEd5fLkCOAd+W^Jepr z<{!H%Z;iPVgiQTNKWFa^PC_>Q$iUHioP=!pAqb_m`@Ff4KI$Ubvj!Zy+(?{J(^B=o z0`mo(FBzI9^5EPInE*Nrq+6&wINx*0+sepyc+E_uO$W7~ISJX6RuJ;(hO0L?j3H|` z6od>=%a#XcyNkZw(#HkEPC<>5k&r&k>Lcw7T-^Fd+b7WY3MV03pm7HMxyeb$26}>! z5om1PO*QEx*F%^wuSH(~vmkkJ?sPI|+sSYkZ+n_dN1cRh=pqRD==<+G3E8wm5HisP zGf8G5rAJ*Sa(}_{M`Jl@`Itkg(B?Cua zb`tW?AAfXt$VsjTbm8pwg)aT)!CAi1HO$+fWij6NgqBTCLN;g-gnXc7hm(*^H3XqP zpyfOl{o@WTyICt`fR+r>o^Ww%g%&}`2U>1(60$){2981}ArJlWhn6Eway>u`XSXkC z*_7r|PILUMln+WLjJlxQfxqqK(griXiMKsr=A}+THkc8Fd|>9!orG*^A_(;XGw*fL zKkhK|PS#2pU?zjK?{{%)g&9G}2WB2{60*Te29AE{B;=t#{xGv-lWUys0cJS6eZkBz z%5HP2lU*C$oP@VM@#ZWiAsgNZLOytNfs>F;Uj!i&Z{TFM&6w!6Lhx%`^n1q}BGki- z=?d0L8So~9w5MF$TJc5@^1+*ilaLK>GH`T{laPo0_~XqBoaB1I8_sTDc(dKU^qpql z3?*NYhEDel)m>iYn6k;>=f_glsq?2>Ia5cb$Z6dLjrJI5S9_MG@63;bu5J zQYV>mbkT_pbD(Fy>DlY^Q{G-aV%+Siy%j(NAu}*EJ(~FpCn1|+WZ-CzlaNg@1fkSu z=0uFvlU;;*Zg@th2dkG?-ozejj8=yJc8iN!tD*=(J|oSHlaOts$-q(DNyw%sf{-!N zIJ|wo<|Np|c*E;qwz;l&sX^xM$3?2ydAB!x0qIm_I?`zLSv~BEOYLII*uFY#S?`Zs zGShjrgjq*RYLj7yJAEn;;qsPy69Gojkmhk2yN&m2&GCa zW&8ApT*N$O7S1j~u39>pT#78Q9lZyLN|o72EVB_!X7{_;@R6C%82Ere=y#ud0(R@+ zzhFD|NGHs88zN+Er5_qpQ;7YdwG!XXirw{#4rr}3aFWCP@n|JC9Et4B^TClSAUp>f zP!=M4^R+04XKy|O9ES8$W^dk*+;D29aF&}uu}A+rwHpRNVNc=w)|(0kS;{84O_a7< z&*BFz62UmLg^|OVl3R#$--E5gwOpamD9kn4M(skmik-@|^}5NjHWzE{YO9%>oXgQp z?6KTa>aB9ETBuZz#Hj(Jw>dafXcZ{`6yKMfE8x8x4iL{xl`7@ga*L8v6(%dl)Yniu zuz4B{XvL$p{%V%A%caYDmqc0t%K7l<+dmDxe5_)0ff6ELs7mxog2xgfU!cDfKAwJU z-@hC+8jDSfAE>RqJQoltpRw6@kcU5XWm!wlKuKq=cI69_5u#l;v;+lR>qpuq{gnPF)rb=DYWfAG8i-a+R%*qA`8(RR zR;i;Mj_|)Z)0*mP|C^=ofBEJ*!{{&v`si?!Z|)YnpR}11eKdSJ(by)tDZOQOQ>Bn6 z9G0HOQF}@%h!TFqOj6cw+ zW`y&T%~~fj;+>ahj1}?-9Cu5c6t{$G-;{GNLXp8rGwIQq($?4OLofSeuzD-R!82IB zjlQuAR_t5G3|6Yz(ORU}E*D3qONCY&2ev4oh&ws$&Q8qdG%fum=K67Rq43A_Yy1Ai zw$21N!S{~_{~r8D@Pm7U z9|k`P{_|+?Uq^!<!xz(mQR(`59-R#`mi8dHltAGo38Kq6fKbGT1d5T?MK^OV= z;qd*WB=5l=18F9rSk))m(Ez;ww-zgwzj8GE9Nsw^exClegVXQs46{P#OLi z{ULN|B=Vm8smAvujro_eg z=>g-h0ZEmWzriS<%@I2L7e$+sWr;fwc6ka($bfxl>u6Q6R;i$+(WcE#wBj;x{XVp9 zaR2_L&F6G(=tOHV5Hw49v~9C6gO&gq!1i3*oNKm9v+}ZLenO9Ne7H8}dGbDJK($O% zkbfCT@{yt$xuVOh0P_({$tNp?>OtJ8mM+Y-tED4ICrxwnHm3VirD`jlk@sDWg6^NA zNn>>IgYK>2Pe>0E9yHw=h?Z4Khf0;s{>9N!Qd&s#>6hFvarMNNooFes*V(^Wfy_nF zO-kkWFjZwMQ`NXeA>9OCZGxBO5!{#4$1c&1?nBW3D9_Tjatl5U@(1Ur>+H?# zP^0*cSde>MZy~L)dXEwdYYwulC-)$_lkk#FbgV-bVgW9a0$h6a#1&8JD525m22z&G zH0f!{Wig70GZ5$~BCGWJRw%JR-FG=kF(2QHbkB20Hs1{CbhKer28o|uvHiT z8+!6=FR}|=vZKM%DLe9wN&Q={$&LnHg@Ve1W|!TGPgSD^A2Zmn9OK=*_f@~Uw-;GF z$03Wj-z|}Nw(Rm7Zg>jD)L4mhK@7PBvCgGL7hXyZA!G!FnbPYh+gBM%ps(yjpfC3o zs0+wQtPW|y?6qsvamBIs_9Cu#ImE@x*Gzr!Bu!}ZO{z=LhE}6cZBEx3vH8br(N*zf zHjh{(PV2~5YBMy27@R5 z8#PLZE@$rDHpZ}44FuV zh0S*wCOX0Cu&Xf}H;m2|s6zv%nvh){F2~d-+9ONOi=unX;hZd{JBPC&AuiT%m6pqv z*L^q~(ym1xNR~US)Oz8^7xU^?^megj38tPGuu9-Uv|+q1_BCfnySqrOrjIM2!1{Cq)jtFM0em*ultam##$*6 zL}UxK=0Z>|-Q@6<2c#6rm{HYZ4SuQbJ74w01{P0qj3>(eGU=sUAHW3~>n)dXt?F85g78AnUv(0)sjDF5qpmM> z60)hQAk>Gt{;`YxaaY$rVy%=xT{B4gT`q2|TYv;1pDjRt?<8c~0+fNH&pHWt=#Q}l zXwe?o3-L{Ly?=2M>S5~-XS6S**%sqRn)@dWan=}bNM;jP72`j5GH#m5x>Y{(#F=rQQlw7Q~4ka0+eWiwM&Bi`X8+XDh|w);Y$v&TuurXzxofiXQM*|^MAk)FY(=Oi0X=I!Mp#;3b#Zv_uQ$aJWuC)p@D3E31Q z14m6KA)8_dLaF=N6F$mcaS`gd;d@Q8!7Fd#j@8=D(BEF<;?}Atf{@QB^J*s{+bENP zqqjN<*%U<(GDew29G+<(`fhE8{UIlz9>y3>-)w7L;Zj%Q+>eXo8uPA`8_6}+nukoY zu_@iXpOOmV8!oBn+*s0Qbgzi^p9e{SM2?tPg+Xc;m;6&v=Dp$Pr@<; z-}}FGJHFA+c<+BQe!|@QFM}Nr4RwNAUBR&4z4t$uFG7hz%EV?Ptqg=|%ffrvY_yRW z`8jRs*hJshW+V2^w%Lfq*NC_-5e25C9mO#wqatid+in!!LuvsYbXEuw8;)4vr-nR+ zC;UFej(Kl5qNgFIU#Ja7jDusf;VAqV0yHPWf56`Zo$wR*xVsa6l7IX&|M)cj_$>d} zMy-4b{xrics4GXCd;<{OVBvbK%Y@Xm+ToY^b6@2jU&jYXeUpDYz(2mlKfcXB9^xP0 z#mD|d;rHm{gz)?L2!DV-cLSVn=!E};uPEm;Xfb@;kB^D)bNt5_=m!EDNd?eFUY;?q zaoN7huf5`G>GKf3l*8k4@QA{nOdsAMjF;*!MYkjZ!uItW!iYo~)8&N=Tzo7m&m&s# zq?Eui_HK8Gq9Fm#5XGDS0O2#dE-Ls*geKB{t7Z+Gp~P?6R+^{yP4PR9@6<11hg0z& zZGBP~b5F`m)T*VC+)SY^u0FMj9a6)Ho*T(sS*n7@m4$k9SNx!syn)e*Z_E_2qpLwX z_IPFn+_z%i^=R3Jv?w@iayAWlzLBftFqoh(t`wdfK+$}{*=;&^Ub({;jyHb z6Lk_jZNWn?dC&8Rx8x6s&XE#XxlG)mEqhxc@k@#4h|X5Jc+MyBJZ?Vm45x@EJWQo_ z$57sUH~QWG^|=4W9w$22u?rG?flHsPQ_tt)ZBL)li=BjQt^+~H#~Jb(Cn4L6P!KYF zO4))$-{qpOgI1;~QLjOwZ)2^L!EeolpiFT`kmz$+`DT#lT60_$dTfYwAbvy+4cZlj zcwceJ)2g9g;B_;dTj^oU|K=oQ(@;UkM?-(&BxKW2LC6qgHVs{SS_aGYxM=7gYLuL+ zdo*i*8fsdKsTvwT5^JcsqBQgzmprYkj4|H5;+`&c60&KiAmpQ=6HY=l4Hbm?(9qjm z^p87+-o{!f1BP-T^rfL2Q|2ydYP!~ZPU>p%vQpSzcZt`ku=g-gcq#1fI0@MlRuJ-0 z*q1p8*%Vd~>O*1Q_Cz|n`Cggg|_AF}?*Nv;RT;_UVXStri3 ze2@lFtF&h&N*UKwhxv|^T^mq6h_^j~>R~4#8&C;CK0vkdbccyz?E!+20aV$%C8xOP z_Y6V3`t!D+Mwv{c4AMT&#jTIDeemW|Cm|c&WZ>v}Cm|c&2txjN^9(1s9`J_OqCdQu zXH_x{ZwA$~5^nTM3T+NMnYE!!6K{K>&2yZDY-l40`Jl~xPC_5x!Fm`1~?fwnsyTMP$7T7 zX*tRD063i8z5wTx`J<@PFlUwaxC9;JnnIo5baHG%ouhc$6LntXBxFM!LC6PnUhO1g zQyD?XKpnQ-VSXzovF+lWF8V!VPOsZ8-pX1jgN>6x+MjZ9YlR#^$Om%1?j&S`oD3X& z-$}?re+PY_o=FreO~|r@;*BlzgY%QX)9%jDGB& zO?cZAi5}}DWJ4lB$Onnea}u&?k|1Ot(J~et%jB6p;}Q=jsb1l#L(ga=NcG@UzLd39 z20Y3j^V?ngTJcB_^1-93laLLMGH`U4laPlN8F;kl9N8oBO{vQBorHS8AkJuC7<8P{ z9K6EGzRePPDc<(PpEo)Q+3-gY^1+|?Itke{M-VdbCz~bok1qN>V^6P^(8pLSWk8+` z(*CxKTPyMiLO#gzV<#aS@?_v>#baC}vWNZ{$TM%6gUwD-Jzx)KwJ+=$N^UbrGkI2s zha{@TzZJHQIr+1J%UO8a6I`C?BxC~@LC6POu5l8wDTg4`2e{nkqJP}MJj+2mw{utmgPyV=*fi+z$ltWj$*K)*F2>uQaC3u`kPU7GAs@K8-ATx%D}s;#H#o{d zN?SDik)PC_=d$iUGbI|ONwA0UhS$Svb6xXfs-cUQ!dloG@(r`@$3-3|Bb9-^SKr9vG?bc{ zA>9Ms{j3tu#>YA=8lACByFKM{bnbm0pOX^^za*{b0pbwL3Loi18?o>|0+TqPtT#}n^SJ_ExxmJKIAV}!J zPaJOIcL_O0a9-F{4QKq#(TQJ|1r4M*DHp1>9L^vvR0fC7*}dlpyW*ob7pgd=KTpV_ zKa^x?G}!hFoSy^D^Eky(dor*bg*bS9fij}tDDS4kAN`V&(SB8;f9{~G^q0ab>DTuC zbf)qz;c#m6bi(2AY1*~u`a}*7RH_x=>^^oZT)hU9i_V8@)p9udyD*DW;wq&a9rA>u ztLVn{mk%N-`wShf2yH7&HM#Z-hqviOQqL|!3X`tuN({H_9Hk{Q(K|M!ExQ#2k*G}Y zz5;D?8;XDk?$T<~btw163&Ji~>AxVw`yCm1r*5J%US*7%liH-X?j&(Z87ag|rgI?4 zKDA4-w{XcCigZJqvVmnhGW3Y4&)5u0l+>j{wQ6N9Ctd~!6@x}?mZxnJR=%N1X~`oX z{^VsP%-_l=%!DEhLP)>C*|jRtWx68u!!MXwkg}8nUY1b;x;hd2FJbI^sS}q}7Ih*5 zq)sAT8v3iDRjoLw!aQ1a>E-*nGzvNC4^HOj%^c3q1TKkVTnB{)V(cphwQ{jEmb=Ux z0(0$VshLaFJF_AZ!`CJ*E2+OnG3ABh3B6kbxx9l3-VR_>U3zy6BqF&zKE#v^Kb}#B zy5^DqKgtB?rMXb!QB#y&%wfaD5VraG6l&C3L`_RcJ?VFDo8LGxDhG%?2=d z7Guy0A-F8E=nYBGqBjrA-Q}qoQ^-M(=bg<5x5EJrBF~iy#UKZZywo^UsN~8`*yKez zQ5@+f8>K;vbgfc_eILtRlAA0|iGi_D#Sa?UrgCSU#jLIJ^jT-I8R2xT-GI42T`pCo z25GEhB&f_eSoz3P*{s*9Q}GNymY>6uiZW_4SSd_aQ2q}2#1497hk9lNqj0m1w3p>W zrOI5Yrmr!?A$2@)Rki&7j4hu)xGiX#D?POPI|=RnU(hV*mZ<~%LMx*dI(J)lV+I4! za!f;O)tSzH9XW-KR%se6Rb++GX|25J?(*z?e2QMcbcksL1n_Ieq{P-jRtlB?BQNS}+z z9_w6~E%8Tkt>&RrXgFp5BBT=79#L|9K~}vmy$UCR)8{i$+Kuv!^YI1EO1-CQ_|l9u z)LZ&wRPV+9EzLQ}($d7grKNAtw#~4-!h<&=YcaVRtF`JVWhkx`>UA1T_=E6D)-cTA zdXC#dW4V2$=|a2Gq9Nsc_$y}$lLgGkQk7yTNlmIk_YEc9cV`rDV$|3Q0leKq0j^q5 z#-TL}SD=!`KV+1Ju4*KRkNB$^msu87BLWsxdq?YbP3w%i1d_f)A4^9G*q!$BFg z6Vxq!j{!V)e!{V-YhLc0RDC-=epSo1ZIF}-=<%d#h3{l+g@i_KgPb1p(8wqDEe>d5 ze}yQXf0~hJUGuhs;fMV-kIN>D=8;4#ns=oh(W@ONOdKnn0h^!S)p% z3Ui{3L+Hi4_f<`A%~(^t`FEh2H~Tj~=O|0_lN>C~f5ZqFgV|3v1JlE^ccvl?V&@r99toJ#V7Cj~c zh928rzJ4W}HK(mUPv|E_MT2#<`px1gXgM-*HE~9hwz95PH?gE`uaP*sN{gDn%QBoI z`SNhIxIWj3R?47>j&W#6c-JC?YP=KT=7(3ki@veLtJpW&;Z^M5pRFM~&qkd86F$5o zxe`C`DO}MC^1zi#&CY?&aJU?SLD3!-C6ZUkmpo41IV0tym1HrFLwKUM9GAmUG`_}s z&q>kW>E>!X^e>>hjk`6Ib9&h#P7ep2p&kz5S21objFc$XN_7wSNqPeUcG=S&TUUI*fQQZMJx z+vfWhq0x8g4Lp==U^%*V-%tqsOHJ5L|&eWnkFMJJ(_<0v0R2~im2HC z;F@A+@x~Mo7TRvee;IpDDzW&bgnXS#$W}hCW{i8O@U2clHWe0xd{nsXBxF-zLC6$g z=Cm1iy6Vug>h_*C<1lM0(*fYqxIQxfT^GOB=zAe^pXmEnI0@OJ?=xu88=Ztaw8)6Q zUrJ_@?1%h^>W1%ilItP%p0nE*%B<3?x-@iITy9C0=&NGrvrdL=JG%ZEZ+i}n|KcQM z!xcfuN5_BQBxKVFLCCwCH5ghA(-%?TIgU zI0@PCMG*4AmuEW(+4MsYGVmqq2KC=|)u3mD>3PfGZ?cBUV6F@TLwSnB-jJgaE3ENjr(!2WpF;XgeoBXD5hHrvF+^vl*6~Z z{Rnaj>8ITGwjt@6F?Ya8ZwdU-AIDp2cR=?JIBf&mrB{_Ibu7Y4hc4FmvG(689K^y3 zcV^_Ka5gntO2Kmoc${tKuDmQ)m>z6%(ulEJRUiMEZ$KO>|%p8{fizAjaV_ zf((AF-cQ;ai8n*x0oSAk54aR(FCOrXXQSzUK7c=)=o|BZvv1xWaKQ<=WEaE>uF`+^ zom>$yM&@kfGB_5Zu?Ygc+dxJ}~R=3Xt-uASOZ+8;1 z*~Ws9k8NCa60#XKf{-Cr&Eq_OYHsZzCEa^mbMbXSL-`PC_=d7KD7%`h8A9HnkRn z47JWW<@=yvV5b}YVAtxal)MVgjyOWTI3T1(s5huYOpoTM?5o+9z3pe(B zZVy#J_!!ur3*pAT2<31$_H~d`NIw&9Y~|oF-PqC_0~hXNl|c-|N^xVKc6VnuIQ>8; zIp?GlOv0(Fl>w)&EW8(|?rp>fbLt+TZ_KI7zIi)!xyMRLJ6gtEWgQjX9bZU9cC+Z{ zQ$zN#ExeHu+-={#*yh*9PH-eDD3&_xY4VRR3SKo4{MkhC>fm)E!gt+7@cN114HLl| zCxSOk1aA)hGI$Go=YNHNZ=DF1 z4n7ckF!)gLH~9Q;@VCL=1%DrWB=~6Xv5DZ*6TxQ?Jp9?<{@`;H!RIG}FH8hqoCv-& z5qx|;2brUot2pV!m!%j@u`9ezQ(d6eBa+73>K z#_=a9Qk^9`3@Irhdncr*ezp=6(uxu5Od)l;cKBsZ@T>ge>-a#`zR5ox;2+=OAK&I5 z5Al!h;$#1!@O$)eLil}rgg?NayRmeCLnr(%d__5*IhlRjkB^D)bNt5_=!aSZdKp6L zgT-cKw>9_P<<+Ut>uRm?w937wT~hO&7eHztb1!{}xP5cT(g#jbL&^;E8~RJpfkeRk zzFM)(_V0{eS#Dj`o*ciTjE(Q5n-CR#u-qD-sui2#dHiJ$6=+-hc%fd-$H{}nOVz1a zR`sz)6QM?|r}VjuayFP};<%zwx}%vJE>;T7CPLSd2ZZX@;&r2__nBRtDCO#yQ9$?V zi6Ii-)swPO=cYJM6OY?rD>TZbCluS$ir5-K1Rb%AwE=H{FDF~&CZ5bQbG*XwlNcqZa7M7DCGeN3{Egu;qb&IR|Jxgi{ z27gUXGcH0s%ZU+MC@GD^`ZS_d{!UlreWc`r4@aGZZ1`YRT)t04f$Q(PNcG$xy>A0a zRa|bnVeDOWKx>lMx~lKfB<6x^I-$2O03kIMCl7+hsAayOw}dnd#qO(z_#kJD*2}q} zoi+?FIvDHsK~0#Saq?*M^!^jx?gHlYy@KC#60&)E1tFh~^dC+_wvHqS83S#$4H3)6 z9TtV&rnaH9Ygp)YL&PG~DCx+tY9bdxUz#}o@wVsePE*hIT~kA;t|@mElLbg?k3>^KYlaPo07^@VEMUTZeOkY*!dy$h=59<@0)r{EVeq5|i%s0nY1%$80 zxVjMQ6JJF+e0}0wkW)xM#rg#MP74U@FtNvyf%HSb+w)pHC48M2SG(6E^n+!>%b16d zMbkH1$cTZ&`pPp$InUsp8D-9#+`&;e?u^?=Tr?<-3~7opXjo1(q&X_r+Z7}@LYzLb z8B=I}9Djd2Nh&>ize~?_NFoO?9Z>UV@|2KquDOGhW~;#c$>sxP zVl&EqpY+Kf`lLlFrg}duJu@ynd8|W7&eX@Jtf5zyJH~r(|$UwM{B;Nct2?~CmUVl zX67xeMv%0nVsToJM&PTwot~!a$CiWWG*}RcGxRdp=F4M=jDzz`=g!Q?c0zFnphu@O z&P~OQXFzC7_FW13+^iIZx)K>rbzLj-_G;olMUt0Qo%Us{6U*i%+J=t4xrB+pv^eK! zd@ijljZZSB##h6J*q3}{dr9%s%*d0jNUOn6-CvP7?^zUy zBxWd*{bi9BFl~hIe-Ge=(>U*forOZ1|I{iZ))m=`wYfH(<7?ae-WNUm9`^EaN9+j(1S z=SVKVxqBt-4CL$EyLaVAFUmbDg-_V%a>3Q8ljyf^#)Lq|R74jfR=>Fbv#f!yVv^_Y zX*0P$>(=wo$64`)?)Oa8v`(LiYKE2YSL(!~H#|C4!j)=ues?KF58=PGHRl0M!})r% zc0~cwhjbaF8K$0D@C;doAEZ)KwkO_vta^h`Zo_xIxr-R}IPs+6&>D!Jl=!Y)QL_5H zOIB9j;Ail*r)&FLPC_={pdjSa-Tu=_$mZJ-gbYz4NpS-pr%5_>?K82WH?Su*U);uZ zHWxQ79a>iOLh_|VD-oK)gLz_C%H8Bj*%~fG&CqH-!rbO!!irsjkhzSMev13qPC_>I z$iUGPoP=!ZAqb_m|5BzPs%u^8qNH2PnG|4kT^nxu*96lf^62p93pyK#<+p$0_+UWT zmUP=a4Z~7aHH1$f<&F~kL6_jIEY9Fnx51% zF@ODkF8aC-WKv~Ds1GdrUDjF&d&;)%!G+P62Cqxlv1zKi1kcEUmwi|2`EHjmt?K!9 z#<16N+((>*Z0acp`KagpPC_>I6ogFmq#=&_`aJ4Mx0OV{?V{hidiFWgKEPTlgL-C= z`m%Ez28MNP7KD73 zx#;(fGDN74L9oGED+9`8kopT!J*-c=S15$+d|l`nl?P3lw6pDXaWwXX1MO zrErLTZQs8XO7lzFQm{N2$5VW0zjjG-q={J>-g>;At6{JrhNMH6sdwITHolgk$mXSt*LeWFmvbWFib|*4T%~ zkSmL%=M);oJimvP#IDL%f3{vI#I+pax|}g!T02Q0i>L!GSp}k&r~|D%c5n$9YIQc| z^IW0S0`TBIfjbR;L_OPvI*&G4`~lM$<&n@Jildq2H8wP84Vq8YRZbKVS5>RDverUq z6_NJTsuOMUf+Ed(U)AzC8EdKQ&PoXCSDB!^bcf3{i|$ZM>`)a%Co@#&8a`#?(JQKD z2GxnA6?TpyK&d=aMW`a3{@cP)!1Nvq3Bz{=SE=y|atbIwL;h5K_#)oo?kvCmCNxbi6 z;`P!_-V#}~lL#2vX@6NnLZl7Eh=fq@BGhSWk4l{p?Cd%nao2$knMFijvo1ti(y$)> zHc~Xx323%V2+MCMwc3rUY$*9t3ICz2!Y4c9U-g%yov{Wr8H?iyPKjeSo9McR$tx>k zdqh?65uKKYrJ!raTC=W311xWF$;9bPSR1ITF8QyC<*!;bZJ-pHTr?vdZ78jKy+-u1 zIG}R5h@wb2p7NCQ5b(|NxNN0wERPHOX3OKk@>^^TSvbqW98Y-(i~Y_|m5~|@8~^9> zO*%KxD?ld>&3RnPq|#87u~Z_CFrDaKkCNz(d6@G%$kGgYN*5Gb1A#&6B(GufsKm|l zRDg$w%yU=u%k!ar*3>DU;UatVavt@K$4;a)k}535yq*~s^QC)|J`LeZGUO3nM$+No zGlnlo?1rU+)15@(0o7hN=yG=9Xr{$T_s(2bXvGBTmci{apNJF?hi9Y21#_DHxhmb(cXd4arsK{83^>NN)VhhAU055dyBYTlIE} zg;>uMnw$vTkjGl@(z6FGmsQ~gg#4*G#h)vsPVW?+7Q?Ica-v6FLv@=7doniwvnYnm za|ljMDTT$>k&%!%Vq=x|telP+*Ho*0P?vU^-C&Koc^}@!$YjPcre|^Zq?3?sMO+Z_ zSrPw=laOsCQxGy%#Cr>M{dZSAboXo~i_De0#$}KF8*eoqVJ<)4F%7UTbPGbJdZdTC zZgLW`sYeEmb~p*y)I$*R3U%G>qSUhjELf;3XGa;<wi7o_5`d+Cn1|g3PL`8tnMUa(?~(c0IYbOEPe8rSUUSv7k#~fk1J3; zi?x>N`t@mEAF03C#kCdLgw%aPcwXZqWDDWRphs_W67tX^BZS8qDEK!{ay0j9G+@&ISS zpAtJf*|E!6aQgLF!$$gp?%W<&WC4FPlV)o5{TFm({SAhoWg+>7marivU#h~y(EPE6JZ4pAt z;sH*?j`C&M79q40FepRjhM7kiBByc68pNrwFt)|QVBb81!7@cJ%o@aQsr}8XtB~NK zLdBWd`b>*=K$X(%8|W#&b>zkjzpfGS?e@TfA%75^0Wp`&td&`7bDgLw}Mcr*t&99f7nIJ zS7u$wN_)>?ok3EccU6DkB=s#9sb3UHrRTB!sjK=vlJWtGRgdp7Lo%2XHsxJP=9abx zB*%>UA6aV5Ys1{PUyk~Af%?&PTwMjdGiIm zA*5X(e2X>cCB`|!x0pSP^({^wZ94*=inl$-+8HMy+gK|I`E;YUlaOt!6@-kjHruxN z=eg+XZE71#y9Nf=w)pw_)~~TvN??h*S^Lt&>O~qF+!FVm-z1>O3roMuZ zkNSStNyw(Yf>0mod%uhRaaZ3@u~y2Uz8R$bA1-dKUT{Ik#|ysb0@vVf^MYsKXq}Ug zhyEB|@OiUXZ*!9B!2`}&&4@kj$At%czR9#IARNWG+K&f3SkCrShDDUao!u8fPVA@5 zVokTm_7PdErRxEc{c+r}IkELD)^}&kV%^Nu5YIf=Zk8IO&3dU=o-QN8EuNDjW^GDt zhO;HM9yAhL|2Nk{c?~XeX`>EY!u$T{^P@pWE>?`%cSm5CW9)tx8-VmnN_0besdy@9VKWp_}OyvuMG(EzmD(tL6W>~(xm}PXA>9KKK zBg$plu4L8IcZbTm@wuF-{;g1#T$%$jA#S@V27atkJ_Bw-%vbx4Vekm zqXG0QOzw6p&6a*!s7kh%lp_5wBTu>_(O$%VXAF5M66ZaOB9X)lMY6vvcB-ZsDgB4; zpHGH?BXD1>e~L3=9ND_n^GLl?x}$rM-eBcXki@x*A-@>@iSG4QCJ=UjHjCe9`~E8B zX6sgQK~vss7`S96XF?IddKz*a zTFV?HJeqfYv`;LH>`f_OXI4Hg970An4WB?_<3S+Ce$?TNaFg0ZOQ{fT748p@SsQUm zeKgYVF(D?pRQi(pU%0riuEq&Msq$LJa9tDFyIiF7cD5;XSD3sZ>rcHLSX6JT+o z?cA<7-^4FgrPTcI%`R2dyS7-m3(ug&fUS;pd4qc2bK{KGl5oq)CQgRqyYp53Jt*^h z5+9*&Y~u|3=CN0VIdrxOKKge`T^yf-=F0_Q< zq~bIAaFynJk=a>?v}@6?r@DOPsd#bfR_1u{J4bG0=P&lDaobYjt49z{D&bPY|}(xGLo79Ml$ibADD7dmDFo}NHMj^PPZ zDzB8WfdlE{^z##a^<4NjjVREyW>Ml1!<(dKEsjMX>1#9Y6I~*(dTuu2ZBNJCnNC7B z$DAPKGrc?4NyyfN1R+C|Y_?58^xABGxr@HuA#Fa41)q#x!dfcwUZ(U%6V)pJLU@Kc2nOCOdj-|uwE(yEM;BfS;_uVva`!TS)4fo2r$X)t#+ez0{aSy()8fxX~yz>or8jLbOe4H_0)uB*?q;tty`)nve(zW(@9hZ<1 zj(knmG35MUp26!bx&D_3#g%v!?RNX+J5SImiE5R*FLTh>WN5oztU8QQ2Nz zRnlDdB-D}TiSt9MQNaLjqL`@Ly!TZtugzFX9o$Gz zS2IC*fg6|U|7Y(_;N&W*{qcmXOag>J0wEBZ1k6MylRZFK6cRQEnjKMyu`|<|+cz`Q zLw8R?5DA0i#1V!I-0mKyq+1&9d`cMQ#abG}DpCB&$&#C2B)$Qs!Rku6C z(r@ps!oMq2niS%au*gmcHFr9_R;T4*Ea>Ri*KDgEu0soZt=R$bJ}g})CHPs1 z;N4IVmn~?^J?K2S4%C~11|1z7zaHekgX1^gI~E*g@4SQKB7*$PBz4a)k03|QuA8Y( z!)rX?z~(4sg`Wyx=K4{Cebr5Hmxq5?Jh{VZsb4@`5TMR%d~$aRp(Z@}9osm=;#iP! z*Rt`qZ~?=#q(%JTM)Fyy=NYm6yk1XzH|@5@;~V4pB8LCgWo}cN&QQp=p)@Ra zd;)bpB?-AgA%c)kDC9|!kjsTF2pOS}Y!@+1IzF){X@hr6L(b3gUh@&=0TdI?2!|kK z!oz+M!x1DQ7d!$uT166a!9x(T9-NrW?nO~*@dS#J?z{*Bfd54dgcqK(V_GL31Kup4 zvmxE~V)McM9BIZjnHDc%C{j{&w!Z+SJr!1!B;-P*AmlT~t|ke&5Ge>53M*`H%v&k? zdItyLl(nOU^H6VMy=AV~e7e_1>K~)Hc4{^ub)VSnZ6qOA>^1;LUnL27;K+#GIxk}Q z9!V}k^p>+5s9)&EMfBD%Fyn8ap}@8TstV#;;mbBf5f5r^n~NCY(;z~73^B2?WdzX{ zl9Y!25*GgvS*;{ju%P`6GU#_T!|In*N;Qbt!BvgSv05zjM#;{3jK39fu#{T{|N1M1 z;YbU-fnzXRVKq@sd|}c~+ENmcp!n0G_khoTDkM@KLb24=Bm+xrDYEdT_JPoHzSN$F z@7PkCz4Kmb3qD%khkmm4;@u33?_)d{-{o3qOZuv2YAJr#ZnYG*bLh7)Pwqt24!Jbz zA-GSOA9Q936+}9BcEj>Ue#WT1cPy`>hMVVdeVJZQ{eMN*HZI;nFIqN)5}$w~;=9g` z4MOv%{@G`JibDa$}BKC zc|4V%AwXiUqu6Ml#6~Gn<4t1r^U@!t*zl2<&#L0nBq5g#?gTTN5VV~N_fn*?cMT`i z!otl8X8U>B?^A5}bdBj@vJ?768wja|LV9nFbbN^Yip{10RYAN2+S8_$MyGA1VYOcP zN! zcQ({IZBKwr@D`32V26VV1bshMmG@kyX=s6UnuJmKIxPp3`8w?|e8<*l?4AEQjq}m^ zI_*ff&^%jIw99W{#_K0mVj{vzo)Iov2E1SZx0i~u!E~e%_h@axqw(ucqdEoT`i-uy+I^27fIyX2&dsgZk<2$8zuBU|T zgza^_p{DI>hwaTIAs1`~As^V@NfL6wRuD2^n=N?$ZK@s58GP^Oz2+m#pHoaYLrj8@ z2@iYl{7)ny7d!$uns@?X0s3%c_0^<<=lf8UG6SG(!E-J*Q!jZ8c(Z`chFn8B6xm$6 zAtk0`W8m$XJSw%A_KnhEt0+M`Sy~3AJ*VCiNJ1`<3PL`^?o5)9ONR+UhA1ba&B~-` zPd34SS28V7Ezo;CD5B0OwcwfA$T}=w_6-pHD=D^}+CdQV390WS3AsY*0UW)9B;)}l zGo+5|9yuT+Thcl$ZrQnmWXqNB4j`2k7D zg$qH*P%&X!c78|E&#YitweEk#dMiM`1W0}AiLF>4f{>4X*`Flj(k}rVEhGtf;K6hgsxeWS+vm2;i=*PvD9m6LRpNfWVddtoV__9robX#gl;acII^Rq#M z_8mLYEhRVX%x~^FGxqC9mcT!{N}2Ii-?)C>f7N+~twoh=5))mjyXDa1!?Im&=ev4f z|IUdgZAkJ_W-6;t^fC%Xy7G|+w|7@>8g$D`6u)gcwLPF}v^y-*62zlaCB0A_;im;X zlL08?sqJpfqrp739VbKH1l-ld@R6Vh?^~;ttyiqgN>?FOOyds&5YC=-ebXEvgH)8woDh+mfq+NeU;cF{8%z zQWd=NLT#{=AJvW|y2eU$=Qb3#6d*rt4zhNzk_-x|BiHkqwnqZT@r3G&n*#eHg&;it z|4}Y2CxQxNBO^fJ7*JBuyDLz7I+9UzcQDa;A(=}#1j$GMk*qeT8h}1QMus#bpIaP; zn>A|?>_te{3Xo!@J9i%Bwt;8y2S^IAc}K2~!_%t9W;fO<@o4)=iSkj^QZJ320wSI- zf0#+rt;)JHun4FMEvESTLm*!|MDSGp#b)okqu3(s+uFh2W4T4lHiBo^ zU%VnDjLnF&DVAMpYLRnRc14`j8ql7h2~esZ<2yAzkAaSMZn^LbZ6B%EQ~%8F7ups; z*iGZx=jh_MS;9^ydmc)Adca;m5^{OK1R);}*bqs`<+%`qTJV5fMbXzy?jRR?s~)h+ zS#OzBqDS{OpW9Mlp%=6I$0WXe10`f9U+?D)H3OLT`1UO%As1`~As^U&ktF1TtsrE; zHd}oA0jeF(8GOIVd(B6fzo3|K#(M-I6CU>X_Mb^YE_eiRw8sWwy7l46E51F8qLdi` zZHsSnxtV&&W5AmQbT&K`S^MMLt0_S{Sy~RIJ*VCiNkT4=3PL`^?ktj!ONR+Uh7Jpj zZ*Qhrp!a&vciAgVLTV=6;fpOT`F6J}Ty6l8_4*f{>wN!s6SHQ}i<{ zm{zU(U$fo{&@TZ}pLS9!)`uYEqhIEbgk1V1fTKkuArBmx`o$IBUO|$}pkFw}EfEevTZo^9@Bi%W|uV#e1C5PbJU9GHo z(0`3b!SrzVQGwxZnW!R(d1tRcIpZ#(;H7IN8Tj6RP6#X7lHG0KTB8+~= zdZD<4pT>Fg`_+1jZ9cygT4cyb@P^UvE1?P)8qU}y5!V*Ub&01G#@`y)Y8DU@O~&Z= zn^}|1`7zC?h<FG#D(cQ^J=Y?c0Z?d7+at!w3vd( zlYxBc5W(p86O1V@h;aTxAc9geAmT18qTjZ8vLX6?lyCG~oBSbiEoa@Z=(lF(K^@Zm z3y*#;JXuD+7vVb={bujRHu{a{w`Y12g-&coWcw(+p55-yHWQI0sC`=7dPnTeGfryn zqT{gV>Rn;8c%82HGoiGnAFMzUa{0joAs;_jnIz=$UkE~mA1qtA@M@|Zx``d+aBtNg zb_MS>A7Q?YV#4V@7leGmh1ZjWT<{3s=w_0T3m$@ySGe#_ic)3(v@Kl7*)fe2j{$EM z(Ah|Z3wuBWpdSoH*8XtePbon=S$dSW(FCb|%fpi-As0vmA)jIQEJ?@(QbEYjVWHu| zeNQ2#dcD_!v{%dF!o8qr>0CrUJ?ta+7f@_F^_>vBk30Wpl90=t9{{CONJ1V^GTr&E zaN+qRxeV@n&TdOur^RsL5XqJ+To^-XPc!Lql8{Tq2tqzc|5uWb3m1Zrp<=?qh1XK_ zGb@-@&7*g+-ZDJ|PW=)f^-oh=JN1hoAG#W~xZZ z5;(usD8mI5o;yA`DDu}A1_qL}^>_nyU#?KCmU~O=aL|^@B_qY5UVhAxr?AhhFAt0i z4h7zR&DYd$@Mg={kk#BK9U$?P+a$gcZmyJfOvhK_HJ04zVq7vkyRo2BOZCa6z7@+& zuVDI?>7(^qrm-0i4xC$`il-*v+EwM)v9z!`yk(ShcRL;|{Wbv8X-cqd3Xm>WHF~+* zS%7q@UMTLuPYZgcz`z-|$AeGOTWoU|>9aNl1238mOdTS5!)W6PPzA8)3~v#k&(Hwr z1%a(*F$2*Z)1b-cvL>scm(FH~jEVp$=gv8Juz% zw44YUgRtdu5g>hSp!9Skqv&4EMCXNMF69s;BLPJ6?hzopUbWOqW2b?y*V`sem^cCd^I}lP%1q$yX2zWtR=6NSu!7<JRR=^X$wf3&C@4Dsav*Z6OVB>tXAg1z&Q#2c0Z z(L=al61R3_dS#{9Un&o6Dh~B+;(0ePeq0)YBpiJskcy@8Nc57?`r(b=b~n`17$;`U z=C^(&t*7#QU$_W_)lfGyaCoG)X$vHa5sAKg%R{wNzxYtC6)LrLxZHv~-nH_ucv~rM zsTMC$r5fYPTiKJ41AKKCq$DZy)=)G9*z@70zAQdly7X#cf zG%^Q%0Ohx@UQhi$#_j3u2850BK^-sA1-h^0F}|R+{Gx<;xGn^{FxQ|k*ESPor$w0Y zBCNGBK!4$M7%>0;@ZiJ4w#8tdlyJl|hLg8LJtGH<{*~(5byU|nU8-xLw5P}XRFaU( zV=f5!c+4*#3AsF-f{-E1Fpqge(buQappYEpG0)eh5ARsVC+s{fcCX;Wu8;MSX(4)a zt1?m23u&n%MK6D@u>Nyr6ELC6P~ zA0`R8fGG&I0L;%*^v4{SpJu%j08B1~mVgPngrsd{!{rqAvxKGiq)_=IN`_8U{($it z`=Ii7Bq0|n1tA|)K0^|6p;8bsQ3>W96QDh#_ayvTNp$9m2}3PADv^*QpLa8LIUQOQ zv~ht8p(RxAnOONYP)^2QB_{a?CBWsB0G*KRV$6C$@_3Sv3zCA64Sxe7~p0Bz4;zXj}GMovrVQGw@M8K@04De z-9y+R&Svior9BtIIg*eIfP#?Ekm@E0xd12#8G4DCZW#ISvg}?&(bxMmY$2S{vOAXb zQouACAnlh?+&UGQAmp=UEFuZHwu}XEw2dU>fgfYb*u>Sz&|9qyz1NV0GHe#(jJBjm z=Gr~zHl;FCe^fGQeyLQ=dr5v>yHwu=r9D;6f0Be;szwmh8bQcM)%=MhR963d`+II}IOoOw;-{WhI5Q-4}=YJRC${v^q=OXGY3N_%RYyGTMVjUx#8Xq^8d z3Aqp>2pJkD^sL`cs1{__IpkTtX3P5@vW^N+IspRz8^x|u=?FqTN@veADC5JWbOJa! zfF$GrAw%i#TP}s2lfLru2$Ea|wZqwMN$o6f?z(>U5c2UbzmX*50!9Ew*OG)>zz~G2J^uSk^BtR1ZL`k44bMxn*Yb-REz|OpJ>i;xCP8V>8E6hk$falm zAs^Mbh$Q5~k04~sKw*)DH57dv2xAgSSiyQJ!0-)__L&s7PW>YY`RJdGBq5jn3E*fe zNyq~~hW^=OWwO}Dw`%b1AW3D=J)G6nbdO^XyiNB^6VFSHlYCaJzJ+AfrDxsFwz5rID{UX(n%nB#-Qu}t^Up`{|F4cOc z0uh9KEZxUQLM~tgaP$X~kP8@skhSMiyAl6M5z5^0j8KLZ4sX1vdz_YTz<4|GOv+Mm ziB%BtnQ5L!5^~Kn0UWI+33+g2%rsNjF(s*n#V4gHP9zCtm~S}4W}oZ8v)a1!<08?C zaimE8+J(v}k3_RL!WPm~99 zh1`iJoYB>BF1+OU?a-x5p+sNtQg{%LFtThgm11qAG6WZwLp^I2=e90|>?OHQab+~z zXx_0Jzgd!lgPQz;^c=qg9n#1E1wd7#|C1Fu?tSyUd$6>GV|K(2G;@|CNWB-c{>c5FF*?5cM?hdirs`1+7>D09T@ zZs!^S{I5}bwkbEvyHt(xbg#L<({%?*4lmDmyIv@M8-7~QGYy6#nHwgrj_BpsvEL5d zU5%J#0}Y2%CE|V+>elg|#e?S$$_5kQGnJ}r&ynBLh%B6UFD8;Q%u^_nu@Zo~UR&0Fd7dw4eRe3T~_Bp?=h@J23E zBfHHSeoRjQG+!7jB0$BLFcsO0n8K>4IFh&la# z$vN=F;9o;23Jf9{PYiYji45T8UqDH&<1A>8nU=r_6CGKY;A0w;ciBk@7m+uKOE?5s z*e{5zCfR0=VCU@sU$CXOWBJm}g(}z-{JY+Axzbk}g8Xt;KoKYPIs=80f)i#|Ih@HQ zrP6Tgu~cdJUUkFTP>KRhNX8RR^V|{w{5YOaEj=Z$r8;2t0>Nxxf^lL@0*1>l1TZLh z2VfTBSvY~06#_3f3leB?9-%7+$|Hr9y`jYgCK7L~R6{8WtRNXrtQ_Ey4j`rJ?+Pcc z32dc~6Eu#lWJ0;T(1j;mpwOPRR`;oOA7l-=!%0;d1F?VTqZbNZPVPv2NtN+|;>%eJp80*PU>5Kf8!d#vWEIiI+WDb(O zV8T}ImHu^61mlb4*?tY zlml$5lYQn&39BJao~JL$+J69o+$;sKXCkfCQ|q6 z^*|?k0EOlcsJ6Z^u&uhHnF9?y*1zvLPa%Del5q6>nxxB;0}*=X7cTYg{DWOJ$=-KA zq(r(gP^78up9@UC)T{el46^QT_JC^ZP+(j2?mqw;y4An?IZq+okCJe7|0Vi%bDlX) z>;Cmo84}9nwnyL%1~+r9oEw3U;DXp*sPv)x8D^qtt~@jVPT~stO@0T@Ku{Q_EB?fm z+*v0%JZJ~IT9H7<`H99p1z1ttQT%IAYMFIwF-GxO)RGXU^GNMM^iLbP%?TQ8q3%ArEbiu6GVBfGIt-%%( z+eYAfw(|jMu-ZIhL{0VS7h34k`5yzxM(G1xe(NtW- zbw;z~7xk&KY?Ic$AnDYqN4DBSENM_x1#L=Gy9%;y zs!AL4(`xP%7OfhS+_P-&1?az#n#z{TG^1zo*;SByc6+(974FfH`Dj1eNX%Deld zp}sT9wbGW8VK`QqLgAf$k@`F1l8^PvQlyOVT!&U*$>*5#Rz5Cl{LV6 z$#hgj}!?gsl6oC$p52 zY9gO-E@1#=?)a8-*>N^ZJ>)UK%>sJ!Jrq~ATy}?3LUcAe2cw?!cL%_L($j!HEbHiO(Yqn(LC#=fN3;9+5;4~P6Z|i`J4;5j3neb7ZAYF zH6$Sq{21o~Cfak^y`3bK;XD9mv?WEdt8&?Wg5=kA2<<;NJ1X?F;q>{ zTy}?%q%tTQ&T31_W>@C2TSxNjQaEd&w5P&3l_ca+ID(Lm!nuGXVX}_A{)~Rp=As>bFW|ELg;RJB>K9Z0Jehh`<$Yu9Yl2`_n!l8{T~2tqz8=O-i~7i0t>L!hC_ z?EXZxAhXiRe8T?stfK<7PJqDoI-jyWJOu8eb>@?VTv{i9qa`FE4~`72L!7iek|dZx z^Kgb+(mcC1o!wa^*Dl?2I+XU*JufE-xpa>p@MT|2>Et=+tS(b#+z!$ z>7xx8Zx2%3I)Nex`Aj`OBMG^to&b*iND^`ZMG!Kk9-e5uTtgCa z;YScML>m@NIEA9G17S>p3F}!e1(?18(k@WkI`xkrpigk0bdgj!H84^Z^ST)BLc^-_Rx36S>hC~lp~MG*2)F3*sJT*@VYqv*`NkSP^3um+?)iS^RnKGA=th%(!3!t>8mN||j zAqlxqA_y5;CS#_|jZ{N2tDDSzyqEI+@)6@DRO_AULlE*=M8Aq83=asfjS zvM-{|Y$xxb2xad0teG--<4xV;Tto+qw@*>rI)Nex`OGu-kc3?GOaMpUCJDKKA_y7t z4B@|hlq8s8zTxdK`&`Ifl!)r93py{Yxt1};S- z_2wq+Od$uP%V3wpUgVdZVnOT2v2-9+EsD>QO?aO0!O`uFuNX5L9ui;!9NHubn ziSUH+o$A%Mhqgc<7s+}e_oP(*u@)o^KyFiQN&+_qN^?=`YYIt$6mwnP#bjiv(^SSV0n^mCs++zO+6n!{Hq~=qy16VnqQ8If^U~6?~Va~;OGJ$zPi_10yTG%57wA_V7dNkXr-As>msApm` z@;N2P+ggw#Cdbqot*4@5Dalr+Qe$-t7bIrL-GHWj!7?z|= za|uIFN?)I(5j~i zkhD7!+I)b%b9LmI3GD#Ap87|}Z6-8{K5ejBQ=;u>eURryv;L;k?DKU|*wn0Nk~Bl4 z@e-`HF-h8m$Fh;B^7gUeqWLtFQHD$Ifzsw~%ml;65>q<==SQJfxb3=RYcHbU;M_cM zER+T}i@Ev5o@^~o5^`;R5rllU^IS|4a_wmlgp6HL?BodAGxm^u>R`zbMPCmZ1O@6D zp$q}|nDvrr>w9!-bE92G>_xJ*qgef8l5FiQlyIGVy^%N62d?iY3Ax}Z2>HPE<0K&$ zTm>NmuGx~UeUWO%n8WsV-djFG{4Uja=gura$b^MG+1g_yAr~wHIQj!g$OQ{Q$hw6u zoowx&6s61^-*U1w&W5RnJO;Q~KySW>;z|}giS3bC{>?3ZF-;r8a8GHYaibVqJK8tO z9$R=3Vd6R&UI3*%C*b8IAs2K7A)mo`JW0p}T|vkYP{nd6GbYs%w`Iiaf%r%+yH^yOL37|U@86b z07b}GTx~mGZk1A30;?{quYW-`-bYG4itNuMp{&E6ogh&2>>d{r^KAC+fQi0squkyd zbE(F+t2+)S3AL#^R#JqNa-7kY6v?hi9ley~*QIKfKxt1^a|}tyrD_BrA60W2 zNyw#Y1fdpG%|#UbF;_J&VZ9WfY67G^LUHRHn1Yaxs`(d^kW1ABaPyySEi2sEXlJ=;oJ(PJr&NENJ1`!BMA8@obQr^T!0aTT2MH@py-de z!g-AKQh>qg?*Ni2iP;mo$Aa^^MN zbY+X}m`S3=R!8$o<#}39vh310FND&b8s}`1kW1qTLOvR26G_O07(vL;IH8%NFQHnH zS?6TVI5WsPDnRK32>cBcyG|=d5b{wv?;;7gluiIgH?=$+$yO`iJ-jH3mOL zlFOiWIJ+&Won4zZ`kN%zF3s~bDDA0v9w7<2G>;(Uqj`Qq5^}*t5Hd7R#=OygryAm` zfEogbJo9V@kLlCAzkI|vYf~#mj38usOzrz+7LbHozzE=|izMU%h9G2(gQmiI>nK9L z9pARF9&fygD;YScMW}vW0 z!hIBd9SCC*Nw|ykQh?zbAnivfZk_r^5c1JKkCTL4`X_*+zmbGI@MGworg@|Hd<8Yj zXV5*I)s}QmyYfaaB>8hGmjzJTQ@JcB3AvPuAmpQ5jwcDZz##~=pj^(P=#RN_Ii2-V zfN}|tc1&^WR4#&$k8-(`B;-;q0UW)KB;JGPF#_ywML+4aux-GJEm9$NS4ijK8N^?^GXx zkk2CeA0#0cFakK5QJ@S47cc}N`yv{5si;-aJc>}}j?bDmnm69mJLebR4DNi=pKDt_ z<&kQ!va~u}>@96675gxa1wVS9D-88P?z`GZWe9TLMaA5j#ks9Z2aA=C&c5Q70;I&t zm8uP?mb-IQLTTwKyX`sPAW0Y9Di3N@eIR61$(+u+Uj_<*=XHwHHYInyRn_Q~nKQ!N zL^tb&;+yc(f}W``V9wT3Fh)}`DBo#j8_jEJaCvfP%r=3U%pAFid&@($LTLz6z(88a zQl(uvp1-PdVN1iID`QM5coA?1DTM^T(?AgSK^4HZkvW$IE5v?;RN&%!p%g`aGbAGj z12t!k=i^$JCmfS)u@*Hne-+3v%P1uTj7hYA&ID}w9@5<+GCuRZP;-kTSkhjkQR=KSxln62UL;9 ztdZGSVAuFg_2~YgEf5$+vYr?|p*>Ot9Jiq+#rY9|oagJTz%dHOB-i;> zfdWcF7*lj#&SYdlI50c!8$(+mK#Zh4LF}EoTnu>c=M~tl3*WHT2X-{e=-&0h~~l>jR?#S^R~$nrUSr7kB406&jboE1z1es{TC)f6R?5Wbb4=MS$VCJ zV*yYk?FrDPxy%I&oBpoAHZQQ1I@mB@^js+Ka_?!0^|?$#z=l2H0NWVmIzKW{OesiV z>h4ucQY}I1q|jCfNFixYNICPE3s^ayQP8>|u(dk0Fh}>fOkiGmjLS9zTG%57wA_V7 zu5+6cOXfO%+k^=dC*XfqjCMv->SQu=Ax!c)CD3gx2y`y+tF>NFZOxLNuT7=eZkqI5 zb0-Q&p&u_vw;jz`a`h;afbiu-v*Z``spl}av|LNckBY%Jg))ftT3s(B9c}ZBq~{Bh zs75;J`DxN^E*s_ZsA}+gb=n^8Kpo--nQd?Akt0(*VoiQ-?TvX!Z@57{1$~o7`~rGZ z1~&Be_$EKU9mK(tpML@0vE=9MU10Ka)$Do)bluXya;>xllkYEr1RqCi98G<@7`|Py zaTLAu=rg%ysW$P(*W#xIJ$tw&sruAvd8E=?9A!^qJrkoF^U;U%(MO_>3i$4mk3Nx) zZpueD=c8Nl(I=x@qfhlrj6MzjK9i3=n~y%1k3QeCM|4}yl<0Q&_l10PM?Sjqn&^ws zUD4gqJ<+|1ji=$uVqhCkAiGCaXE_ys4JrVsr`a{q3 z=*gYYAEQ4-f4(OApXe{qQ#+%lcSe7OBG2rM{ucc``p3@bpVvgs?u=1cf$ECyKM?-L z--K64l>06CbH!-<0RQt{{^vpd=lkqWXZ$7X+I!%ouIq?=UE(u85lrdM;Qg8)fBmpmtg!`a!h)Mnx_gjGnCA^^0B9DS-oaxe24qDJ6 z^W#ULkdA4_Trxr;F(%@jz;dBJWuUmNI566?M}0EnYy+InnFswh8Cf0enW*6ZZg?6k zwr4;_K%)X5lZM6kBaEcU02-_{eign99S1M(!FO-NcQt&u6<wE4#Tb-f1ULV$UTvXpUR&fKLv%1&O+uI zJ8M3E>)lyh@U+%h)8J#$uo!>jYA?oG|Jm^J_A}w-&-m^; z_<|QT$9SQ0{B^k9gI$&q{}JEeWgRU39%Gz7ejTvItcv(!_zq{{k@!(I_~W1OKR<;( zpjdv+|NN5w`8EIZTmI*9{^$4br)OgP2mCW3eiHt~e}Q6eVRmlyLtf>0^{S4ps_QwzF4{e0tThtLJcl69mIE~8eEWF=`Yrp-+x_hp}JgWVbVP-s8Wwz zb*(D**j4ZC);6iVI7_dc!g{T_pxIQUhUP@6M^~U8O{@o$iqxu;wV}D&$gY@0cAF{L z;iOE;?(CzK?51k6!^vFX4xa+t;l2T!0LMxbT$M#GS1`G>NfW#gD)ZF@NEkE$o6I*W zTUuJr(l&5wf@uoYDXRcyd(|VtDwqa6GTt=7N3!(Vhgh#UGyz&XB$`nwQWH$m(40+n zODKJ~kZ<@>8kE$#ph0<=l=i$gi_Gq#WQMk3kj!RjGDDlP0dKR$A>JO%BD+T@*`d8m z$}R$XTH;NgdC<;Qvcspw>8$-s7TG;T$qv^Qr0hzt?y$)Y*CR@H_>_5ZJdlDP=r0*rCO;x#P{BSr=ps;Eeg5K1BIcj@XJu~7+4<_FNN*H zHP}2n0{bNUibHCB)N(y)5!I7Lwx<%Zb(=2pmFa?l(-3Ku>OmAD$8h@Hl0{m*gtXYo zJ_w09O=jp3Xh33)k{M}$w144ubr#uONy!d9Af)V8UT7c1+BLIakmFOk=_tN7i)`OT z$ksiI=crMPg3}ObmFoT!BFAtPel9U~8@s@M3?t;+brXV}95gc6*&INDFbEpUqw_J~!iyzM-+usnfb&uk?Y80d3 zG(=jZI){?#7>?rUTeOMK*P@;Rg`5^Oddh>4I8T#VvsiaA{vJ3Y!O#8>{K>~Z;2$2r z4`S*Dx!yPl_}N4HrA6q=5w73w*r?TIr<7`^j%;3ba%reAP&}_(9@tu{E$b`yR+nvpSN2c= zE#PH^;nJq$n8h-LNNI?@@> z)%n`rCcPw#V*OF!@pK(pHavP>NPVhaPyK@_h=NQ?aI~ktxN2E(Xj^reYE*S8!zbL7 zyli*}#E^$pb+1^ttXirSmkt+tw-)+~`qPMK1{$bA0<3#@$2zQo2cqFfg{mAL?`Dr{ zVA9@NZ=&u{HA@-lUn$95q;qVS+#2YncrCmX^*EC}*V_p{z~D9{7rzW^ZM=87{uy=D zkKwZm4n*w^h!ud{b@x4ALUn^P>A@hB25o01t+3zs{3?==D`|xwXiVF7L$ZL@MEN2;R%PuB9VVk18@yV zE<@rK&Teb^2DZ-)kJK70P^-Sto=xY?KwSOOcHYG8$rlN-^3&# z7hVLR7WB>K6#X&RHUl=f6M6_Suk*$6^D z%H}GPkP9q=Pz%cDEfoDRS2k~Cy%b>C1W5a%6t_-gBMA8@o6nPkT*@YZqpy&JJn-YM zY#t=ZWl%Pp-IkQi7~KT%dy;*Z{`oDG_S8TBAPKqjk09iue`b^jW5YQj1fdr6&mk23 zG1ouyphZE(PJpzJq`38wwvYZfi6rFGKLH$_OA>PFA3?~_KTU6fD3GKw=pNpJmUK_M zZi2XsO)Of;l*g3NiD&lGA-wA?ZA7vW)nQE7gnSEaFpMi}vC#k?N zC@XjN`9GY{+glv2@x1WEm_)l)&J}Veo^S?FYw~i*TX@6VI#U^kP$3M=h!p;UNA%UstZLoEs`b zDtgSnQ-xC~P!Hc;fOTT&{?fMM5FS|R-HKUcad#5zQ^OV}W%$XKhLWP5&BeatK>7bY z#?>VFK5F>s3LEyCVveHSX=@vdf%hmD+mzz|CRL;V2G)=1h2oFmCw^wDF~z-^Y59D< z?F|QQY?Lo%=_9|;3B zXPWzySOVp?NEH(Pw5c{F^PdGufaMa?1pX5y0@Dggcauna&-+GAX6e1oxa0hMfQ=9= zpcs4f4i5q%Po8Zg$UJ$tzj{jj4sA0T2R&>;9>#6k9oiNT^OwRvhuU@wKfy4Nh480j zr*gwj4V#i1o)9~e8@?B74EP>5C@X4m^z80zDELj@3jOWca+Si84!;?I4z0`e^fN}1 zFeBqp>K846o2Jec0;eTO?OZ7ar|}en$vK7Ovtsm+P)6}=!a;f=soLSlnU?Bi-v-=D zkXU|E&3S=dvxlnH<&If0wU!xjpT^TWXj${{Btu>Mnv(ebiNxKSLZlJY3{mJcX`$+E zLN(J_-(z^kXnp#Yk)d83?W4w~@%VDcN*BKvM8eYu_TW2~Mv%R8r4eL%1;rr}apa`M z;~h);i$mqX;z~3>ea?3rYBBY@wL02#z~cz5%1-`XZKqq3TY5Y@`OUD`&Lb3k6iz*l zP`pB~r+)1&KSIGzM);hb;7@AOwVs@qVLSl06@e{ae5ZzXRcF;Uv^(Q9K4&Kkk;N6P z)pB-XRvHTo0_Jva`!k)f;SmztFi=SqW_+hO+(~ih+%xl9DDCNBdk0C#m{a zBni2^BZ812&ai#npP}gM)9{!aOZX(~CDX3-=+@?QM(S9?)t35oCgtP8HPdu3822+m zYD+xj2gB380geBzfc%qPCU#CK!xpq3ddfvyoY+h*svqKupvJbitVWE3tB?oRmNFjFWP;;-xk2mICu1y;tTPLpgcJ z5I?lYj}n54ZnYW(m1)3osG+x2RMd36-GGL=4VajRJ6(T`tErb?LjQpq=eXZW+@WF(6 z;IC$#73809_#Q3z-?Dc|UAJwP#O@_XBHNk*e*$bZy!!Dqw-rm!&qF z$`QU4%|L=Wq~)YD=Icv&7=+1vDUaYg=1XDk#@3h8S?KTIw0XOa8|5II8-*8dlLzHG z(U^v011z$*tuUbcDUF#ix^jcXzEWXm({{+2SKhvV%p4989ziXHKZg@X=rM?i4N}O>2$P)0b zB%!aV@;C0Yksp;}oIFTM$;(}1NGYC#wOZUY?--}(6Grf^OJ#8oC1$5{VJ?&g%f%-* zKqpDam}1h@aR@GZ>Q%*=>!s~EM~L% zP2cA1M(r)IY={RY801}ND&*@}2Oeb9OtNyvp(LC6QK*N}untr=$XpdRtj^FLl1MeaQ#ieYlByG@pJx*A(yHGe z3Au182>Iaj2P7dEP6eSBaQZun{+Q$RSFD!;aLR?y5>DqktX&&qXE#1Ck!$-&0eIFB zVSPCPJQGTLngt6;LM{LcLOuZQA_=(wEC`tZhPjJL(;n2Agg+~Z9#7HF4qzmdA*8X6 z^-=(U1EhT+#jSIrwjkuQQF{wX$hA>BfTJ2o$OAvdM(v5qclu>gYML)CdVT3XmHD|G23Q#=((jKC?b*dgg$Vc^DP7-pdo&b*il_cbW zA4By_Tq6e}yi-H(og|?QDu*-LlFDi80oR*JCSCgFV^G>tzuZX@a_JXA$Vb22PZDzB zLl83bOQ?18DAj_@8YZ)K^DyhE02LD;@V`>*I#rAy0VQ0U<-h z5Z28il3)f^!x;`#HT2_R7iF^;m8u~A9R&N@vRiN}xUKkZ!3`j&7(dG0g420S&fF*{ zBWAD_;0YCQ1V!aO+WQWPm%u(0+<{UU;-^Ky-Jd)0qz(982atrbN9>Gi z6^_-xFNJ|Jo~DDNbTT$jO-_!sxmGnly_f=xu4d%1%yAxag&sRav1Oc&`PRwhN=}L% z4==vttaEc*{?#r#3S5K^fQ@+A3*3c>d-5PslYdFI@53aCLA4(FT_Hyl>`6Tq*VA?LVsL zyAc@(3=wI{f{u&=cD@}L+Y43pd;$$5hjl_W0lw=Tp=E75GS^{8ODAmITa`f; z+Hz*3v6tfg^poBD+XN?-lsoitMPuEjt(lsN;@NmMcz%p+0wq7Ue%tQcL24veWUTC= z^o|5EB};X;SM!lj&u!qzE+FT{<}#=kK2ud;cB$pcL%qdBrO*$m#=b4E)7Umnp_}(> zXslyba>rSPN@1{wc{(JV^siKlJ`~y_+?#y8UPuaau3=idzaJ1CUOoniCX?H{UbOOn=&UgtlSXl>HO6z)HsBtfPr58^@m z4$$eKg_(I@t-%2yhRoC+b7x%W$AK)%!x~})9SrS%gmG=|FIUb6P>cM767v(GG{p{c zBqT%!f^z1#m}M0Vw59O})vjj)+odD(5D>)QnIPO#hB$V?W#-hXGV_Ec>4z8r6Ap38 z8_&l!8u_p|=q(S73=ZWwtF=Of+4`VqmoJg)0jWOtgf7ko@g)YYv^xj)Xv+b$hO6fk zxEh@PVu&?-uf%-FCD4rl85UBII}{{652^qNm`PQD9jTa8&hi(8QWStgGM<1tZY(HWy1lnTr6vIYfJvOnP|~5z3G7xy z>+!ZEX`(!GB$FyCA-yb6NGaGZ1U4>Uax!5%$J%NM~gkgd1k8a9pZyB=J!8DWKa6+Y0*dd!? z|4}vS7QOyJyYG2s`}6}q^{G6;i;}zc4IFcdv;$67nFEXN?iXi~G#@N|NklB-QNtet4_zQuN#`#q=Hgj^ZTE5dWD^^ZL&z@vzh}a$=6x zVnRiBJ#h0;s4lg}r*SDbF}g7yeK;R|B>JeZy!XjRpU6iy<)fSP(JlGtlhLiwr+Owv zpN4;*$w!~fN1w|_pYPctx~*qQbUXa}LO!}9AKiIP^u_3|=sz8-xex<4O1n2){(mp6YudMNrqK6*GGJ(7=pn2&yxj~>lOKh8%#;T$}ckA52c zEc*F1(Jz4FFVC2@IQmsS`gQc1=(o}DqQ~>m6VdOZKlDtGp4=JzG5S;V=WC+>iT)Bj zwKIBpXY^Mn^32ZYZ_(eQf9#C@c}?`}&Uga&b70uV_k$sykG~18aF*^{@aKxr_yPXs zyZq0C{LlBEqWm+%Eo4zdtOjG>VD zJy17Wkg!%ToiGwV%K7*S|MOG$104UH|M?~V^K1U+xBSoJ{Lk;*96Y}3c zisYfKkOgO`cua0Y32S5s&L@Mo5=pgGhmz*&vq|L2v;OG=!NQ=Qpc<}lzT@o7jSjiDW%$}Bb%39Q{mNz!7#+xQ`AubuMA8Px)Th-8b&fgFTUqr<-wA0aTKXxJtQ z;;qYFi5Y+fN}Ib`I^fIkbUqy2&zFaaJXus{{K=)7Z++!O$1cL0Q|oez8C#2w@5&w9 zSFHBJ$$wZB4i|di_ruG+CEh`Rft1eSrSzXGo2clgzyaTk;(5mhg zE0y*@{^2xthPFUH?io>o0V()_@e^weVu3RF$3E2|uJeS8vua zx(pBZ87>Uw<{9kys$9e9;-kV$H91{AFP$ms3&r}(DzyCIxVa8>o(!B0rD1yYIf8u< zNyxRyRS@zS&YdJ7*A7KN$k^lx5m^Wl~m-K28#H0Ywlp_Bu~S zOGu)he^79_og|lGr!#Mb+2cCwao*#f16=p z-sST&)Wo+s{}5Uk<43X8nZ3uA%RV>{ACkNUwho9Df<0BNuszVQ!439O$dEYfbHs#gJ;T>j;Mdd(d_4_f7MZmc{Og^r!f2&g<&0gxFo~-aK^nA z3^;mJF$Oq#29~#}#qFWsIgbtlBNJ4r&SZTWf~Zuij-pF?Dgd;;dh@CyFq!NP74@q9N_+qk&X8ZH;f^x{sex=+Ei18c0XdyK`~QK`inZ)nI8ZU*C! zm(whPskH{1H1?T+_HHZ}u#iKl0Smc3bYk`E#_>XqcZO~Ot>CyhvRq1saCPQ`M8_}SX^J5Yrk zwFNu|P#zNXbaiY7uV`Os3)ChiGbG9;G&W_airD3KTZ-H9&_}haqcqezFw)2F)q($#Tn8WP1p<;#RwJCl-4Pu+qd2sk8~R zw3)Vmq1&JW`B+WuOP!3>CCfMVL2-78-bmY&nc^(j%E#H6349L1Tj0vrfvPoFQr5px z^j{T9Uu@b#qPSU%({^rv?o@J2W}N2219z)`0ma9g1Nq>a{IJl19y}=WZ;TNqsA92U zn#)^R4QbmQCv0(5p8y^9QtUxM?C!Gx*WBHwT^Xh=9Mtxmg0a<17fmt_lI?wNM#PRY z&D?-qmv%_n@D)4GrV88KaC-B5#O{K&@cm|Y<2$zBjJpl6bhS9@1R&46X^M0)F>GjmFAJ6NYL@1Ue#zI=)LeNHX<{4Ts@w*Wk zn96^bnpu8S-S9_Ue70_Ix?i7w(l8;I?(^hy^u%@AqItpyXh3Hm$K^g3guGVSBq5hq zR1h+R7?$ETN72{k*`Tlr*WK~ZbK-Wq0^N@D}@#}@ob4WribP7T~=zIl9$c0Wp$V8_+ z0_2q!v_jF(j!tZcBj!V)bBOhpX%~5PZ%gRhGnvh7;GB%VN^J5E3Yu@H1nF%1TNtxm z(7b^pXvfc`SCKpB^H0j4hRLd}V;$Pzo&MgY# z7R0bw>xo?_e6$f;&k zpU6XqIeZQh6`&`xw^C*?z*4VX5kwJL9aZojf-km1g$cXBRZ$zM4B;(cx#Hk(Z3k|$ z1HY*BE{@a2Db0QW^qbRC)zK$?WxLJ71CX@8V$kZNN}atwoUb9kO$8m1 zc+74h8fc8|Ck2X~fo;=4F&#wlIwlG)P;jY*fC6RxJk>xLBL+4OMoU^i<0ROqq65Qv zG~H=>->3*>Q5$&8;Pp%xrYGBhi%*486u3Y#p17EmmWy0?H2$D4@uk3a>6kz<+{47+ zg$XXP5KJHe0~7AT!X>RuPC|0g0&q#U7}oi9sGu;c^9#KY)BWhew@#TR+!vw!#HY&> zn8gJdNTebZCYKfUlc1dJcJ^NN^gs2s*!*;9{Vwho7D^l0d4_d%3iHx|+c;Iu+z!}v zIqcFD1?G{AC*}`qCLJk+<_{>z91_@0eGH&j4ubM&uUMKj5s%>#bi-K0V>G!x#pLcD zWCHv)#F_CJ%O#|rX3H7v#J_C__3V{|VO&FL>N$l{750KjlTCb7(mo|r+9=`;dLcQG zW_t{zB^MM1Mv5m@DzN8}H3jnUv84y(bS?Ekrk`>JHf`W`6V~EXIJ85RmJI1%DW)#g z+ZR5#Fr(Uq3`K6saDfL4Fb=85RJ#WQ+pR-?e`s{f8tq1=fIjCh1o|kI^F0U%=-V)2 zLVs$7V>8L{fEW5g-V6CHH3DWQBf!mu2t;b@ZBS=&As!xxd>_bw2O_V-cPtRe-i>V_ zavesW_)2aQ?hFVDNNNYYv}08%=Y>{zn*x((HK)+Ysj*3xMIx`X#!QjZ?)B_$@>AsA zh|buERqm4#j8qj3->Y%=S?EaT)aV(zyj8EK{-5JLc4>65C5G7$j5N=OHT>LZo(Gfu z0Xg?@a@y+bzjSfg)U?y({&gq~Q;tup@`ofLm&;uc@^QKUmL%kIxeG$3%Uv3DO`<{g zvjXxzDEhh~G^Vl2zp~ykrzVf?ZLZm+n^?puzig>rXI4HgT<*q5jlYCqv$))k@K-|i z?&;7}mFlI%mlEnmZ+K8I9qy$xTX5blf~LESYbj>oyl*CE)vfU-K=y5O-XGL_f)P&q zQ-A?;6LrJ9Af5RKH?Pce>Pz^5fpjw>$hL z_#u!C816_Is5xEshiNW*yRhU)@_15p|Jwsw&X#AIpx(-wZq9*e@rvacm#I>d4mZ9= zVAz9zSf1HXX)ez?R0b@SmXIyc%wM!+nl|D@Pa)KkWtz)Tk!;--12Fll#D7<)_|a8y zhh9jIK1}jNZROseMi-mK3nd7Fs<0?K-XTwJCeA><$2+C4(_Rc!u|%QWOn6Xldic;p zckKfV5bnWpG`1%@cQC+Ps6qAaF9W&N2iFW>^=FJ#uffHo5;C|@mjC5JKnyM$=*+$&hk0Av_V-f)La=AhvF_W1{;bkEWmv`sOdjxR${@tIhw z#h(;$i*nviI$OshO)>FA%y`mNSBf}^pbnW z*S%_Ss9KdQ4zW)gkC3s$wH?*sB_sUID4Zz;lSS?CVaH8jzZgU>`Q8q82NOS@is>dw z)sE_pq4LmkymLI+pVP@a(I3_)Xe3Ul}uI)B(*_7<%lg zQTTtUg&{R`wyVzcTMOcKYA?V-FfsrPHB}zKVB7$+#Jk72fYtRdug6OHP!Fg?F||`Q zDwrwUGV)p|?{W{}xDa>82vJ}uLlkOo+txh7qR~bYNL3E8v}UIdm3#MJE@kiY`FHP?S>cG>eiz-uH$8R z-4DZTDrU2%)=Cav?HdKpJ1Ka2PFJ_-_0&H&o=rMUFqRqhxjJR`pe{h0-QaZXKLDjs z=jkU5;cS^uT*fK0pOJ)IksCqCCvx*gl8`HMBM7w+xtV-fgFS58wYr%a6ccFml-UGm zSz4!ibZ>J#E{$vvx%nnXLmN+-byBi)Hve$OuNOMkl7w976oh=xxq&3)LZ={Pq7ygD z;)t^cu2TDGFQDjWM<=$Ug@DvKthdae;?cb=p|gckW|vWdbhdpPW7Z3r*N}u<&=iDx zp!s%^kPDiEPz%ufFh##LXufSCUX=p>wSdtZShodWluIQLqx9n<_H9@{@%=dQSz_Pn z@H#8Er2Qj=)U3U<)IWscpAxoF9Hbz zHD`EwA1yqcNCx6)4c{yDpAgt879A5pz!?4UtXbw1lop)`J#%>}WoL84h)waDl;?B4 zjZ;F0I8Tt-@IV|O+Y~5;6dKUibP;c-i3Vv4<7NeXujD=$N>QKz$#|k+--ZKZQgd2< zQ7yYNuw^0e6Ij;TVShnK%fvl%Y@(s2rjP>Kp+7F5bnYv zj&7TY8sg}w%Sz+hAx>{(G1I11A$^?Bk`Q`}yHb80Dt4S=AJYrTDc0vC+6FWbMZWM& z<;o__^b(h;pH~@yd;oY**KL`lcBRZ~TCs$l;|T@AXLQEG=j**eHh*C_GzX(vjDU(x zuRNw-4#O(L!8Ro1IUE=HN)?*t^{kTEyujA$!xo`57s{vIb4_M;E?M`;GiP?}k3X^g zaO(vzUTv^$7_Y0n_PtmKtvd7OW25MC_e+lt=_u zT8j`JS%&+(2O!3Z=Y4{LL|s&nNUym~aiaCwqExTG)lkt)y)vnr%rDj8>Z1miXTazc zdOh_IkLQ4qDV}i@GkT>iL)+BgbbW4z(qKmV#Ef>5gj}vqLCDAT`3{nh%k?P;nXXT{ zZQAa0OC>+~2t{9?2gWpJ^g-5J=A7Ztz0I|{bkT{JQI*wi9!F~}GvWP|ES=5&DsPVu zIv*wpxzH&H`JnUHBq0|%1tAlia!J$#o#xW{ZxsFP=tM#-_=BHfy%m5?E{vAY*+R_d z&?^Z0)(Oq|P});*E+q-MpeYFXK=T-qkPDiEPz%sJgQEYOLGv`$TLIAI!U%*W{kRAf z8Fo)x!4chtP|@~XCjOQ~MOBOZbuh?zNQ8=-$wvt|z6gZYwouUlO^j->Q}rFtdNW#N z8pbkUG_OfD=CMZE-LMASsB}5#68Fy4)y|laG*7`f0jrqg;EXinvlUhb|NBFrC8I>U zmpu>N@m|Gcn*v3*s2aVTs4P(Q3B6GKas2e01&Y3`x5c))&_}TrC=#v4K+!!=1)$pu z4M>9=Lj&en`~ME5D7?T(2HX)y7^t;7Q1pwyRxx*y5CR5@e#)9MLIM&E-zz}8BCu6DAW#S!nGn1H!Q~YK2qa(t!d+N6o^3NxgX4Kk z%JJOv7_&CLie6}Ez~~L3;zuw4HF_aA)&6e?7`dC= zB;+|Py@EhusCqrChVPw$t=ESyLg{uUF0bLsCF>r6B48wxB=*OFw&Me(9d%H6CN=714w`ejGn}IEMUamjcveaMXkIE?uiZx6+Mp%74bUT z6eL=tEks3Q%Okbnk=mv$rGX+(2FI3$sq;cpWh?k$A^A}al8#p;HidmX;~Dsws@GHh zz<3V)NRe1VKC{w7WimD0=k{k(Dcxph70D&L@tx{{!*t2n6uZ-Fc?gsS>)XenzKkT~ z@>&W)K3>b?NJ1{Jr66Q_E#>O6i9_97aGpug*B3Qo8t&;~y=6`*9^Kn~Vv%k(5$>61 zsb6PSJ}$hL#-NQ4M6t0!q3FdE;mfvp<@5vKVifY-+ph#Fraw+13b_+c+ORr@x>j6jjOV>^OKJyPB!cg2 zJBHb{$$CY}#UHzviqa*oQLNjwxef;D)!SW^HFWLOioZ7b^WLs%^phA`hHupi#c#n+ za483|^)T=tYk^ zF1L8;;;xQLu{tsU@ZDY-7=W9vStT{dga`FiYkg3{dOe9T5eeJc_)Y=pKXp!RlT!*% z(iI?Nf?kUop^66okksdm-onp?QWR?rBm=f65(a8cZ{en~kU4PHo0SeEXIKjVy!u!5 z)z<&#&*fGZlt%`yD92lakS5>CzT+I z%%zZ2-lpY`esC+PdyEq?&ABQuE96Y!m5Aw(#&YHub0%U!s%envgHl>_A`#QRI`3ar(#JPggt)T~yeaN?Ojs%`eQ zen3)5i<{VI0U^`G)}KN(MmZ^AjJt7wa z<2uKS!ZeOfK;Q+6MfZ9j$&xC}-Q=?p*H%@RpSW-(5b1^De*CncXR60a;6<=dG;@G; zs1b3BLAk-?J}PB$+d~Z6uoOLqqaw`S)+QIIL(V#BQ;5!7_AQVAx3|BI@0h*K-UZs* zZpn*9!o3yEMvQ-npHdDr>^9NpDg3hfqCW28%OQzI{G+7Jk0xzq?>yRk0}?%ikM9;U ztvz2QV9s^&B>;HFY;lhzqxC~=-y1j3OwHFu3usC70*?TG)>8908l6?`O{z`i0U33` zZ(Z(6@W$cAyXTDz4-_u~2VWQNpWE1#q+F<~XHKgXD}~MQSd&6fDk@YrRikpHwh6AO zTsbKA~wk*xy8pHzmZo1x=4URshFn$0jWcKUdxUNS2vV1^^9}bfmG9DO~+|! z+3{z+k@feCyXcPsja+QZ)pM%Nv0_(FXH9-pT{MRhb!WT~$i<7`#Te~UigVxx7!ZaO zOH&)MqF02{-E7hz;bhFlAv(`3iRwvP{WAtYI3r}gmLXllsrV};NcKv7+ zgVD&4HbZNd_}vICk(o7)ro`wB;H-htV7Be3FnWJ|_qnLS#EW z5sY5(xqgbiu4&pDpUc;$5ARsV=iNL`MOSc$_p)9}>Bn>7w}RdjEO0U}z=hDVb5y0PCiF9M+c1yzc(KMKAAl$#Vv4YI9$dzTA!&KF0PYX z&4BzVTkl;Y@iOrujf?v!E@D^j2|`wZrBcH@OcC-G*Wjd-xELYF`L-Y_btO{j(xmiz zs_{Nj^1=8&NJ1`*2Xx1bR}+Te_~;I95`#rNaii89hfnHGjCw zLIP`!WUZ0XKEnJrZ-v}5DJX%deWSGfaim0C^Vrc)+S5GgAqlzkg&^cJ5?)FYa*YH* z$k6ulD8XCR*mPM+!{1h_Z8|!FRR2Cg^(RC#=(T=ZZ`!s0t0+dC14$6FimhR~{5OhJ zW|_4-T?Pp3-zhFK3oJEVeu5(8E3URpmsTm+r^|b&#`{RgM@f8}B;-;OF8rpt<57yx z_~;J%bonQ$@jl&QE(Pp_CjJXyRCo|Fr&;H`%$2-ZK<@{Sd3nCWtH&nX)Q;Z0jOXQ) zocdNx%ZHKzaZStfp|t0;yp$y5nwAA2pAmNqNys(g1R-NuR%cJ_Zi96GvNNa_=n!yC zz73j@JPzM%C2<<-r~t=7fWZ4HcAXwvLFkbwnqzw6aT2%iPGNO~B=jq&rNI^QFnkGK z%K(o4g(Tzwp=WfCrZ6wO3_Gm^R|rO0nr=)}-uzs0z0YE+3tv6iEh=r?kalY$M(8lq zlE#`lSrXrM7-_?#sBy$J+U*TdavE|q&& z_irq0rfZVz2MpbZtau(3dxN;elO6lQ4W!zIp&53Ib)$E-L%@1(v^cdLD)8v999Pe3PT-*-b$Ip2}`{iz2soon_6hoV^>|vTJ_jf z?`>bZlmYY3kiiAR8n?#nKK2P<=WU8X_ukWvvkDbBDG10&_Gao|DUtn$s!{IXGHpIx zAEC%_2kMP_q4-1iso4(H)FmVfm`w%8&;Yd^=RydwhM0djLFms)duj?<>dKcUI`vz&V)kq7L8r^FQ#R3pW#uE^;QddqS+PLut1%~;7?b5-3VmJ`Wr!9i?XcC9>xWq!h zfCLZ>$yDerEH(_=G*82Z;iFRxHCh^~og! z%l}G89(2AuXJVQP_JNe_p#sH{%Aj|V-jHy;ioCpp;m57%<~y1!^{?|81^0o#7VB`w z=9XAuVv%#B!6_aTAvJO~J!+hAbgd~&I8#qt!;?K|VGC|AjMTqvJL zAC=7C5h`<(!>C?JVth8tiPTZ{RTmTnMv5m@D&^r~tlG zux5+7{?fMMkkzER&+d@`XTN^x?5T zF!FiEh}ZDoJckSql+*`32#DcfLr~-JSYZy2_^sP!xMoahSjgWJlueRsv3kT4=WfO z?Z?U$zCf3jP2W2GjR!$#Pgi&sNyz1I6oh>Ijq6B4E`OsS)Ple9bc()i& z%6iM3PdvJ}xl&HK!soL3&He8!xWb1iK|0$$z#C(3Ygs3akBRHF;Kh|BAr~|SAs=Yg zNkT4Y3PLSF^L-Tk=M0+fX1x^vO)iW;Xwr`hSGX~U#B)$=JY4z6-r7cs(48$`*=6D< zceYSbvU@G^*TEo1y13|}nS7Lh<9~up)wWQ769~>*FugTSFf( zn+HVxgyOGF?)6EpC(OvS#BhB)K`#_Pi;eQUx}p8<^#k>`*etRX1Jau+T8&pX>y%2A%M$*fdY0UuC7~SE)DkuWR~LbOb80 z#J}S5JSNF4V$W|jLfv|;UP$WJ8K5vI-{WEEO6ZVR4MQR)@G!!}T7bMx z{N`7yr%@SY;I-o)6a%;FZ3)+{Gl89(pbARc9ZWVF+U9;pwfVllHtV3@3mSYkYp@sS zId37LM~QsQgMdK04GWEEPhDYNw>#ObP@j=N-OYt?C2AHQ3>Rq%riU)=O8g6mfV&c( z!gtJ-$li^uD{(bA)oQ(iFi?WLiS|T~rp?ByZIeTBm96d!KE*u~e&y_;eWOOutZN99 z(9^RxQ?F+nrd_m2^*MDeF4hHRQ@2hJ&LSucn%2jIvxX$(^56(UJ|3L)Bq5gvM-Xbk zgL6JbUpF(x)VX*z>n(Gd@#x;>YFfG+L~@NoS^aHuF7BWN>1_K5Z;TH#Ur!QpK~oU& zf#%ytLM~_uLM=e^MvDG(2F>ePZv{Y;3nLJk^y9+0XiOvV0u);toQvPyW#Vtyxp==t z{yG@sNEgneC@tR&n*~?%q@2NTp zW;eH&@mMb}qe?M^n~P;aiNx{PS|!SidPX(eZ}o?JeaBy>SzBjGcjQxw#WuMkXYM3y zPkkVu0~eRfd+LSa>G6n3hxt=fmIw5 zrWWY7Exp3+Vf#sqffog~jV;E7D9{~w9BZ686{Q6z+>u;rO6fV=k(#Uz;@nfaeG|7^ z_-@~q2Z|sC2y~OZj5pF35CfqU1t5@&Cm9gkz$F#} z1|)EhYGB%@kp`V`(AYFjql0F(uRBuHr=la;>5lxcV$W|vLf!g7y^z$c&yhRw3wm3^ zbt^jGJ_l7$+Rp816hL=Bq(J}8z&7ikM|b4cS%bYm&v^?0Jxb)$9s~s1ZCGeTd-|eW zyF1bf^+0!|W*Wk9kv3y`=+f@UXF&wq9Xa7&r8|@yd(M$<(d+C|%67t+|p%$?~YiDd+NMy_d?z!PRdaG=+pFYTO!_`I8q2Y(f_M;2s zzo3c+Z<17}ji)Mq5=v1x50H!?Os%hGq~!yxFuqgZ|6^cl*y>4i9v+x8pnfD3=<0X?nn1WXJ&uv-w&m;Je89bc>6O z6D#FHU&m=f)mo`G0+-yMa?bi_)seYQXy+2`?$u=7kvn0aTF#ABi(5tpaHZ0*r8Izf z1O`g|L;Q04Xk@SeXQNka-LwrWTCsfj@*KbWv6?%pQjUwgwI#{&Wp{19QrCB@&hj(! zabYz6Coq8For<$IEs4IXYV?y8E{VRa7mB}ypPD7nGS74D(k0Qa^;X$tXe+QM4EIT zWBi&EP`XdVlE{Xz#wF2_zDpu)+$f$^wj?(rB0Qr_0Z@mW8?r2kjs`*V2+cZt$CgCw z-PkUPWQ1nbQ9%nMXM{%8)u!cmadg8n)E0GbtYz%cf?7LD7p}3^lfA+0+L$ z@nzEk_zpkHWs{81sF80jp5!nE!{T%(=DT=mQ}ATfQMQ$mJlwQvi6{m5eZ{!9MYh{a z640^#t@vxxa^yFvMn8$+a^#nKq4*d0X&gjop4D4roBi}bt}RDI`!R;_H>e_DIkMNk zCF9IXcruwQk^z$z3Ab@MvLLWEEJ7og$FTt51I z&mPfjJyW9F;oleX(H;5d&TFDCMt4PbNB2bcM)yTug1=vmz7l;k`dak$=o``f`RKuX z^gX!!`1{dA(GT*`!};iueDuS7^rL+AXg>OJKKcpg;IVx4)97c>&##Go0Th3E#;nEB zukz8aqu)fojeZwBo{yf0ejojzXL|JH&ghTPpQ1ls6a7#0m*}aT(bGGlze15`c1C}T z{vQ2fXY|i&qGxx;6DCfW03eL-KM?-L--K7VQ2bl)=Zewz0siN^{Lh2@&;Q5Xm%zzU zRR1UB-W(((1TY6pB9cIMb8!YyLoQ;HNytGsjLYn7@Ahajmx~IFUdS-S>Hstfk%uaPxy{dP7tGepd ztB1+gEcYZ7^9k@F4umHv!wWQCYQh&2AyIZ8lS=Jyw?eTUZiakz;b+-7;H+Ktl?j%?x zAx;Nm`P;>1a`#|>DzfTE=5{X50p0f?#}Syy?h`~r?vwQE5AX$=@HG8;mVW)2emzIO zo~K_g!q=+7?o0SJ$bA{U+*jb^tX}80tM)3M+q=HkeGPtZ0r|cG-#lg$yXsrSa5{Kt zIiE?VAbhQr?!v#)C5ztCO>Tc!WX&kprE(!#oZ+o9x9Ez%eG9A*+_=yp1)2LG^jo=q z8NhHDSEjgULLn7?5N%9WhGpz+cBXgL;L1?AUl!10{(fL39=03^+FBW!NoVceRbz3; zejT_1wWAh$O>!|8;1x!`-g&roNiAIatd47Fn_8~D|8&8%Q4-hCrUln97jSKqj%)jD z%G#&rVaEctHqzO4@ZUw%|Ok!+E*95hw8Am6ifdZ5dJ{Bm_$Q=>8oWUfq#pu>lt_ZhdD!-#^GE-@D6kBbQ*U+EnJ(f;~LJNVsTB@IGlG?acyVRxOdjVyQ6fx!+EBb zcb|q#T;qmG7>Dyy!8^Tj;bH8g=-h+xQ6d^vA8B`|O)WgTO2;#N`;Eo3y(B9Qy9;9#-ln2_Z_;w0@pIoF*TTEo zbiBh=0xj<_LMpdXdF~q)?{X)b`#xR^*B;ez4OdiRac#7uaba;2SK*=colWEZRSWO_ zspB24JZX7{K`_EJE-a+MPNs2_E|i9S(>I0*P)Pa4fU9(|xF%~{*wOf%Qsd^{di*vkftB-aiB4B8{G zRzBMQdzLevCsc+kUbm7vCXm0yLgl%XH6O$;c1Mz_$OW%E(l%E1xT8+j}qS<=tX?1hBsahacDD$2algM)q}(%!oY!u`Pk1~`e3%Vv5YZ&M-J zEhLI_vd;rG*t@<6zhF%RGdL7i_GB8=++9fK^L7FDk|k}yih8kzDXvfRS+)LM z`XQjp(pEJ48Q6U$<~G%(R>xZhnjUR>VuuL(0xjC9cAp7&o`T;aK@Pjjk`#Nwa0QXUl?!$6-I7EM`yd7%8 z;ObEkfe`f|9?)ceoFGhXLGX5lCrZ6ZH2xI0L4fi5`c9|*?r15@3>}bWx#Oj@6ZeC% z*p75IUoN#GN|Ix@)|uAX`JQ63t0j|eOObxF(sGxB?M3STE|$4Tox+oChF5#OrHU5fE(Q5!TbgD=2*~UqD`%t zTzB{bC*A3IPmY8lrS3*jN$_|TRs0u8(r0-8xl&6|x^PM!_u zo$qPMwkHdPWDko_;0t^-F+?0(w?m%^jo#;z8jUt|sh=p=H_{j1sHGjvwQ=h)sP%5W2qlZ24psS~o&o%~2B4QOi;$LYOVLaI{&jF8DG zffKcaRHp4|av$s05MgB3=t$PA0S6jQ1!@WYML8<`X7Nqf z01NyD4jOY zMlx~bWWR)NPXClYhct6q@Shc@^+-id{bI-tQd>Aq*Zyvo~$3|rju7%Quxby=p zA(aL)LMAqKpO%nH0~w+Eap^H#Gh|7}8#-&mrH84oOnCT`uJKA-VuVa^>AzY+Dy@jo zqcNY>jlU|bV1!I?>1{efwadLmT%wKl!;FDd`wPgeHo&EQB32W_@F_-Y(Rb;XtL)bz zC~b&VtF?qwddUcxSlY>2LMpvvgnVcfZ-$@I(U%1u52k8VSBFR`#tc6Ox6jk{R*7qj z&||~I?m}hoF?`Aoe~H;iua?lCpq8rb!bc$yb_`Q6d#@gO|N z3IFh#Ws)j7_)RU{;ll$RtV}GH^Z8t%)LQI<-H6l5upL$Gg=3nBxP$kQ`dt_BOb*|z z2*n*KD;MHuIZgETUTtqTz*1n9IF~~ri1RKeZHPM$X$h%thY>Qtou{>gRC>b*`EduQ zC5n{=d@MNns*Zl`xKrcw=ogaw#ZU{jHsA^BS<%h6h5HGmE6Y+YcpPsA2z7}|`H^YVWB6GewNYCEjLn{`my5O3PF zgj9IL2$|qbUQ0-&FN{zfcyo@9e!t_**+fb)@FoVgFV*!{i8qXp3Eo_*C8WZe7(KdG zOUOWfO!4M!EwLK#hIY0tyxG^okbq}J7~qWcW#)(zNEMLtgtpHr$axe>8$!$wDEq6ZvI2tO%=wx z45bY*W(X{tso(Zh7{dseV9W$9A(f6WLOzUX627;L%b|N7Lou7AK{Is?sTpi2r5bi) z_lG8dyiC}5gs$~U@L+^YcDt5o38@q#MvpdV38@r=5ek)j!22SpBUH2C389+h?#CVF z95;r&eL&Y+rJ^uGCZo&_Eg{t?6Qf6;)e=%E3M1qjWd?hL4E!a)_bM%+8paq(-!E%f z;X*em_1RfG>qyV_$Hqw;K;uG=CWQOejo_yj1Xu3VaYgP;tlhV<{sR*=7}9Ofw&2U6 z+#Jr_M}Zr#$q~gZ!ESdP`0g1*|K6+m5JRuqg@>MoyMy4aNOu<0Lt}sc5!y(8^4Q^#D%nG!P&ss)@E`92IBe! z&rrc-Mn$U#LI2VnX%hC&+K}yOw+ohCf@_YNW-XXE|M1yX4kjm765@V$;^C`Ph^OEj z^xP458}%DKp?rUdqkMRD5HBOz8Beu8vio2e_b}l0Sf~OlHX~VV}_qq(c_>#Hf>5`D|45Ckjqq7?ab1ad85$ z?PG-5{&5ikUzDniGmt7;aar6}u+a}m8;*V*{U{I^1^SDe;NkT#c_`x%it+12j7Gx= zm3W-t1PPo^2>36&JeO;7EAAyLj0hjsY(;qJKdu!8wy2pI1yTj~e;Skf0Xv!m{JDqn z$2Y$WSPXB4-?~IA9*NruW=BZc(2hEV9re9Tz>xZlp5WqhF}WyP5(@H9M36?7L}ebw zl90gpqJhB+ZGy8?_gi%I?QuJb zcYhrq7vgUZQ((ebJ-zWG^OZ%6&V$1Ct>HCg^A?GIg45HYlgvW^pX?lK!ECGBfw)$% z1du6rWv%%*Gc7szJ6C9j5Na@SO=jDh*y9EKF(HCatSnEW5wfs)QML%PrKXUDE5fb7 z^k+D2IAdbecY4YTvx(pz@*65xIM?u^jzz2FE z+XeU+xsZ+grMi%fL<(bJuvoybIwN!)+y!so=~lAVuZ`0+wR$_D#Vg;SXk80{IbNN< zm|bSky1bxV5c8?E&4#d8u(}DudASsf{)NYIw2`@Bl4=)VLBbca>#%wA`XFc*o0;%9 zUi06?FkW8)l~hhg48wR`A=gv+Vqb^x^7O_en3u@x{S|sI_9*Ewoz_Sx0(ftfyBani z8wUCEvCRDz)*2GzYwtjiueWRi3>A!-?wHT=N5k>O{qpVA_(Ej(y?4Ye5}$;H@5$Vw zle^Mm;!Y@y3#U@_tIFW;NIAdJ5>k1*FhV9iJb%;@QaLg(LOy0rjAnYMXH4Y2#y@pU zlgHUuoBVwj|LJd3#3r0?`kV%Kl}<5?kYAU=W0>r#C8W}&7(IH2mXJ!97@<%dA!oA% z{2rn|QBV=M(B`qP99x_5cM#hT`aGs97Ea+IkRjYcQL!{(? z(K8ThUFtbqJqr)h*BB8kuGR5a*}ba?Ka57=TeXB#TFVHTXzkrvLMp9ggnU{H`_veL z(~C>0Im<~+R^XY`ztCf6DIyu*LdZi$_SYZs;_GasnjAyk4ApJo@oLj6gsE| zLsLxFQ8E?$xAuW(;G^Jz33_96FAIWE!>~%5?}s51!!}WsdAjZ@RfXA`iBs~sw1iYn z$uSUQwU&?pg7}=0MNAV|1`X=V$y#zXxF*x?`Xw&wox!}QZ$g6roI>))K1$Y-nfe0-OCJ*Nnp^xab@q zR+#x)Ss+!sn*CSXX%*(Y4y6q-XUrwKNrnn@7$FnPd7GAyN@p0MIxuIBj()#m&MatA z@VJO_iW7s|%XPg~Vh$r@f;k(tgjARlqepF8LI(Qd!3#APa=d)TuD#T%gOc3WPEg_Z0FhX@8&Mi9n{f;=_CQ^zq%Zb75 z2X(zwA`T;Df;dlT38@e#MvtD?5;D*qAL1xxId5o*)qpp&vvuK3Uj|T`^ab7ALj^hG zp|m07%+L~2K@KBi0y*=vgj6cS2-N{O$Li?!JLJ5JNGS&7#NhV(biGwV4kKg&Ij)wF z3UXrf=yWY11N{j=PGkV3^R&cjfE?P{x*(^Y0w`Uf?Y;_qz5t~S(dQdlLMrrOgiO%q z`&vRO?O}xKK%WP6^!pus?j=%+fj%*~{j9FHO7vlbOwi{aT0$!HiP57Wm+Ho21O4%# zPhI{N(%E*puIVt`8wZWnaDRe}p6WCAYRwS-jQ5~D|-&=NAxA0N03 zp3e;s{t~8lsg_U;&_X*}7qm1uHrvhGZmJOGTTt2%VScP7q(T@*$OK^?)Dlu@2qWY} zm>OfV{Xy4|nxUrV*lbTwd6}^BRbA_q(7_0qI6@4&OgCLnDMpMQP1F)nDF!1H>Ie~t z&31r}P|bp`H8vYHew-wtgHZnnwI z;ml>R*`l~5*zH~dj=7D9&2|&iLu0dD32k)oCy&iG+B=itkI=@Ci@-U%OCdWu!UN;E zIzn65a&}M+PP--{+FEBP98-nUu0@Q~LPM^h+b|wrwT@l3l*Y+Qrr>NXoQmzlfF5v4 zwyDc5Ik|SL-7cmIX*hXhwe|QyxLGuW8w=+$xzf*6#YFJhIO@owwe1>*mq74e6}@Xv z{I(y68qMRkeOE5z-ip7X;}U-Q>);q>;}Pit5I(7;aQ~ zm9_IT;}U`U2mwDzyo(=XArR4YEQ~k7@QvKF3W7M~th`<5$Q8Qih?WhFITdnx2J|J6 zDs08N+#6wyV39}5VI9NpX;YyJoxRMfscX>i_ytAZ=Ev-ttP)Mou@=%XBbA^$h@%q7 zIaCR6dZRAPq6vfzNdD-4i=^WzbmWO0xv!oo1ow}xgZra_IZ{_ayWWb**CGLRst(?c z1>UwAXf}(=#|#}y`6W^vwk9wII*&sa2|EC~2){*0q9z`#&`zc>1RwPu^~X-eur)Xb zM@($7HaNL*1}5Y-nWz_&UA6^aXxR|-sE1b2mdyA9GNKDyI7o7Oq-lJiHPT=8?3nBh zfaG}K-5G@A{s~XakYbg%tzgp{ByBjYar#v#0Pp=rPyo|qG5IJD3n}w2r7lTKfVseKTpn%*v2-`+R>GICp=t5HCf5la@xA z`QVzQ7Xhx$(3WfC_6$Q?u9ge&WzuPYyVdUqekdNep)K2Gmc(BpwScRqLKVP6|5V2x z#F8m{U;|0$X(4Va7&aqmLu}s3f=Dus>}0JH68UgUiO4v=KPbg^q7+6GC#pXJT|yQ? z1Iv`Cbz2MwFn|v;dw*z4z_SGbJUiP6&!%~Jrf&Z*dgX_-PY7zuHxPpnnN1>EejB<^ zBU;{sf02lmE(VS}(?I7=Vj+()t2kZ_h$1K}*+vWhvlEbCbXGYVg`x+Ie`q8$M5GT z@^E_zk7D^Zow$|0WiLQ!+-Q((HX@4Upf76d(N*~dGD0Taj^nh1R4!kPkdK-1BEDHV z`ttT|ET5-ZBfd?A76spP4a6Efi{P$NEFj@us22E?bg$~6Elf|v_5qG=TvY?90-ToW zc&qHzdk7zlv~|6fkV;z_AroyqRZB>vt&C6|+FH=j?{{s@5-Is->jq-2OIycF8^Dp6 z8Y3d%XLMXucIeZD14ep!rIwINPZ=Q-J-ty&NTsKYP#t=Dr;dKV>*;MoN-^}5GNC>_ z4ZaG5Vd`ip6Gv2En!wXP>A0%Y(?1dp80qOhwS-i9$_Sb0>Ci9frWqFIR!3u>6w?p0lcD{t5%p~H)G99Qb_;euO&(YDZU5Bw9HTdec6Dh^O+8EqEN7q~Bp%+HTlxUBUA?j{ar`D-y!HlBBdA*6ocDizg*9xg%L7= zpeb5HDhP_vquE+Q2KwWJpgk6Nhr97lVSGnuN!0*9w5xT&&%RO1>|xNeXCO1jovL)v z?{(UKt3YQplr{vN_iG8MK!*`B0iBGNkVOXovXEkRG<^1M>lB+8R(A>bOtZrh6sNN)4M}Us0PTP9jyy;;6*98e-{QeLoplg z82uso_NcaRDp+|4N*lt;pS6Tku)+wLz{;yyLMpXjgnY0MNS@ zy=GvkIef%0Xi}_Iffx**sq3y1Sr{P`WSOreq(YV$J$kp6kbw&MkYyOzUFSx~ehH0P zqa|1a!q5)ag)mc9-T+}(GtOUtcQ}|VdfuV!xe9;UptK?Wl(d9Y_`?X9;LkZ)LMr89 zgzCbdUR?|NAAdec1Qlau6NBN`>$AJ)X0D-Ben!ZL zHt}w9*3~nE#>#Yg5O`v9lmXHc+V)ST}mXHc+7$G0j41pu1 z+z83v!u(QNVl}`FZ9`o!)2N`IXKMSWf|t{wv?07)pe3Y&7e>egUOuNKq*4z?s1A6! zR!6_z;pJ)~r5H1r7~H;7*IOmLFhVBq@(V2?6}-gg(eJf{4D`nbFA+gMU(gb&0a|EB z>w=a8;OKo@t_a@VQJ&CY)0q*h6vt8Tx4_a7SLp_R71j)a(uP>Gx0a9!YZxIDteL4L zq|y~e$cHuKgFGkv3}3{l&MSC*n670tqfj-~8n(;l6Jf@Hq!>b3tLwTFk{BTqNZO($ zq=KXvJ=&@zWT0j~NYX6s^k@mz08O;RF`-GHoyCfb^5z#6xOajVa3i80J`VNJ=!cg8 zpIrROqaThDhZy|f5Bc!|IE!^R;^-tK;#uGnQd>{kldCo6}R>@ugGPRJ^aZmo{V`c@@S4V z|ER+co$bXyd^1Q3{Q9C!17-Z;fe?3@voD|pmx&HGC>G+4qDG@5`wkxRy+JPIUXQ;F zV<9dU2RLX%s-|_xl7m4JS>R1iMN_$KDVfeD&CLH;iYOAPwBF)|Z_Oh_c^AwNSKVq_d|25l-9x$R#%47raBYPJm-mU;KUs|@0gER=`QUbY#0x8x zMjSOp87kEHWTrnnv`v)`FSX%@6WhY)5K||e%#d)%p=|cy@PbfHuJX=j2wasexO-Sk z?gn&tZ|MJg!r;1ecuCw=FdatHhB~~cPF8~^*HeYy_{NxhmGv2eI37>fZ3N3yGI8`7 z<*Cr;lh9Kel$eG~%H>NCJ1LoITG?Th3T24RgiF$5K{{Qu%0+lXNN0;BI|-{T9c;x~ zR^=w*cp9qCO26!VJ`eOB%&r(BX#E zC3^p-mNYC^Ej-cBBhMxTFfU zR5D5U1Kf(Nwq%jsPL*t;6A<#46S6ws4VV<|c5<*{$(I>rd!S*?LhT{wq|DGgm@K4o zLrm!eY-9@X@9RWBb=t@eJ^0P6+29C|k%A(X!)WwoFzk zjEuXCFv|$pC|~0!6-vXWRO-Sk0&m!!d{qSAh5iV6gf6k!;p1$Tu4@9t0UBz7d$>Xyp$6Bq;LqRePxLr!u^l zD;H9BFUgHgDTAG_CY);$&explW`C&ntlnA9o(boMg!9dW^R0w)W5W5ibCYxPs=>~8 z;QuWN=hlSt-GuYKReLz!Up3760sQ}A!ue6c`M>j>+nn2-JDeXocRF`DcfGPdufa0@j#vkPTDdGIt`HS{7XqE%qkL?qgEk9qz@Dd58NM{46^M05eH(_azuk z+;JctcOrgF`7C_=>tgsg1OGYzKk(XH7q7>4SD@<_#_4yj!oM)qHE|1b(S6Kyu}x@w zW%mi%+9&DPAK(l6^)&r@mVW)2emzIOo~K_g!q=+7?o0SJ$bA{U+*jb^tX}80tA-TM z?OosNz6QUyKAN)Ky(=LwuS$$yc^IETxL+4txOu;CG2c_(dtgaJ+@_d!?4;i z$?R5mlC_Vv%31sLJZL_=SeL=errpk#=-UEdXWjJ(q`d~X6La{U;$8)Xlr}Rg16O@z zdROgH8CvSegYE3SALztT>{;)sQNpBN1Cio&7q0`?098@KUSnK*2-Z0g6j905eKrYJ zQAQ<^!ydOHp9?PhxE3zlX3B*joC}vD7d$+{{&Aj+({W*}jtfU0o5`iNTBnr(FKgAS zy6Ob)}x#eyJ$;)b`8d+ZQK&O+pm2 zx05OE1Sq6}H!|QPD;(qobMv0>GjF^lj+^%|Ng<^RWnkLH?vfj(<6YgF)Od}YTMKXJ zXn5;!HPp;U3ynm^>A2dY<7(v4z_=CpT-fD%YvIBQQ!Ydd9kOnX)p22rjth0cKI2qf zbqH?SwQ#e|l$)VCwP!4y+7*Y6?X@uVth$)GZ!D&++DE6N2kQob8SD*1j2kVwA~0^S zLV-c!3$^g;a~gh;cavCy#x%*W!|v}{h1Yf|r!jBBfcu?Vc=v4`@9-T?%R6)~4;yg9 zR$f-YfNQ%C!GH~KfWL*Wg!>5n@fiN_{CUfjk+A%d!~;6L?(IY1#qSRIs0?jSr%JsS zL2Rz|y_MmmbSYyOaV5aL1fDwM`3oO=0i0YJcWknlPFc(CB)kSgRtk9V#`6&Lyx68( zsB-oMF<%*8@AxGdJGm{{XRvXi?u+5oH7(1w zH?PT+(j8Lg|7%$1SHtU^xV(_;w3g$UfK8=z241UW&W^s;jI&=3uYCLpa{EzO&HEbG zd~JBmLl&=-_v&k;bev^SuM5s z-DZ`QD@~akxcB<4gQz^wXBSn}Mg4P8yIfQq7j?o#fx9R`7p3DO!(HU2i`;UN6)twj z#n!smnlenmb1BILM^#3*l`|Q;)QamYV5tF<990>G4_d*sxvT2wEN4(=ggu=*r4S!MN=kz~sld@g#=uM7to-&dsU22}p`0I2uwT%CoriQ*|{9aPeTHC-WO6L9(=G=cw(+^Ybzg@$9 z(neVXzts`eir_bz8mdGfHh%cdjQqP?r$| z-yl8+%~1_J;iANrMQi?<23=(1aSzEFqWQH?dcswI1e}@cNXz>EB~8yIeZO4OAwwor z_6q}j(lA-czo4V0Rr1eiYLJxtVv;pPrRu^N(x=wWR4cso6ks+c^ZjQ)QKfMb-|yG- z!<6r#I1_B6EP{J5cmz}c;U!D78be48rSlIeVVk+^*#*)BpfM*7ZDeC8kO@D~D+LEt)E0&vqSsE$7eD z)F5Hc86<0iN8khf0_nmv-q!XsEcX=CrJh#ejVBA|+t3KZLHV1Su9+Ic5qjZ-Hd_|d zH*{^$3hG)-4Sg-B$$mkVa;>G}Hd!*iH$CDZihx>+%M4~5v@%Cx5Ni8vF`g?ReZ^TFxXsT>g$LQ#5Ilo9#gJe}l zkgOs4UynehSF67mbY-dJfx6)k)TQZ@sVU4eGX>FJSv0P$5n9o7YHH|f(M$~yO;>xd zwaspq1#_9XU@p=0$W$;bhJsDAQG*J3$1Of0$y+)E1pcTq-ni{HvqJFVq??80+tpX&H4YNrYolWKPZgiR@j9hu8s}fg;6`k&b&cA0|}QcwljJ=#)3LkQx)Vm z+lQY^YnT8Bj0EA{I-qFU8|H4cO8naeXBL;kk3Ej&WTmV?c? zd=O++%@0hu9CWX$;xe{T2AQ|(2x~cgfTjisWTum>4IWM>2^DIAlk%;}f^Ryr8EC2u zT~hUpnx2>nA-HK`i zx{k6|1lMS4=xY&7mPC-www6-hY3XzMf81OSk81j2Du;su^U!KJcrBHM@vx4(Rv5q5 z)X>+$*iRA$9=po`LLp4ab}{-}#>2))$l8dpJGenqEf2Y|vPg#MTA&rl9-12ZS|k%C zkyP*29ceC%!!#W+HICrIT(vN&_vsesXlunVS5re@i$R8|a;lhWbvoxCC7Xq9E{Qfx zUrZ&Thbgb6vQ4z=$ZLi1K1~f(!ce~wv$tpZVxrE<-kx8f?=aOzj_Z3NTten${ujc_ z&E@(94O>j*8u3CXwGJ7~UI;&@BdV3=#iRzqH|}~~2q%diguRd4W6tTjbe#_Mc&l2Y zs6@PvRJT*MpF4EKwH*IHO%0O${D5R_@QdL@se>?+2@LT60Fs99g@4m@#8l%W#+0gN z%3^p?M_Vg~ziMjeYcWjr_pf^DJL5)UN$d|<8!^?27*oPpDhp$(j=WYF`)O*Z5{7!9 zU}Fl!Hg#6rm{JeqP4q@!w6dVD)hXukJyFA+IxVfLnX+&<>1b<(yIxa+B;3fMy&f@) zg|)pf0i16xfO9onFcm=XcomyIOAVA+e~yl-mh~Uh)X>+g=N7Q=$S?uiY%YKsH61Y( zK*U(XEI>3<7Q+oX+FCJOr>UVz3~J0`@J2UF)L9w4{aUkefDK?9P9$DZgEyS~p{rie zh&^1E*skb3rk4#k%=VaGAX!6ZyzV6zR>i~FAH%dC0B2xX;CLQhq%s`hJ3(meUJ_rb zG6McAU>Gs?DyX9}CY?=X%Iy%e8{@mVH)Gn!uH@F z?x+lR((Mqe8~%bTK}cyYVI&O`WViRO0v6D?Sh;Mb2l6%*lHDHd9|0Yd@m`+=M0$6w2H*uYOq$B#xQ#)bY3;34c9kpakRc2Wx!CT zZ-H>LD;{BR_qtKbh$|;)e7_z9cPhjm7LmIW<%?n72y|bREqosw@ zO_~~z7z4ibBx{4;phkDW-7e|Y0J}d1q*Q7qvHN^Y2Ta*LEsWh><7B3vtD~r8`Z<~! z`kLuu=w31|4Kj{xZqhP$-9pd!yn0KZqLH1vdpsz9^G# zYDiZrV`j?Lqq;C0o(Kd~iw2mL^?STQR;DgvN!Ad+HC&tpevH{rZfmY)$WaYq$k>^_ z`X!DWZqQA}k%hFI)yf_=sGE0vq!&}t^GQ0XLERoT)2mzR@(Jc$-VmqDX7B4D>`Ci# z5bptwUclYPiwm9QE||?qR?yR+-tRp#@6l<7t0Nd4i4)t*IZ-so%FH28nO415Va%XC z6A-esJ&ZS(Hi$RlXJS;?_Hed*-k`6{CO%`3)yEd~_``-Os&?wEtk!i=%r-Z`(Kusm zrqNG@U*P=>;`ErAa`lq(-DAKy#^t+cC(V$@Sj#kK_*{b+FfG&!TMKp`BAm~cXHI`I z=g89rS(%1BMVZ$p<~Z)=#thi|2F)>yJ)?n`;ov>eAghl(YFlGwN!3uDwQ*)SUb35J zjEyU7^Oy#)eS&P8l!j!Wiwu~^4D<++wb7GAje%}y5EqmNx78^oh11NE`zEQ3BXg*n3@tB*Zut78UA)li+aaR$1#Y@qz0o@AvrG>G?;eO4+6 zNv3+80XrGzzeck5v#I{S2C+hEstaXP{i!)e?ls8DwB~Ngygo72zcq+QQKsr+&x;0q zW(xCHgRDOGsO^uLDpf;u*2bCY5L}P-UM~;$PGe>*LuUq-d8b3ghBK5YBx^sL;o=5$ zTxo`f%4Ya3bB-Kskdk z#1wziARa}TqK`elH0U!^n4cSD^|427U(6J#8mhB4&J>&Ik@{vh@h=9(VYf79U>ps5 zbQn*7)Gkd^_kj8h$H)Isz3Sg3p934zf2C0#E*s?xbB^q9kd^7jRFXAhL&A7%EP4g@ zxCZek$|!y8S!U2@W|YSoWc9H}ZE4IXsT!)YHqa>Pj%u@Sw%XkwhL4^p)h-!j$$)W; z$ET63{X9~Bwn6<@8l~?bbgwx_K4p-V>BlE1^ZI0@{9c226lIh?_S|C7XQnVW8D#ab zM{Q}$D5)B%vo_8sheJ4y=C*DzO8&V)%pNh5)hrp~GX@M}y!`{o+Rw%~>ej~05R}H~ zJMcRkC>qWgh8SdJdNGJ(?VAyDPJ?(9WsE-d%r@vVQ^blBckzn{%XW zkd^65fika8M$5|^#G@z!^|9v*27P7<^Erd8KK7`sju|LbLv_~18E6wkjBKXSM1^TS z&>)77o+;HX8RdNjjAK0h3CY^eM)`b$`afOiN-$5h%D&sd;lIIUnF_&BO@8= zI}KRL4D~3IwVw^OwLy$f8>-Lg=Y8fZImsX^Q<)Pe_xi+8&uI{oA`R8YpAQ;znyJj0 z23dXlQClA~RH}&Ttc^3&A#izy7&yPxAXX2ZiPcJmc)bCu7+1eevi7qfKG>j+s}0fT zz49}2mfUZUm8rx%lzV+*h_5t=Ns)%=E07CG~KjhUs46+>mfG%cWDI5U|>vi7rSE@==4)TZh4R(X#(OO7$f%9Laga48R7Yt6$Vy)%2a%Im_F4YQgEZ~kA8Yu$;Yq*!d!Q53t z-7E2H5BE#-7haORYCO5%1fF5owp9~Il#Nw`T@1^~qKpw3S z+OlA`mD8DasDT!}5WX=o$tOu2;ulsXeqpWR7gjHRAsz7x33|WEm9ZEc1n83X7ke-4 ztxVvtKzyl9?YXXGI@_KsC9!Fh!71`Jx{%A2T8lkhZMjUZdmXg1GJFI5by4r^4`Ci> zN}@8Rm~P9Yvz?3EAd)JCB;mi0wKKVH_&qEQfk{g6$LMxDl}Q$ocwQ5Jj%d%N@aSM~ z!kM0^?3pgEx8)2wDx+Fc4sZ(srSxv;t&D9=W^>skBBk6`8Ifyq?G&8&1d${LgH#8V zE2C0QGTUhv?Gow42=-IXGBTAe(N>@!XhHY+eFqJKYMvxt<;sv$K93c+=YvhVH$dmz z9q^abarfi!JK=r;KP#h1C)XC%=AmcfN_JO1lPuZmptoH`NEyRZ;E*c(c0WmqehNRK z^X{kNj~(ts@VTYey_kHJ+nfVMuiO;$PHOCxAZYxFCa?v*M-7GcO=yCTg%d#Mh)qCM z|J!fSpd_&j%#@rC&mWit9|sYh^}0F8N=%c z9#@8TB_Y0!lxeJ!EVkOGm5Hv<;>hqFguOcmUw05L?jZf%L3+7^G-(HE(GEg?N0}?9 z`voRO+KO3~DIIAzx@?znxy;sd3GU&AfG6HT>&o86ypztJ-a^f@*plxlIbb@K(QAp? zF9R&>>AeU#g{^W&q7J+<3ffod{ZMaZdPvn+e=9ql>fQ~UU`5BH=F9-ip+&>uf=ESM z$q_oa`~oQI-U^lzU7kzepE*+?-L)uM#hOfrWaMRdLr z(3#fNY*rVnlVLnbU#o6Hh~Ez&p4N1t*HI7C=SrOc=uAHY=#33vn2H#?!F3hcv7D;!U|FV{ix^3PUJu$+VCP zgo^q^HVMbwJz(6WCEpQJk}thVmoxgR*b7R#KTPo|0)s}?m2s@yI>D z49JONz(RSAV?sjdR5rQup8%JN|9zDE4`!_bHqV9HG! z5za}e4jKpCSH*vE!v5+-jaX!>C$m2$MLp&kyAhEtGrsMm<+dsw| z5}2hit&k(=$|`jzlyeusdxnY;)zM$&D&7mF-E|-5RZR9937PQY83k5^1iBoD?=Tm@ zI}D{dHKd4$(kBe8q?}$iPg)gHYV-z@!&(RH*1eRf zkCa=c{h7Fqyq{SCB4rF72LV?-R*?QPCY;ynx=`BPN~(Zg*b3GZ_=PpI>d))tuaT8u zu$>Ca3TNSa?eKILG^+?Ng^Zgx@b*^5FNei-TwU3eO`ocfgw!Z0??p z+EJMVi)qM8SSbTBx6(+n_+TIZ1Eh{k!yZ)j_CM=N=JT+YgiogUpOETWrRV$lpC>aJ ziDaNKZIM_!tW5S7hIOP;PoB1@`Vns|tVFiC55Q|~!u=V1!m`89$!d}N3;Ojd`t=+7 z^)UTsk8sXZrOV{lYaV$nqk5!Sdxx_yt28e7Uc{ z$62s>vcA`S4gQ2o5A8?3ehXg-_YwNzG5q07buNR|q-oA@SZdNN^gGQo->SjR6z5a4 zWYUQWV+{K$&V`Wiv~rtr#n;I}ri_lX3z<%mYx0LSOa_A}BlRXIGX|PD#F>T*Y0%Bl zY+-U3baw=-2sz_2_=4wB@CJ&qV%yQhy?0Jh~)nq zoBT5}`4+F!9ZQm#R2df|ix!SH7$J`Uti{)vESynU{6(P%e_2WE*kwy$sLa?_C%ocg z!iL3b=2*w#$CCBa3@_%&g_Pav z3`aE@?0gl9U6XLW=3K|>*)!qXkZ``4aK4prZcI4ec5ZTR2CMiE{J$mP+?sH{n{d9j zY7gi8tA;v1fGF8NOgKMEIRBS$Zc8|KI6rpobnbHQhVP#^_c-@D_c`}FKXo2(e$HzD zCFtI-QC)wNa2^8E4_5{s*y}u!a2`!Kk0qSnC7j0-&Jzje_X+38g!5Fw`2!Sq8fZTQ z|DRnm{vhX13Fpt1eVtM%UtBbIZr+9oI$a)Y$rU>1_Bziwe|4TuI4@MD@;tc6SZqn# zr4EwCDRpHa-%G1TIxi=jzd3(*UfJRNBjLQdW7h;Z_kSSqT5!%KmNS)?KaML>WxH?U zCG6#tW@n3aN^{OyyJ_RPO&eR6uUx$h6N=V`C5u-tYhAv0$;P$oG37Mt_)UvfuiSW2 z>&D~OFWYe3+SN-jx!c;jcKxbl>o?$!ZCk+N^5qg)+wshh{NhIS<~PLiZ*KXadVkv4 z?3{=ewE{4VB9b#ljmqI0;tWp09}44tH#8?6O1~3JaFpK4Wz7eRd@!NxPjJrQzbj2b zYFtiolE<+VG#o>2^#HdvKtA0NS%Q4)NIvJ2ydkvdjzIh)HBb$T3`0N~CgYvnh+vU9 z9bb-Sr5?zZ2RVqWG8`-Qnoz$gZjQKc#|;ulTnU?zyylG{3mwQw1?q ze04r}{cv$`@V$Xd3XS_5^(sO}JoRW-6%B-8ZdJO_sBu4vJI0O15{($+CN$^fSk2A3 za*0n+xW$A#@nGOUAa4Q#Ga#SIh_^q<7aZ|sNkiTY4+pv(xB}W|?fC)%f@kU`Sq1Ok ziJYt+#xOZrI|rIIFQxpCZ_P&$?zybIn4yeWYIh{z5|l;OjOH0!qsDuQPi?=n`Kj%f zG1pLh8+OCRfXTa$7z%ZYftFW;AkHSJxvBHPf{r_twkO7HVz1^R!buUAdz(9wsZy@M zr62al1C(olk_n)Em9!{YBXHQjdBv5q<$-yH3@8UK?#h+3B>^Pe=}g9Ivn{glp3kHq zrhZ!wZ@gh{0V}sd143X0lcQTd&|u|WDuwv4@*~1Mmz5W=vX_S-^XHL&E%Ug9!X626 zycjMHOx}IO@oJsopyk!Df$&0&Po1wec-g17V zx&LPdG;<)I$;@Ro$rqftNE4UQp2{xtbk&z8lyo`N6@nR~Pzo5|V%ZPNUR*Nt>x=#abJiLm^ zCcbW8Lb&I$@?tz}^1x+27m}PL*nfXG`!RXCx*5x`w`rB!Q|*JMGvHJ(q_0j4wr%B?uNVLu@v9;b|>JkfwQ}PK8UcU z-EE?%Q(abG>~4SDzq^gTA?)Tl*pwz4+$n3x+Qi0{D{z;3gSBDf;`JNx&t>rE+I9F> z-ddU12;11pmTYWYw|4c)B`0BO)xLPdF1T;wn~zpIS*xgJfw|uV>{m_1<$Z4o4Vry# zcQNWG9inx++;>r{j)6{hU_bSU(5r-9RF~J{0q_^b$vJ`L1XYuNv4MF>UsAhM$S*ru9Y(mcRWmfn3*Ux^xk

;g+G1s5y+4OoKs)9Uj(`zB0iA}F2`4l$2fi?@x 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 T@>m+$|os*mdKIqG$f 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

XW2?_9U7)43cUyYK-k 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%0D3pgRpI;WyTP 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 diff --git a/docs/_build/doctrees/index.doctree b/docs/_build/doctrees/index.doctree index 934fbac5c22624dfdcf3204746dcd1b794cc6f41..7ed5e1c04e0977751cb649510f7d7bf07bdf2647 100644 GIT binary patch delta 39 scmbQ_x6YTffpzL)wT-M{vW&))V`Pmvr)03lPRS7K0rNKN%RS}*00Pns!~g&Q delta 139 zcmZ4IJIRl=fpsdo`bO3;S;o}KF|x+i3U2vD3d#Aoxv52&$%#1%rNxQqsX7V;IjM=o ssX&RmlEmZ^g_4X^g~Za5jQpZvy(t;&u~Ra{dcgV(N!Gvll

CLI#

-

Calculates fragmentation features given a CRAM, BAM, SAM, or Frag.gz file.

+

FinaleToolkit is a package and standalone program to extract fragmentation features of cell-free DNA from paired-end sequencing data.

-
usage: finaletoolkit [-h] {coverage,frag-length,frag-length-bins,frag-length-intervals,wps,delfi,filter-bam,adjust-wps,agg-bw,delfi-gc-correct,end-motifs,interval-end-motifs,mds,interval-mds,gap-bed,cleavage-profile} ...
+
usage: finaletoolkit [-h] {coverage,frag-length-bins,frag-length-intervals,wps,delfi,filter-bam,adjust-wps,agg-bw,delfi-gc-correct,end-motifs,interval-end-motifs,mds,interval-mds,gap-bed,cleavage-profile} ...
 
-
-

subcommands#

-
-
subcommand
-

Possible choices: coverage, frag-length, frag-length-bins, frag-length-intervals, wps, delfi, filter-bam, adjust-wps, agg-bw, delfi-gc-correct, end-motifs, interval-end-motifs, mds, interval-mds, gap-bed, cleavage-profile

-
-
-

Sub-commands#

coverage#

-

Calculates fragmentation coverage over intervals in a BED file given a SAM, BAM, CRAM, or Frag.gz file

+

Calculates fragmentation coverage over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

finaletoolkit coverage [-h] [-o OUTPUT_FILE] [-s SCALE_FACTOR] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file interval_file
 
@@ -371,10 +363,10 @@

coverage#

input_file
-

SAM, BAM, CRAM, or Frag.gz file containing fragment data

+

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

interval_file
-

BED file containing intervals over which coverage is calculated

+

Path to a BED file containing intervals to calculate coverage over.

@@ -382,37 +374,39 @@

Positional ArgumentsNamed Arguments#

-o, --output_file
-

BED file where coverage is printed

+

A BED file containing coverage values over the intervals specified in interval file.

Default: “-”

-s, --scale-factor
-

Amount coverage will be multiplied by

+

Scale factor for coverage values.

Default: 1000000.0

-q, --quality_threshold
-

Default: 30

+

Minimum mapping quality threshold.

+

Default: 30

-w, --workers
-

Number of worker processes to use. Default is 1.

+

Number of worker processes.

Default: 1

-v, --verbose
-

Default: 0

+

Enable verbose mode to display detailed processing information.

+

Default: False

-
-

frag-length#

-

Calculates fragment lengths given a CRAM/BAM/SAM file

-
finaletoolkit frag-length [-h] [-c CONTIG] [-S START] [-E STOP] [-p INTERSECT_POLICY] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-v] input_file
+
+

frag-length-bins#

+

Retrieves fragment lengths grouped in bins given a BAM/SAM/CRAM/Fragment file.

+
finaletoolkit frag-length-bins [-h] [-c CONTIG] [-S START] [-p INTERSECT_POLICY] [-E STOP] [--bin-size BIN_SIZE] [-o OUTPUT_FILE] [--contig-by-contig] [--histogram] [-q QUALITY_THRESHOLD] [-v] input_file
 

Positional Arguments#

input_file
-

bam or frag.gz file containing fragment data.

+

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

@@ -420,72 +414,23 @@

Positional Arguments#

-c, --contig
-

contig or chromosome to select fragments from. Required if using –start or –stop.

+

Specify the contig or chromosome to select fragments from. (Required if using –start or –stop.)

-S, --start
-

0-based left-most coordinate of interval to select fragmentsfrom. Must also use –contig.

-
-
-E, --stop
-

1-based right-most coordinate of interval to select fragmentsfrom. Must also use –contig.

+

Specify the 0-based left-most coordinate of the interval to select fragments from. (Must also specify –contig.)

-p, --intersect_policy
-

Specifies what policy is used to include fragments in the given interval. Default is “midpoint”. Policies include: -- midpoint: the average of end coordinates of a fragment liesin the interval. -- any: any part of the fragment is in the interval.

-

Default: “midpoint”

-
-
-o, --output_file
-

File to write results to. “-” may be used to write to stdout. Default is “-“.

-

Default: “-”

-
-
-q, --quality_threshold
-

Minimum MAPQ. Default is 30.

-

Default: 30

-
-
-v, --verbose
-

Verbose logging.

-

Default: 0

-
-
-
-
-
-

frag-length-bins#

-

computes frag lengths of fragments and agregates in bins by length. Either writes bins and counts to tsv or prints a histogram

-
finaletoolkit frag-length-bins [-h] [-c CONTIG] [-S START] [-p INTERSECT_POLICY] [-E STOP] [--bin-size BIN_SIZE] [-o OUTPUT_FILE] [--contig-by-contig] [--histogram] [-q QUALITY_THRESHOLD] [-v] input_file
-
-
-
-

Positional Arguments#

-
-
input_file
-

BAM or SAM file containing fragment data

-
-
-
-
-

Named Arguments#

-
-
-c, --contig
-

contig or chromosome to select fragments from. Required if using –start or –stop.

-
-
-S, --start
-

0-based left-most coordinate of interval to select fragmentsfrom. Must also use –contig.

-
-
-p, --intersect_policy
-

Specifies what policy is used to include fragments in the given interval. Default is “midpoint”. Policies include: -- midpoint: the average of end coordinates of a fragment liesin the interval. -- any: any part of the fragment is in the interval.

+

Specifies what policy is used to include fragments in the given interval. See User Guide for more information.

Default: “midpoint”

-E, --stop
-

1-based right-most coordinate of interval to select fragmentsfrom. Must also use –contig.

+

Specify the 1-based right-most coordinate of the interval to select fragments from. (Must also specify –contig.)

--bin-size
-

Used to specify a custom bin size instead of automatically calculating one.

+

Specify the size of the bins to group fragment lengths into.

-o, --output_file
-

File to write results to. “-” may be used to write to stdout. Default is “-“.

+

A .TSV file containing containing fragment lengths binned according to the specified bin size.

Default: “-”

--contig-by-contig
@@ -493,15 +438,15 @@

Named Arguments

frag-length-intervals#

-

Calculates frag lengths statistics over user-specified genomic intervals.

+

Retrieves fragment length summary statistics over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

finaletoolkit frag-length-intervals [-h] [-p INTERSECT_POLICY] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file interval_file
 
-
-

Positional Arguments#

+
+

Positional Arguments#

input_file
-

BAM or SAM file containing PE WGS of cfDNA

+

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

interval_file
-

BED file containing intervals over which to produce statistics

+

Path to a BED file containing intervals to retrieve fragment length summary statistics over.

-
-

Named Arguments#

+
+

Named Arguments#

-p, --intersect_policy
-

Specifies what policy is used to include fragments in the given interval. Default is “midpoint”. Policies include: -- midpoint: the average of end coordinates of a fragment liesin the interval. -- any: any part of the fragment is in the interval.

+

Specifies what policy is used to include fragments in the given interval. See User Guide for more information.

Default: “midpoint”

-o, --output-file
-

File to print results to. if “-”, will print to stdout. Defaultis “-“.

+

A BED file containing fragment length summary statistics (mean, median, st. dev, min, max) over the intervals specified in the interval file.

Default: “-”

-q, --quality-threshold
-

minimum MAPQ to filter for

+

Minimum mapping quality threshold.

Default: 30

-w, --workers
-

Number of subprocesses to use

+

Number of worker processes.

Default: 1

-v, --verbose
-

Determines how much is written to stderr

+

Enable verbose mode to display detailed processing information.

Default: 0

@@ -554,87 +497,93 @@

Named Arguments

wps#

-

Calculates Windowed Protection Score over a region around sites specified in a BED file from alignments in a CRAM/BAM/SAM/Frag.gz file

+

Calculates Windowed Protection Score (WPS) over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

finaletoolkit wps [-h] [-o OUTPUT_FILE] [-i INTERVAL_SIZE] [-W WINDOW_SIZE] [-lo FRACTION_LOW] [-hi FRACTION_HIGH] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file site_bed
 
-
-

Positional Arguments#

+
+

Positional Arguments#

input_file
-

bam or sam file containing paired-end reads of cfDNA WGS

+

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

site_bed
-

bed file containing sites over which to calculate wps

+

Path to a BED file containing intervals to calculate WPS over.

-
-

Named Arguments#

+
+

Named Arguments#

-o, --output_file
-

BigWig file to write results to. Default is stdout

+

A bigWig file containing the WPS results over the intervals specified in interval file.

Default: “-”

-i, --interval_size
-

Default: 5000

+

Size in bp of each interval in the interval file.

+

Default: 5000

-W, --window_size
-

Default: 120

+

Size of the sliding window used to calculate WPS scores.

+

Default: 120

-lo, --fraction_low
-

Default: 120

+

Minimum length for a fragment to be included in WPS calculation.

+

Default: 120

-hi, --fraction_high
-

Default: 180

+

Maximum length for a fragment to be included in WPS calculation.

+

Default: 180

-q, --quality_threshold
-

Default: 30

+

Minimum mapping quality threshold.

+

Default: 30

-w, --workers
-

Default: 1

+

Number of worker processes.

+

Default: 1

-v, --verbose
-

Default: 0

+

Enable verbose mode to display detailed processing information.

+

Default: 0

delfi#

-

Calculates DELFI score over genome. -NOTE: due to some ad hoc implementation details, currently the only accepted reference genome is hg19.

+

Calculates DELFI score over genome. NOTE: Due to some ad hoc implementation details, currently the only accepted reference genome is hg19.

finaletoolkit delfi [-h] [-b BLACKLIST_FILE] [-g GAP_FILE] [-o OUTPUT_FILE] [-W WINDOW_SIZE] [-gc] [-m] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file autosomes reference_file bins_file
 
-
-

Positional Arguments#

+
+

Positional Arguments#

input_file
-

SAM, BAM, CRAM, or Frag.gz file containing fragment reads.

+

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

autosomes
-

Tab-delimited file where column one is chromosomes and column two is the length of said chromosome.

+

Tab-delimited file containing (1) autosome name and (2) integer length of chromosome in base pairs.

reference_file
-

2bit file for reference sequence used during alignment.

+

The .2bit file for the associate reference genome sequence used during alignment.

bins_file
-

BED format file containing bins over which to calculate delfi. To replicate Cristiano and colleage’s methodology, use 100kb bins over human autosomes.

+

A BED file containing bins over which to calculate DELFI. To replicate Cristiano et al.’s methodology, use 100kb bins over human autosomes.

-
-

Named Arguments#

+
+

Named Arguments#

-b, --blacklist_file
-

BED file containing darkregions to ignore when calculating DELFI.

+

BED file containing regions to ignore when calculating DELFI.

-g, --gap_file
-

BED4 format file with columns “chrom”,”start”,”stop”,”type”. “type” should be “centromere”, “telomere”, or “short arm”; all others are ignored. This information corresponds to “gap” track for hg19 in UCSC Genome Browser.

+

BED4 format file containing columns for “chrom”, “start”, “stop”, and “type”. The “type” column should denote whether the entry corresponds to a “centromere”, “telomere”, or “short arm”, and entries not falling into these categories are ignored. This information corresponds to the “gap” track for hg19 in the UCSC Genome Browser.

-o, --output_file
-

BED, bed.gz, tsv, or csv file to write results to. If “-”, writes tab-deliniated data to stdout. Default is “-“.

+

BED, bed.gz, TSV, or CSV file to write results to. If “-”, writes to stdout.

Default: “-”

-W, --window_size
@@ -642,23 +591,24 @@

Named Arguments
finaletoolkit filter-bam [-h] [-r REGION_FILE] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-hi FRACTION_HIGH] [-lo FRACTION_LOW] [-w WORKERS] [-v] input_file
 

-
-

Positional Arguments#

+
+

Positional Arguments#

input_file
-

BAM file with PE WGS

+

Path to BAM file.

-
-

Named Arguments#

+
+

Named Arguments#

-r, --region-file
-

BED file containing regions to read fragments from. Default is None.

+

Only output alignments overlapping the intervals in this BED file will be included.

-o, --output-file
-

Path to write filtered BAM. Defualt is “-”. If set to “-”, the BAM file will be written to stdout.

+

Output BAM file path.

Default: “-”

-q, --quality_threshold
-

Minimum mapping quality to filter for. Defualt is 30.

+

Minimum mapping quality threshold.

Default: 30

-hi, --fraction-high
-

Maximum fragment size. Default is None

+

Maximum length for a fragment to be included in output BAM.

-lo, --fraction-low
-

Minimum fragment size. Default is None

+

Minimum length for a fragment to be included in output BAM.

-w, --workers
-

Number of worker processes to spawn.

+

Number of worker processes.

Default: 1

-v, --verbose
-

Specify verbosity. Number of printed statements is proportional to number of vs.

+

Enable verbose mode to display detailed processing information.

adjust-wps#

-

Reads WPS data from a WIG file and applies a median filter and a Savitsky-Golay filter (Savitsky and Golay, 1964).

+

Adjusts raw Windowed Protection Score (WPS) by applying a median filter and Savitsky-Golay filter.

finaletoolkit adjust-wps [-h] [-o OUTPUT_FILE] [-m MEDIAN_WINDOW_SIZE] [-s SAVGOL_WINDOW_SIZE] [-p SAVGOL_POLY_DEG] [-w WORKERS] [--mean] [--subtract-edges] [-v] input_file interval_file genome_file
 
-
-

Positional Arguments#

+
+

Positional Arguments#

input_file
-

BigWig file with WPS data.

+

A bigWig file containing the WPS results over the intervals specified in interval file.

interval_file
-

BED file containing intervals over which wps was calculated

+

Path to a BED file containing intervals to WPS was calculated over.

genome_file
-

GENOME file containing chromosome/contig names and lengths. Needed to write head for BigWig.

+

A .chrom.sizes file containing chromosome sizes.

-
-

Named Arguments#

+
+

Named Arguments#

-o, --output-file
-

WIG file to print filtered WPS data. If “-”, will write to stdout. Default is “-“.

+

A bigWig file containing the adjusted WPS results over the intervals specified in interval file.

Default: “-”

-m, --median-window-size
-

Size of window for median filter. Default is 1000.

+

Size of the median filter window used to adjust WPS scores.

Default: 1000

-s, --savgol-window-size
-

Size of window for Savitsky-Golay filter. Default is 21.

+

Size of the Savitsky-Golay filter window used to adjust WPS scores.

Default: 21

-p, --savgol-poly-deg
-

Degree polynomial for Savitsky-Golay filter. Default is 2.

+

Degree polynomial for Savitsky-Golay filter.

Default: 2

-w, --workers
-

Number of subprocesses to use. Default is 1.

+

Number of worker processes.

Default: 1

--mean
-

Default: False

+

A mean filter is used instead of median.

+

Default: False

--subtract-edges
-

Default: False

+

Take the median of the first and last 500 bases in a window and subtract from the whole interval.

+

Default: False

-v, --verbose
-

Specify verbosity. Number of printed statements is proportional to number of vs.

+

Enable verbose mode to display detailed processing information.

agg-bw#

-

Reads data from a BigWig file and aggregates over intervals in a BED file.

+

Aggregates a bigWig signal over constant-length intervals defined in a BED file.

finaletoolkit agg-bw [-h] [-o OUTPUT_FILE] [-m MEDIAN_WINDOW_SIZE] [-v] input_file interval_file
 
-
-

Positional Arguments#

+
+

Positional Arguments#

input_file
-

BigWig file with data.

+
+

A bigWig file containing signals over the intervals specified in interval file.

+
interval_file
-

BED file containing intervals over which wps was calculated

+

Path to a BED file containing intervals over which signals were calculated over.

-
-

Named Arguments#

+
+

Named Arguments#

-o, --output-file
-

WIG file to print filtered WPS data. If “-”, will write to stdout. Default is “-“.

+

A wiggle file containing the aggregate signal over the intervals specified in interval file.

Default: “-”

-m, --median-window-size
-

Size of window for median filter. Default is 1000.

-

Default: 1000

+

Size of the median filter window used to adjust WPS scores. Only modify if aggregating WPS signals.

+

Default: 0

-v, --verbose
-

Specify verbosity. Number of printed statements is proportional to number of vs.

+

Enable verbose mode to display detailed processing information.

@@ -802,16 +756,16 @@

delfi-gc-correct
finaletoolkit delfi-gc-correct [-h] [-o OUTPUT_FILE] [--header-lines HEADER_LINES] [-v] input_file
 

-
-

Positional Arguments#

+
+

Positional Arguments#

input_file

BED3+3 file containing raw data

-
-

Named Arguments#

+
+

Named Arguments#

-o, --output-file

BED3+3 to print GC-corrected DELFI fractions. If “-”, will write to stdout. Default is “-“.

@@ -833,8 +787,8 @@

end-motifs
finaletoolkit end-motifs [-h] [-k K] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file refseq_file
 
-
-

Positional Arguments#

+
+

Positional Arguments#

input_file

SAM, BAM, or tabix-indexed file with fragment data.

@@ -844,8 +798,8 @@

Positional Arguments -

Named Arguments#

+
+

Named Arguments#

-k

Length of k-mer. Default is 4.

@@ -876,8 +830,8 @@

interval-end-motifs
finaletoolkit interval-end-motifs [-h] [-k K] [-lo FRACTION_LOW] [-hi FRACTION_HIGH] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file refseq_file intervals
 
-
-

Positional Arguments#

+
+

Positional Arguments#

input_file

SAM, BAM, or tabix-indexed file with fragment data.

@@ -890,8 +844,8 @@

Positional Arguments -

Named Arguments#

+
+

Named Arguments#

-k

Length of k-mer. Default is 4.

@@ -930,8 +884,8 @@

mds#
finaletoolkit mds [-h] [-s SEP] [--header HEADER] [file_path]
 
-
-

Positional Arguments#

+
+

Positional Arguments#

file_path

Tab-delimited or similar file containing one column for all k-mers a one column for frequency. Reads from stdin by default.

@@ -939,8 +893,8 @@

Positional Arguments -

Named Arguments#

+
+

Named Arguments#

-s, --sep

Separator used in tabular file. Default is tab.

@@ -959,8 +913,8 @@

interval-mds
finaletoolkit interval-mds [-h] [-s SEP] [file_path] file_out
 
-
-

Positional Arguments#

+
+

Positional Arguments#

file_path

Tab-delimited or similar file containing one column for all k-mers a one column for frequency. Reads from stdin by default.

@@ -971,8 +925,8 @@

Positional Arguments -

Named Arguments#

+
+

Named Arguments#

-s, --sep

Separator used in tabular file. Default is tab.

@@ -987,8 +941,8 @@

gap-bed
finaletoolkit gap-bed [-h] {hg19,b37,human_g1k_v37,hg38,GRCh38} output_file
 
-
-

Positional Arguments#

+
+

Positional Arguments#

reference_genome

Possible choices: hg19, b37, human_g1k_v37, hg38, GRCh38

@@ -1007,8 +961,8 @@

cleavage-profile
finaletoolkit cleavage-profile [-h] [-o OUTPUT_FILE] [-lo FRACTION_LOW] [-hi FRACTION_HIGH] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file interval_file
 
-
-

Positional Arguments#

+
+

Positional Arguments#

input_file

BAM, CRAM, or frag.gz containing fragment coordinates.

@@ -1018,8 +972,8 @@

Positional Arguments -

Named Arguments#

+
+

Named Arguments#

-o, --output_file

Path to write output file to. If “-” used, writes bed.gz to stdout. Writes in BigWig format if “.bw” or “.bigwig” used, and writes in gzip compressed bed file if “.bed.gz” or “.bedGraph.gz” suffixes used. Default is “-“.

@@ -1095,85 +1049,79 @@

Named Arguments

diff --git a/docs/_build/html/searchindex.js b/docs/_build/html/searchindex.js index 87521085..b947a960 100644 --- a/docs/_build/html/searchindex.js +++ b/docs/_build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["_documentation/api_reference/basicfeatures", "_documentation/api_reference/cleavageprofile", "_documentation/api_reference/delfi", "_documentation/api_reference/endmotifs", "_documentation/api_reference/fragfile", "_documentation/api_reference/genomeutils", "_documentation/api_reference/index", "_documentation/api_reference/wps", "_documentation/cli_reference/index", "_documentation/user_guide/features", "_documentation/user_guide/help", "_documentation/user_guide/index", "_documentation/user_guide/inputdata", "_documentation/user_guide/installation", "_documentation/user_guide/quickstart", "_documentation/user_guide/structure", "_documentation/user_guide/what", "index"], "filenames": ["_documentation/api_reference/basicfeatures.rst", "_documentation/api_reference/cleavageprofile.rst", "_documentation/api_reference/delfi.rst", "_documentation/api_reference/endmotifs.rst", "_documentation/api_reference/fragfile.rst", "_documentation/api_reference/genomeutils.rst", "_documentation/api_reference/index.rst", "_documentation/api_reference/wps.rst", "_documentation/cli_reference/index.rst", "_documentation/user_guide/features.rst", "_documentation/user_guide/help.rst", "_documentation/user_guide/index.rst", "_documentation/user_guide/inputdata.rst", "_documentation/user_guide/installation.rst", "_documentation/user_guide/quickstart.rst", "_documentation/user_guide/structure.rst", "_documentation/user_guide/what.rst", "index.rst"], "titles": ["Basic Features", "Cleavage Profile", "DELFI", "End-Motifs", "Frag File Utilities", "Genome Utilities", "API", "Window Protection Score (WPS)", "CLI", "Features", "Help", "User Guide", "Input Data", "Installation", "Quickstart", "Structure", "Introduction", "FinaleToolkit"], "terms": {"finaletoolkit": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 14, 15, 16], "frag": [0, 1, 2, 3, 6, 7, 12, 14, 17], "coverag": [0, 6, 11], "input_fil": [0, 1, 2, 3, 4, 7, 8], "str": [0, 1, 2, 3, 4, 5, 7], "alignmentfil": [0, 4, 7], "interval_fil": [0, 4, 7, 8], "output_fil": [0, 2, 3, 4, 5, 7, 8], "scale_factor": [0, 8], "float": [0, 2, 3], "1000000": [0, 8], "0": [0, 1, 2, 3, 4, 7, 8], "quality_threshold": [0, 1, 2, 3, 4, 7, 8], "int": [0, 1, 2, 3, 4, 5, 7], "30": [0, 1, 2, 3, 4, 7, 8], "worker": [0, 2, 3, 4, 7, 8], "1": [0, 1, 2, 3, 4, 7, 8], "verbos": [0, 1, 2, 3, 4, 7, 8], "bool": [0, 1, 2, 3, 4, 5, 7], "fals": [0, 2, 3, 4, 5, 7, 8], "estim": 0, "fragment": [0, 2, 3, 7, 8, 11, 15, 16, 17], "over": [0, 3, 7, 8, 9], "interv": [0, 2, 3, 4, 5, 7], "specifi": [0, 3, 4, 5, 7, 8], "ar": [0, 3, 4, 5, 8, 9, 10, 13, 15, 16], "read": [0, 2, 3, 4, 5, 7, 8, 9, 12, 15], "from": [0, 3, 5, 7, 8, 9, 12, 14, 16, 17], "which": [0, 2, 4, 7, 8, 9, 16], "mai": [0, 8], "sam": [0, 3, 7, 8, 11, 15], "bam": [0, 2, 3, 4, 7, 11, 15], "cram": [0, 3, 8, 11, 15], "gz": [0, 3, 8, 12], "file": [0, 2, 3, 5, 6, 7, 8, 11, 15, 17], "us": [0, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 14, 16], "an": [0, 3, 4, 5, 9, 10, 12, 13], "algorithm": 0, "where": [0, 2, 4, 5, 7, 8], "midpoint": [0, 8], "calcul": [0, 3, 7, 8, 9], "i": [0, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17], "tabul": [0, 8], "fall": [0, 9], "region": [0, 3, 4, 7, 8, 9], "Not": 0, "suitabl": 0, "size": [0, 2, 3, 4, 7, 8], "approach": [0, 4, 16], "pysam": [0, 7], "contain": [0, 2, 3, 4, 5, 7, 8, 12], "pair": [0, 3, 4, 7, 8, 9, 12, 17], "end": [0, 4, 5, 6, 7, 11, 12, 17], "its": [0, 3, 7, 14], "path": [0, 2, 3, 4, 5, 7, 8], "must": [0, 7, 8, 10], "open": [0, 7, 10, 14], "mode": [0, 7], "bed4": [0, 2, 5, 8], "gener": [0, 3, 5, 8, 15], "statist": [0, 8, 9], "string": [0, 2, 3, 4, 5, 7], "option": [0, 2, 3, 4, 5, 7], "bed": [0, 2, 3, 4, 5, 7], "print": [0, 2, 3, 5, 8], "If": [0, 5, 7, 8, 10, 13, 14, 17], "_": 0, "result": [0, 3, 5, 8, 9, 12], "stdout": [0, 2, 5, 8], "amount": [0, 8], "multipli": [0, 8], "default": [0, 2, 3, 4, 7, 8], "10": [0, 3, 8], "6": 0, "contig": [0, 1, 3, 4, 5, 7, 8], "frag_length": [0, 6], "tabixfil": 0, "none": [0, 2, 3, 4, 5, 7, 8], "start": [0, 1, 3, 4, 5, 7, 8, 9, 11, 12], "stop": [0, 1, 3, 5, 7, 8, 12], "intersect_polici": [0, 8], "ndarrai": [0, 1, 4, 7], "np": [0, 7], "length": [0, 3, 4, 7, 11], "abov": 0, "qualiti": [0, 3, 4, 8, 12, 15], "threshold": [0, 4, 8], "proper": [0, 4], "chromosom": [0, 2, 3, 5, 7, 8], "get": [0, 11, 13], "base": [0, 3, 5, 7, 8, 9], "left": [0, 8], "most": [0, 8], "coordin": [0, 3, 5, 7, 8, 9], "right": [0, 8], "what": [0, 8, 15], "polici": [0, 8], "includ": [0, 3, 5, 7, 8, 9, 10, 15], "given": [0, 3, 4, 5, 8], "averag": [0, 8], "li": [0, 17], "ani": [0, 3, 8, 12, 13], "part": [0, 8], "numpi": [0, 7], "frag_length_bin": [0, 6], "bin_siz": [0, 8], "contig_by_contig": 0, "histogram": [0, 8], "tupl": [0, 3, 4, 5, 8], "take": [0, 2, 3, 4, 5, 7, 15], "comput": [0, 8, 16], "two": [0, 3, 4, 8], "arrai": [0, 7], "bin": [0, 2], "count": [0, 3, 8, 9], "data": [0, 2, 3, 4, 7, 8, 11, 16, 17], "output": [0, 2, 5, 8, 10], "tab": [0, 3, 7, 8, 12], "delimit": [0, 3, 7, 8], "tabl": [0, 3, 8], "cleavage_profil": [1, 6], "fraction_low": [1, 3, 7, 8], "fraction_high": [1, 3, 7, 8], "10000000": 1, "autosom": [2, 8], "bins_fil": [2, 8], "reference_fil": [2, 8], "blacklist_fil": [2, 8], "gap_fil": [2, 8], "union": [2, 7], "genomegap": [2, 5, 6], "gc_correct": [2, 8], "true": [2, 3, 5, 7], "merge_bin": [2, 8], "window_s": [2, 7, 8], "5000000": [2, 8], "subsample_coverag": 2, "2": [2, 4, 7, 8, 12], "preprocess": 2, "panda": 2, "datafram": 2, "A": [2, 3, 7, 10, 12, 15, 17], "function": [2, 3, 4, 7, 8, 14, 15], "replic": [2, 3, 8], "methodologi": [2, 3, 8], "christiano": 2, "et": [2, 3, 7, 8, 9], "al": [2, 3, 7, 8, 9], "2019": [2, 9], "point": [2, 4], "pe": [2, 3, 8], "genom": [2, 3, 4, 6, 7, 8, 9, 12, 16, 17], "onli": [2, 3, 8, 13], "100kb": [2, 8], "refer": [2, 3, 5, 7, 8, 12, 16, 17], "choic": [2, 8], "cristiano": [2, 8, 9], "2bit": [2, 3, 8], "blacklist": [2, 4], "each": [2, 3, 4, 7, 8, 12], "centromer": [2, 5, 8], "telomer": [2, 5, 8], "can": [2, 4, 9, 10, 12, 13, 14, 16], "fourth": 2, "field": 2, "entri": [2, 12, 17], "correspond": [2, 3, 8], "labl": 2, "respect": 2, "tsv": [2, 3, 8], "non": [2, 16], "overlap": [2, 5, 9], "window": [2, 4, 6, 8, 11, 16, 17], "cover": 2, "5": [2, 3, 4, 8], "megabas": 2, "The": [2, 7, 9, 10, 12, 13, 14, 15], "depth": 2, "subsampl": 2, "input_bam": [2, 4], "number": [2, 3, 7, 8, 9], "process": [2, 3, 7, 8, 15], "determin": [2, 8], "how": [2, 8], "mani": 2, "statement": [2, 8], "load": [2, 14], "bar": 2, "appear": 2, "delfi_gc_correct": [2, 6], "alpha": 2, "75": 2, "8": [2, 13], "helper": 2, "perform": [2, 7, 8], "gc": [2, 9], "adjust": [2, 4, 7], "delfi_merge_bin": [2, 6], "hundred_kb_bin": 2, "add_chr": 2, "class": [3, 5], "endmotiffreq": [3, 6], "kmer_frequ": 3, "iter": [3, 5], "k": [3, 7, 8, 9], "20": [3, 8], "store": [3, 12], "frequenc": [3, 8, 9], "mer": [3, 8, 9], "method": [3, 5, 7], "manipul": 3, "thi": [3, 4, 5, 8, 9, 12, 15, 16], "repres": 3, "minimum": [3, 8], "map": [3, 8, 9, 12, 15], "classmethod": [3, 5], "from_fil": 3, "file_path": [3, 8], "sep": [3, 8], "t": 3, "header": [3, 8], "kmer": 3, "column": [3, 4, 7, 8, 12], "line": [3, 8], "ignor": [3, 8], "head": [3, 8], "kmer_freq": 3, "motif_diversity_scor": 3, "divers": [3, 8, 11, 16], "score": [3, 6, 8, 11, 16, 17], "md": [3, 11, 16], "normal": [3, 8, 9], "shannon": [3, 8, 9], "entropi": [3, 8, 9], "describ": [3, 7, 8, 17], "jiang": [3, 8, 9], "2020": [3, 8, 9], "instead": [3, 4, 7, 8], "just": [3, 8], "4": [3, 8], "to_tsv": 3, "endmotifsinterv": [3, 6], "dict": 3, "user": [3, 8, 16, 17], "collect": 3, "chrom": [3, 4, 8, 12], "freq": 3, "list": [3, 4, 8], "associ": [3, 9, 12, 16], "frquenci": 3, "form": 3, "expect": 3, "name": [3, 4, 5, 7], "becaus": [3, 5], "export": 3, "turn": 3, "fraction": [3, 7, 8], "doesn": 3, "perfectli": 3, "other": [3, 5, 8, 9, 15], "mapq": [3, 8, 12], "filter": [3, 4, 7, 15], "some": [3, 8], "mds_bed": 3, "write": [3, 5, 7, 8], "bedgraph": [3, 8], "to_b": [3, 5], "calc_freq": 3, "otherwis": [3, 16], "separ": [3, 8, 12], "to_bedgraph": 3, "all": [3, 4, 8, 9, 12, 14], "region_end_motif": [3, 6], "refseq_fil": [3, 8], "600": [3, 8], "both_strand": 3, "tabix": [3, 7, 8, 12], "index": [3, 8, 12], "dictionari": 3, "reproduc": [3, 10], "zhou": [3, 9], "2023": 3, "sequenc": [3, 5, 8, 9, 12, 16, 17], "wa": [3, 4, 7, 8, 9], "align": [3, 5, 7, 8, 12], "maximum": [3, 8], "choos": 3, "whether": 3, "forward": 3, "both": [3, 4], "end_motif_freq": 3, "end_motif": [3, 6], "either": [3, 8, 12], "csv": [3, 8], "interval_end_motif": [3, 6], "endmotifinterv": 3, "filter_bam": [4, 6], "region_fil": [4, 8], "max_length": 4, "min_length": 4, "accept": [4, 8], "creat": [4, 5, 8], "read1": [4, 8], "exce": [4, 8], "do": [4, 14], "intersect": [4, 5], "genome2list": [4, 6], "genome_fil": [4, 7, 8], "text": [4, 10], "format": [4, 7, 8, 12], "agg_bw": [4, 6], "median_window_s": [4, 7, 8], "mean": [4, 7, 8], "strand_loc": 4, "bigwig": [4, 7, 8], "aggreg": [4, 7, 8], "signal": 4, "along": 4, "For": [4, 12, 17], "wp": [4, 6, 11, 16, 17], "note": [4, 8], "median": [4, 7, 8], "trim": 4, "half": 4, "while": [4, 15], "There": 4, "wai": [4, 5], "suppli": 4, "smaller": [4, 12], "e": [4, 5, 8, 15, 16], "g": [4, 8, 16], "you": [4, 10, 12, 13, 14, 15], "5kb": 4, "1kb": 4, "4kb": 4, "provid": [4, 8, 12, 16], "origin": [4, 9, 16], "were": [4, 8], "onc": 4, "strand": [4, 12], "agg_scor": 4, "gaps_b": 5, "short_arm": 5, "ucsc": [5, 8], "gap": 5, "track": [5, 8], "hg19": [5, 8], "hg38": [5, 8], "b37": [5, 8], "broad": 5, "institut": 5, "grch37": 5, "also": [5, 8, 13], "differ": [5, 16], "few": 5, "absenc": 5, "chr": 5, "prefix": 5, "we": [5, 12, 14, 15], "ad": [5, 8, 16], "hoc": [5, 8, 16], "drop": 5, "between": [5, 9], "perfect": 5, "solut": [5, 16], "get_arm": 5, "arm": [5, 8], "short": [5, 8, 9], "acrocentr": 5, "empti": 5, "valueerror": 5, "invalid": 5, "get_contig_gap": 5, "contiggap": [5, 6], "make": [5, 10, 15], "synonym": 5, "grch38": [5, 8], "in_tcmer": 5, "check": 5, "in_telomere_or_centromer": 5, "overlaps_gap": 5, "type": [5, 8, 14], "gzip": [5, 8, 12], "writ": 5, "ucsc_hg19": 5, "version": [5, 10, 12, 13], "has_short_arm": 5, "noarm": 5, "in_gap": 5, "ucsc_hg19_gap_b": [5, 6], "b37_gap_b": [5, 6], "human_g1k_v37": [5, 8], "1000": [5, 7, 8], "project": [5, 17], "ucsc_hg38_gap_b": [5, 6], "basic": [6, 17], "featur": [6, 8, 11, 16, 17], "protect": [6, 8, 11, 16, 17], "multi_wp": [6, 7], "adjust_wp": [6, 7], "delfi": [6, 11, 14, 16, 17], "motif": [6, 11, 16, 17], "cleavag": [6, 11, 17], "profil": [6, 11, 17], "util": [6, 17], "120": [7, 8, 9], "180": [7, 8], "raw": [7, 8, 9], "snyder": [7, 9], "2016": [7, 9], "equival": 7, "l": 7, "lowest": 7, "long": [7, 9], "highest": 7, "shape": 7, "n": 7, "site_b": [7, 8], "interval_s": [7, 8], "5000": [7, 8], "site": [7, 8, 9], "accord": [7, 9], "should": [7, 8, 12], "same": [7, 8, 9, 12], "everi": 7, "interb": 7, "savgol_window_s": [7, 8], "21": [7, 8], "savgol_poly_deg": [7, 8], "subtract_edg": 7, "edge_s": 7, "500": 7, "appli": [7, 8], "savitski": [7, 8], "golai": [7, 8], "1964": [7, 8], "wg": [7, 8, 16], "degre": [7, 8], "polynomi": [7, 8], "first": 7, "last": 7, "subtract": [7, 8, 9], "whole": [7, 16], "usag": [8, 15, 17], "h": 8, "possibl": [8, 9, 15], "o": 8, "": [8, 9, 13], "q": 8, "w": 8, "v": 8, "scale": 8, "factor": 8, "c": 8, "p": 8, "select": 8, "requir": [8, 12], "fragmentsfrom": 8, "liesin": 8, "log": 8, "agreg": 8, "custom": 8, "automat": 8, "one": [8, 12], "placehold": 8, "implement": 8, "draw": 8, "termin": [8, 13, 14], "cfdna": [8, 9, 16], "produc": 8, "defaulti": 8, "subprocess": 8, "much": 8, "written": [8, 17], "stderr": 8, "around": [8, 9], "lo": 8, "hi": 8, "due": 8, "detail": [8, 13], "current": 8, "b": 8, "m": 8, "said": 8, "dure": [8, 13], "To": [8, 10], "colleag": 8, "human": [8, 12], "darkregion": 8, "when": [8, 13], "inform": [8, 10, 12], "browser": 8, "delini": 8, "unus": 8, "indic": 8, "whther": 8, "merg": 8, "5mb": 8, "spawn": 8, "close": 8, "core": 8, "so": [8, 14], "certain": [8, 9], "flag": 8, "secondari": 8, "supplementari": 8, "mate": 8, "r": 8, "defualt": 8, "set": 8, "high": 8, "low": [8, 15], "proport": [8, 9], "wig": 8, "edg": 8, "need": 8, "savgol": 8, "poli": 8, "deg": 8, "header_lin": 8, "bed3": [8, 12], "3": [8, 13], "measur": 8, "smallest": 8, "consid": 8, "longest": 8, "similar": [8, 12], "stdin": 8, "tabular": 8, "row": [8, 12], "file_out": 8, "annot": 8, "found": [8, 9], "kent": 8, "2002": 8, "support": [8, 9], "reference_genom": 8, "liber": 8, "case": 8, "longer": 8, "wip": 8, "compress": [8, 12], "suffix": 8, "ha": [9, 16, 17], "follow": [9, 10, 12, 13, 14, 15], "cell": [9, 16, 17], "free": [9, 16, 17], "dna": [9, 16, 17], "distribut": 9, "summari": 9, "specif": [9, 10, 14], "total": 9, "sampl": 9, "simpli": 9, "valu": [9, 12], "metric": 9, "design": [9, 15, 16], "It": [9, 12, 15, 16], "quantifi": 9, "level": 9, "across": 9, "assess": 9, "fulli": 9, "span": 9, "defin": 9, "typic": 9, "center": 9, "particular": 9, "endpoint": 9, "within": 9, "correl": 9, "locat": 9, "nucleosom": 9, "transcript": 9, "tss": 9, "dnase": 9, "hypersensit": 9, "dhss": 9, "introduc": 9, "identifi": 9, "abnorm": 9, "pattern": [9, 16], "In": [9, 16], "paper": [9, 17], "categor": 9, "patient": 9, "cancer": [9, 16], "tumor": [9, 16], "tissu": [9, 16], "ratio": 9, "correct": 9, "sinc": 9, "thei": 9, "potenti": 9, "detect": [9, 16], "condit": [9, 16], "diseas": [9, 16], "2022": 9, "definit": 9, "nucleotid": 9, "author": [9, 17], "show": 9, "relationship": 9, "methyl": 9, "cpg": 9, "think": 10, "ve": 10, "encount": 10, "bug": [10, 17], "pleas": [10, 13, 17], "report": [10, 17], "github": [10, 13, 17], "issu": [10, 13, 17], "tracker": 10, "code": [10, 16, 17], "exampl": [10, 12], "demonstr": 10, "problem": 10, "see": 10, "ex": [10, 16], "error": [10, 11], "messag": 10, "clear": 10, "explan": 10, "why": 10, "someth": 10, "wrong": 10, "work": 10, "search": 10, "befor": 10, "new": 10, "often": [10, 16], "solv": 10, "quickli": 10, "avoid": 10, "duplic": 10, "introduct": [11, 17], "input": [11, 17], "instal": [11, 17], "prerequisit": 11, "structur": [11, 17], "quickstart": [11, 17], "import": 11, "modul": 11, "help": [11, 17], "compat": 12, "almost": 12, "readabl": 12, "about": 12, "well": [12, 16], "itself": [12, 14], "binari": 12, "save": 12, "space": 12, "disk": 12, "bai": 12, "therefor": [12, 15], "have": [12, 16], "directori": 12, "your": [12, 15], "than": [12, 13], "still": 12, "crai": 12, "deriv": 12, "block": 12, "here": [12, 17], "tbi": 12, "chr1": 12, "10000": 12, "10050": 12, "60": 12, "10100": 12, "10150": 12, "10200": 12, "10250": 12, "10300": 12, "10350": 12, "10400": 12, "10450": 12, "10500": 12, "encourag": 12, "our": 12, "comprehens": [12, 16], "databas": 12, "finaledb": 12, "access": 12, "relev": [12, 15], "learn": 12, "more": 12, "python": 13, "greater": 13, "pip": 13, "good": 13, "practic": 13, "virtual": 13, "environ": 13, "like": 13, "conda": 13, "aris": 13, "fill": 13, "out": [13, 15], "repositori": 13, "importerror": 13, "mac": 13, "run": [13, 14], "command": [13, 14, 17], "brew": 13, "curl": 13, "integr": [14, 17], "workflow": 14, "intend": 14, "directli": 14, "interfac": [14, 16], "packag": [14, 17], "divid": 14, "api": [14, 17], "ft": 14, "want": 14, "assum": 14, "particularli": 15, "pertin": 15, "page": 15, "give": 15, "sens": 15, "go": 15, "under": 15, "hood": 15, "At": 15, "heart": 15, "flexibl": 15, "among": 15, "argument": 15, "interest": 15, "x": 15, "unmap": 15, "etc": 15, "through": [15, 16], "pass": 15, "rough": 15, "outlin": 15, "circul": 16, "highli": 16, "blood": 16, "plasma": 16, "healthi": 16, "mainli": 16, "hematopoiet": 16, "apoptosi": 16, "necrosi": 16, "patholog": 16, "state": 16, "addit": 16, "releas": 16, "inaccess": 16, "been": [16, 17], "establish": 16, "promis": 16, "invas": 16, "biomark": 16, "monitor": 16, "shown": 16, "chang": 16, "status": 16, "extract": [16, 17], "howev": 16, "variou": 16, "sourc": [16, 17], "absent": 16, "poorli": 16, "document": 16, "unmaintain": 16, "offer": 16, "fast": 16, "toolkit": [16, 17], "friendli": 16, "easi": 16, "maintain": 16, "analysi": 17, "standalon": 17, "program": 17, "websit": 17, "http": 17, "epifluidlab": 17, "io": 17, "doc": 17, "pypi": 17, "org": 17, "guid": 17, "cli": 17, "subcommand": 17, "sub": 17, "scientif": 17, "public": 17, "cite": 17, "readi": 17, "made": 17, "bibtex": 17, "articl": 17, "come": 17, "soon": 17, "jame": 17, "wenhan": 17, "email": 17, "lijw21": 17, "wfu": 17, "edu": 17, "ravi": 17, "bandaru": 17, "northwestern": 17, "yape": 17, "liu": 17, "academ": 17, "research": 17, "mit": 17, "commer": 17}, "objects": {"finaletoolkit.frag": [[3, 0, 1, "", "EndMotifFreqs"], [3, 0, 1, "", "EndMotifsIntervals"], [7, 2, 1, "", "adjust_wps"], [1, 2, 1, "", "cleavage_profile"], [0, 2, 1, "", "coverage"], [2, 2, 1, "", "delfi"], [2, 2, 1, "", "delfi_gc_correct"], [2, 2, 1, "", "delfi_merge_bins"], [3, 2, 1, "", "end_motifs"], [0, 2, 1, "", "frag_length"], [0, 2, 1, "", "frag_length_bins"], [3, 2, 1, "", "interval_end_motifs"], [7, 2, 1, "", "multi_wps"], [3, 2, 1, "", "region_end_motifs"], [7, 2, 1, "", "wps"]], "finaletoolkit.frag.EndMotifFreqs": [[3, 1, 1, "", "from_file"], [3, 1, 1, "", "motif_diversity_score"], [3, 1, 1, "", "to_tsv"]], "finaletoolkit.frag.EndMotifsIntervals": [[3, 1, 1, "", "freq"], [3, 1, 1, "", "from_file"], [3, 1, 1, "", "mds_bed"], [3, 1, 1, "", "motif_diversity_score"], [3, 1, 1, "", "to_bed"], [3, 1, 1, "", "to_bedgraph"], [3, 1, 1, "", "to_tsv"]], "finaletoolkit.genome": [[5, 0, 1, "", "ContigGaps"], [5, 0, 1, "", "GenomeGaps"], [5, 2, 1, "", "b37_gap_bed"], [5, 2, 1, "", "ucsc_hg19_gap_bed"], [5, 2, 1, "", "ucsc_hg38_gap_bed"]], "finaletoolkit.genome.ContigGaps": [[5, 1, 1, "", "get_arm"], [5, 1, 1, "", "in_gap"], [5, 1, 1, "", "in_tcmere"]], "finaletoolkit.genome.GenomeGaps": [[5, 1, 1, "", "b37"], [5, 1, 1, "", "get_arm"], [5, 1, 1, "", "get_contig_gaps"], [5, 1, 1, "", "hg38"], [5, 1, 1, "", "in_tcmere"], [5, 1, 1, "", "overlaps_gap"], [5, 1, 1, "", "to_bed"], [5, 1, 1, "", "ucsc_hg19"]], "finaletoolkit.utils": [[4, 2, 1, "", "agg_bw"], [4, 2, 1, "", "filter_bam"], [4, 2, 1, "", "genome2list"]]}, "objtypes": {"0": "py:class", "1": "py:method", "2": "py:function"}, "objnames": {"0": ["py", "class", "Python class"], "1": ["py", "method", "Python method"], "2": ["py", "function", "Python function"]}, "titleterms": {"basic": 0, "featur": [0, 9], "paramet": [0, 2, 3, 4, 5, 7], "return": [0, 3, 4, 5, 7], "cleavag": [1, 8, 9], "profil": [1, 8, 9], "delfi": [2, 8, 9], "end": [3, 8, 9], "motif": [3, 8, 9], "frag": [4, 8], "file": [4, 12], "util": [4, 5], "genom": 5, "rais": 5, "api": 6, "window": [7, 9], "protect": [7, 9], "score": [7, 9], "wp": [7, 8, 9], "cli": 8, "subcommand": 8, "sub": 8, "command": 8, "coverag": [8, 9], "posit": 8, "argument": 8, "name": 8, "length": [8, 9], "bin": 8, "interv": 8, "filter": 8, "bam": [8, 12], "adjust": 8, "agg": 8, "bw": 8, "gc": 8, "correct": 8, "md": [8, 9], "gap": 8, "bed": 8, "fragment": [9, 12], "divers": 9, "help": 10, "user": 11, "guid": 11, "input": 12, "data": 12, "sam": 12, "cram": 12, "instal": 13, "prerequisit": 13, "error": 13, "quickstart": 14, "get": 14, "start": 14, "import": 14, "modul": 14, "structur": 15, "introduct": 16, "finaletoolkit": 17, "about": 17, "document": 17, "citat": 17, "contact": 17, "licens": 17}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 57}, "alltitles": {"Basic Features": [[0, "basic-features"]], "Parameters": [[0, "parameters"], [0, "id1"], [0, "id3"], [2, "parameters"], [3, "parameters"], [3, "id1"], [3, "id2"], [3, "id5"], [3, "id7"], [3, "id8"], [3, "id11"], [3, "id12"], [3, "id14"], [3, "id16"], [4, "parameters"], [4, "id1"], [4, "id3"], [5, "parameters"], [5, "id3"], [5, "id5"], [5, "id7"], [5, "id9"], [5, "id12"], [5, "id14"], [5, "id16"], [5, "id17"], [5, "id18"], [7, "parameters"], [7, "id1"], [7, "id3"]], "Returns": [[0, "returns"], [0, "id2"], [0, "id4"], [4, "returns"], [4, "id2"], [5, "returns"], [5, "id1"], [5, "id2"], [5, "id4"], [5, "id6"], [5, "id8"], [5, "id10"], [5, "id13"], [5, "id15"], [7, "returns"], [7, "id2"]], "Cleavage Profile": [[1, "cleavage-profile"], [9, "cleavage-profile"]], "DELFI": [[2, "delfi"], [9, "delfi"]], "End-Motifs": [[3, "end-motifs"]], "Return": [[3, "return"], [3, "id6"], [3, "id13"], [3, "id15"], [3, "id17"], [4, "return"]], "Frag File Utilities": [[4, "frag-file-utilities"]], "Genome Utilities": [[5, "genome-utilities"]], "Raises": [[5, "raises"], [5, "id11"]], "API": [[6, "api"]], "Window Protection Score (WPS)": [[7, "window-protection-score-wps"]], "CLI": [[8, "cli"]], "subcommands": [[8, "subcommands"]], "Sub-commands": [[8, "Sub-commands"]], "coverage": [[8, "coverage"]], "Positional Arguments": [[8, "positional-arguments"], [8, "positional-arguments_repeat1"], [8, "positional-arguments_repeat2"], [8, "positional-arguments_repeat3"], [8, "positional-arguments_repeat4"], [8, "positional-arguments_repeat5"], [8, "positional-arguments_repeat6"], [8, "positional-arguments_repeat7"], [8, "positional-arguments_repeat8"], [8, "positional-arguments_repeat9"], [8, "positional-arguments_repeat10"], [8, "positional-arguments_repeat11"], [8, "positional-arguments_repeat12"], [8, "positional-arguments_repeat13"], [8, "positional-arguments_repeat14"], [8, "positional-arguments_repeat15"]], "Named Arguments": [[8, "named-arguments"], [8, "named-arguments_repeat1"], [8, "named-arguments_repeat2"], [8, "named-arguments_repeat3"], [8, "named-arguments_repeat4"], [8, "named-arguments_repeat5"], [8, "named-arguments_repeat6"], [8, "named-arguments_repeat7"], [8, "named-arguments_repeat8"], [8, "named-arguments_repeat9"], [8, "named-arguments_repeat10"], [8, "named-arguments_repeat11"], [8, "named-arguments_repeat12"], [8, "named-arguments_repeat13"], [8, "named-arguments_repeat14"]], "frag-length": [[8, "frag-length"]], "frag-length-bins": [[8, "frag-length-bins"]], "frag-length-intervals": [[8, "frag-length-intervals"]], "wps": [[8, "wps"]], "delfi": [[8, "delfi"]], "filter-bam": [[8, "filter-bam"]], "adjust-wps": [[8, "adjust-wps"]], "agg-bw": [[8, "agg-bw"]], "delfi-gc-correct": [[8, "delfi-gc-correct"]], "end-motifs": [[8, "end-motifs"]], "interval-end-motifs": [[8, "interval-end-motifs"]], "mds": [[8, "mds"]], "interval-mds": [[8, "interval-mds"]], "gap-bed": [[8, "gap-bed"]], "cleavage-profile": [[8, "cleavage-profile"]], "Features": [[9, "features"]], "Fragment Length": [[9, "fragment-length"]], "Fragment Coverage": [[9, "fragment-coverage"]], "Windowed Protection Score (WPS)": [[9, "windowed-protection-score-wps"]], "End Motifs": [[9, "end-motifs"]], "Motif Diversity Score (MDS)": [[9, "motif-diversity-score-mds"]], "Help": [[10, "help"]], "User Guide": [[11, "user-guide"]], "Input Data": [[12, "input-data"]], "SAM": [[12, "sam"]], "BAM": [[12, "bam"]], "CRAM": [[12, "cram"]], "Fragment File": [[12, "fragment-file"]], "Installation": [[13, "installation"], [13, "id1"]], "Prerequisites": [[13, "prerequisites"]], "Errors": [[13, "errors"]], "Quickstart": [[14, "quickstart"]], "Getting Started": [[14, "getting-started"]], "Importing Modules": [[14, "importing-modules"]], "Structure": [[15, "structure"]], "Introduction": [[16, "introduction"]], "FinaleToolkit": [[17, "finaletoolkit"]], "About": [[17, "about"]], "Documentation": [[17, "documentation"]], "Citations": [[17, "citations"]], "Contact": [[17, "contact"]], "License": [[17, "license"]]}, "indexentries": {"coverage() (in module finaletoolkit.frag)": [[0, "finaletoolkit.frag.coverage"]], "frag_length() (in module finaletoolkit.frag)": [[0, "finaletoolkit.frag.frag_length"]], "frag_length_bins() (in module finaletoolkit.frag)": [[0, "finaletoolkit.frag.frag_length_bins"]], "cleavage_profile() (in module finaletoolkit.frag)": [[1, "finaletoolkit.frag.cleavage_profile"]], "delfi() (in module finaletoolkit.frag)": [[2, "finaletoolkit.frag.delfi"]], "delfi_gc_correct() (in module finaletoolkit.frag)": [[2, "finaletoolkit.frag.delfi_gc_correct"]], "delfi_merge_bins() (in module finaletoolkit.frag)": [[2, "finaletoolkit.frag.delfi_merge_bins"]], "endmotiffreqs (class in finaletoolkit.frag)": [[3, "finaletoolkit.frag.EndMotifFreqs"]], "endmotifsintervals (class in finaletoolkit.frag)": [[3, "finaletoolkit.frag.EndMotifsIntervals"]], "end_motifs() (in module finaletoolkit.frag)": [[3, "finaletoolkit.frag.end_motifs"]], "freq() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.freq"]], "from_file() (finaletoolkit.frag.endmotiffreqs class method)": [[3, "finaletoolkit.frag.EndMotifFreqs.from_file"]], "from_file() (finaletoolkit.frag.endmotifsintervals class method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.from_file"]], "interval_end_motifs() (in module finaletoolkit.frag)": [[3, "finaletoolkit.frag.interval_end_motifs"]], "mds_bed() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.mds_bed"]], "motif_diversity_score() (finaletoolkit.frag.endmotiffreqs method)": [[3, "finaletoolkit.frag.EndMotifFreqs.motif_diversity_score"]], "motif_diversity_score() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.motif_diversity_score"]], "region_end_motifs() (in module finaletoolkit.frag)": [[3, "finaletoolkit.frag.region_end_motifs"]], "to_bed() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.to_bed"]], "to_bedgraph() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.to_bedgraph"]], "to_tsv() (finaletoolkit.frag.endmotiffreqs method)": [[3, "finaletoolkit.frag.EndMotifFreqs.to_tsv"]], "to_tsv() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.to_tsv"]], "agg_bw() (in module finaletoolkit.utils)": [[4, "finaletoolkit.utils.agg_bw"]], "filter_bam() (in module finaletoolkit.utils)": [[4, "finaletoolkit.utils.filter_bam"]], "genome2list() (in module finaletoolkit.utils)": [[4, "finaletoolkit.utils.genome2list"]], "contiggaps (class in finaletoolkit.genome)": [[5, "finaletoolkit.genome.ContigGaps"]], "genomegaps (class in finaletoolkit.genome)": [[5, "finaletoolkit.genome.GenomeGaps"]], "b37() (finaletoolkit.genome.genomegaps class method)": [[5, "finaletoolkit.genome.GenomeGaps.b37"]], "b37_gap_bed() (in module finaletoolkit.genome)": [[5, "finaletoolkit.genome.b37_gap_bed"]], "get_arm() (finaletoolkit.genome.contiggaps method)": [[5, "finaletoolkit.genome.ContigGaps.get_arm"]], "get_arm() (finaletoolkit.genome.genomegaps method)": [[5, "finaletoolkit.genome.GenomeGaps.get_arm"]], "get_contig_gaps() (finaletoolkit.genome.genomegaps method)": [[5, "finaletoolkit.genome.GenomeGaps.get_contig_gaps"]], "hg38() (finaletoolkit.genome.genomegaps class method)": [[5, "finaletoolkit.genome.GenomeGaps.hg38"]], "in_gap() (finaletoolkit.genome.contiggaps method)": [[5, "finaletoolkit.genome.ContigGaps.in_gap"]], "in_tcmere() (finaletoolkit.genome.contiggaps method)": [[5, "finaletoolkit.genome.ContigGaps.in_tcmere"]], "in_tcmere() (finaletoolkit.genome.genomegaps method)": [[5, "finaletoolkit.genome.GenomeGaps.in_tcmere"]], "overlaps_gap() (finaletoolkit.genome.genomegaps method)": [[5, "finaletoolkit.genome.GenomeGaps.overlaps_gap"]], "to_bed() (finaletoolkit.genome.genomegaps method)": [[5, "finaletoolkit.genome.GenomeGaps.to_bed"]], "ucsc_hg19() (finaletoolkit.genome.genomegaps class method)": [[5, "finaletoolkit.genome.GenomeGaps.ucsc_hg19"]], "ucsc_hg19_gap_bed() (in module finaletoolkit.genome)": [[5, "finaletoolkit.genome.ucsc_hg19_gap_bed"]], "ucsc_hg38_gap_bed() (in module finaletoolkit.genome)": [[5, "finaletoolkit.genome.ucsc_hg38_gap_bed"]], "adjust_wps() (in module finaletoolkit.frag)": [[7, "finaletoolkit.frag.adjust_wps"]], "multi_wps() (in module finaletoolkit.frag)": [[7, "finaletoolkit.frag.multi_wps"]], "wps() (in module finaletoolkit.frag)": [[7, "finaletoolkit.frag.wps"]]}}) \ No newline at end of file +Search.setIndex({"docnames": ["_documentation/api_reference/basicfeatures", "_documentation/api_reference/cleavageprofile", "_documentation/api_reference/delfi", "_documentation/api_reference/endmotifs", "_documentation/api_reference/fragfile", "_documentation/api_reference/genomeutils", "_documentation/api_reference/index", "_documentation/api_reference/wps", "_documentation/cli_reference/index", "_documentation/user_guide/features", "_documentation/user_guide/help", "_documentation/user_guide/index", "_documentation/user_guide/inputdata", "_documentation/user_guide/installation", "_documentation/user_guide/quickstart", "_documentation/user_guide/structure", "_documentation/user_guide/what", "index"], "filenames": ["_documentation/api_reference/basicfeatures.rst", "_documentation/api_reference/cleavageprofile.rst", "_documentation/api_reference/delfi.rst", "_documentation/api_reference/endmotifs.rst", "_documentation/api_reference/fragfile.rst", "_documentation/api_reference/genomeutils.rst", "_documentation/api_reference/index.rst", "_documentation/api_reference/wps.rst", "_documentation/cli_reference/index.rst", "_documentation/user_guide/features.rst", "_documentation/user_guide/help.rst", "_documentation/user_guide/index.rst", "_documentation/user_guide/inputdata.rst", "_documentation/user_guide/installation.rst", "_documentation/user_guide/quickstart.rst", "_documentation/user_guide/structure.rst", "_documentation/user_guide/what.rst", "index.rst"], "titles": ["Basic Features", "Cleavage Profile", "DELFI", "End-Motifs", "Frag File Utilities", "Genome Utilities", "API", "Window Protection Score (WPS)", "CLI", "Features", "Help", "User Guide", "Input Data", "Installation", "Quickstart", "Structure", "Introduction", "FinaleToolkit"], "terms": {"finaletoolkit": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 14, 15, 16], "frag": [0, 1, 2, 3, 6, 7, 12, 14, 17], "coverag": [0, 6, 11], "input_fil": [0, 1, 2, 3, 4, 7, 8], "str": [0, 1, 2, 3, 4, 5, 7], "alignmentfil": [0, 4, 7], "interval_fil": [0, 4, 7, 8], "output_fil": [0, 2, 3, 4, 5, 7, 8], "scale_factor": [0, 8], "float": [0, 2, 3], "1000000": [0, 8], "0": [0, 1, 2, 3, 4, 7, 8], "quality_threshold": [0, 1, 2, 3, 4, 7, 8], "int": [0, 1, 2, 3, 4, 5, 7], "30": [0, 1, 2, 3, 4, 7, 8], "worker": [0, 2, 3, 4, 7, 8], "1": [0, 1, 2, 3, 4, 7, 8], "verbos": [0, 1, 2, 3, 4, 7, 8], "bool": [0, 1, 2, 3, 4, 5, 7], "fals": [0, 2, 3, 4, 5, 7, 8], "estim": 0, "fragment": [0, 2, 3, 7, 8, 11, 15, 16, 17], "over": [0, 3, 7, 8, 9], "interv": [0, 2, 3, 4, 5, 7], "specifi": [0, 3, 4, 5, 7, 8], "ar": [0, 3, 4, 5, 8, 9, 10, 13, 15, 16], "read": [0, 2, 3, 4, 5, 7, 8, 9, 12, 15], "from": [0, 3, 5, 7, 8, 9, 12, 14, 16, 17], "which": [0, 2, 4, 7, 8, 9, 16], "mai": [0, 8], "sam": [0, 3, 7, 8, 11, 15], "bam": [0, 2, 3, 4, 7, 11, 15], "cram": [0, 3, 8, 11, 15], "gz": [0, 3, 8, 12], "file": [0, 2, 3, 5, 6, 7, 8, 11, 15, 17], "us": [0, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 14, 16], "an": [0, 3, 4, 5, 9, 10, 12, 13], "algorithm": 0, "where": [0, 2, 4, 5, 7, 8], "midpoint": [0, 8], "calcul": [0, 3, 7, 8, 9], "i": [0, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17], "tabul": [0, 8], "fall": [0, 8, 9], "region": [0, 3, 4, 7, 8, 9], "Not": 0, "suitabl": 0, "size": [0, 2, 3, 4, 7, 8], "approach": [0, 4, 16], "pysam": [0, 7], "contain": [0, 2, 3, 4, 5, 7, 8, 12], "pair": [0, 3, 4, 7, 8, 9, 12, 17], "end": [0, 4, 5, 6, 7, 11, 12, 17], "its": [0, 3, 7, 14], "path": [0, 2, 3, 4, 5, 7, 8], "must": [0, 7, 8, 10], "open": [0, 7, 10, 14], "mode": [0, 7, 8], "bed4": [0, 2, 5, 8], "gener": [0, 3, 5, 8, 15], "statist": [0, 8, 9], "string": [0, 2, 3, 4, 5, 7], "option": [0, 2, 3, 4, 5, 7], "bed": [0, 2, 3, 4, 5, 7], "print": [0, 2, 3, 5, 8], "If": [0, 5, 7, 8, 10, 13, 14, 17], "_": 0, "result": [0, 3, 5, 8, 9, 12], "stdout": [0, 2, 5, 8], "amount": 0, "multipli": 0, "default": [0, 2, 3, 4, 7, 8], "10": [0, 3, 8], "6": 0, "contig": [0, 1, 3, 4, 5, 7, 8], "frag_length": [0, 6], "tabixfil": 0, "none": [0, 2, 3, 4, 5, 7], "start": [0, 1, 3, 4, 5, 7, 8, 9, 11, 12], "stop": [0, 1, 3, 5, 7, 8, 12], "intersect_polici": [0, 8], "ndarrai": [0, 1, 4, 7], "np": [0, 7], "length": [0, 3, 4, 7, 11], "abov": 0, "qualiti": [0, 3, 4, 8, 12, 15], "threshold": [0, 4, 8], "proper": [0, 4], "chromosom": [0, 2, 3, 5, 7, 8], "get": [0, 11, 13], "base": [0, 3, 5, 7, 8, 9], "left": [0, 8], "most": [0, 8], "coordin": [0, 3, 5, 7, 8, 9], "right": [0, 8], "what": [0, 8, 15], "polici": [0, 8], "includ": [0, 3, 5, 7, 8, 9, 10, 15], "given": [0, 3, 4, 5, 8], "averag": 0, "li": [0, 17], "ani": [0, 3, 8, 12, 13], "part": 0, "numpi": [0, 7], "frag_length_bin": [0, 6], "bin_siz": [0, 8], "contig_by_contig": 0, "histogram": [0, 8], "tupl": [0, 3, 4, 5, 8], "take": [0, 2, 3, 4, 5, 7, 8, 15], "comput": [0, 16], "two": [0, 3, 4], "arrai": [0, 7], "bin": [0, 2], "count": [0, 3, 9], "data": [0, 2, 3, 4, 7, 8, 11, 16, 17], "output": [0, 2, 5, 8, 10], "tab": [0, 3, 7, 8, 12], "delimit": [0, 3, 7, 8], "tabl": [0, 3, 8], "cleavage_profil": [1, 6], "fraction_low": [1, 3, 7, 8], "fraction_high": [1, 3, 7, 8], "10000000": 1, "autosom": [2, 8], "bins_fil": [2, 8], "reference_fil": [2, 8], "blacklist_fil": [2, 8], "gap_fil": [2, 8], "union": [2, 7], "genomegap": [2, 5, 6], "gc_correct": [2, 8], "true": [2, 3, 5, 7], "merge_bin": [2, 8], "window_s": [2, 7, 8], "5000000": [2, 8], "subsample_coverag": 2, "2": [2, 4, 7, 8, 12], "preprocess": 2, "panda": 2, "datafram": 2, "A": [2, 3, 7, 8, 10, 12, 15, 17], "function": [2, 3, 4, 7, 8, 14, 15], "replic": [2, 3, 8], "methodologi": [2, 3, 8], "christiano": 2, "et": [2, 3, 7, 8, 9], "al": [2, 3, 7, 8, 9], "2019": [2, 9], "point": [2, 4], "pe": [2, 3], "genom": [2, 3, 4, 6, 7, 8, 9, 12, 16, 17], "onli": [2, 3, 8, 13], "100kb": [2, 8], "refer": [2, 3, 5, 7, 8, 12, 16, 17], "choic": [2, 8], "cristiano": [2, 8, 9], "2bit": [2, 3, 8], "blacklist": [2, 4], "each": [2, 3, 4, 7, 8, 12], "centromer": [2, 5, 8], "telomer": [2, 5, 8], "can": [2, 4, 9, 10, 12, 13, 14, 16], "fourth": 2, "field": 2, "entri": [2, 8, 12, 17], "correspond": [2, 3, 8], "labl": 2, "respect": 2, "tsv": [2, 3, 8], "non": [2, 16], "overlap": [2, 5, 8, 9], "window": [2, 4, 6, 8, 11, 16, 17], "cover": 2, "5": [2, 3, 4, 8], "megabas": 2, "The": [2, 7, 8, 9, 10, 12, 13, 14, 15], "depth": 2, "subsampl": 2, "input_bam": [2, 4], "number": [2, 3, 7, 8, 9], "process": [2, 3, 7, 8, 15], "determin": 2, "how": 2, "mani": 2, "statement": [2, 8], "load": [2, 14], "bar": 2, "appear": 2, "delfi_gc_correct": [2, 6], "alpha": 2, "75": 2, "8": [2, 13], "helper": 2, "perform": [2, 7, 8], "gc": [2, 9], "adjust": [2, 4, 7], "delfi_merge_bin": [2, 6], "hundred_kb_bin": 2, "add_chr": 2, "class": [3, 5], "endmotiffreq": [3, 6], "kmer_frequ": 3, "iter": [3, 5], "k": [3, 7, 8, 9], "20": [3, 8], "store": [3, 12], "frequenc": [3, 8, 9], "mer": [3, 8, 9], "method": [3, 5, 7], "manipul": 3, "thi": [3, 4, 5, 8, 9, 12, 15, 16], "repres": 3, "minimum": [3, 8], "map": [3, 8, 9, 12, 15], "classmethod": [3, 5], "from_fil": 3, "file_path": [3, 8], "sep": [3, 8], "t": 3, "header": [3, 8], "kmer": 3, "column": [3, 4, 7, 8, 12], "line": [3, 8], "ignor": [3, 8], "head": 3, "kmer_freq": 3, "motif_diversity_scor": 3, "divers": [3, 8, 11, 16], "score": [3, 6, 8, 11, 16, 17], "md": [3, 11, 16], "normal": [3, 8, 9], "shannon": [3, 8, 9], "entropi": [3, 8, 9], "describ": [3, 7, 8, 17], "jiang": [3, 8, 9], "2020": [3, 8, 9], "instead": [3, 4, 7, 8], "just": [3, 8], "4": [3, 8], "to_tsv": 3, "endmotifsinterv": [3, 6], "dict": 3, "user": [3, 8, 16, 17], "collect": 3, "chrom": [3, 4, 8, 12], "freq": 3, "list": [3, 4, 8], "associ": [3, 8, 9, 12, 16], "frquenci": 3, "form": 3, "expect": 3, "name": [3, 4, 5, 7], "becaus": [3, 5], "export": 3, "turn": 3, "fraction": [3, 7, 8], "doesn": 3, "perfectli": 3, "other": [3, 5, 9, 15], "mapq": [3, 8, 12], "filter": [3, 4, 7, 15], "some": [3, 8], "mds_bed": 3, "write": [3, 5, 7, 8], "bedgraph": [3, 8], "to_b": [3, 5], "calc_freq": 3, "otherwis": [3, 16], "separ": [3, 8, 12], "to_bedgraph": 3, "all": [3, 4, 8, 9, 12, 14], "region_end_motif": [3, 6], "refseq_fil": [3, 8], "600": [3, 8], "both_strand": 3, "tabix": [3, 7, 8, 12], "index": [3, 8, 12], "dictionari": 3, "reproduc": [3, 10], "zhou": [3, 9], "2023": 3, "sequenc": [3, 5, 8, 9, 12, 16, 17], "wa": [3, 4, 7, 8, 9], "align": [3, 5, 7, 8, 12], "maximum": [3, 8], "choos": 3, "whether": [3, 8], "forward": 3, "both": [3, 4], "end_motif_freq": 3, "end_motif": [3, 6], "either": [3, 8, 12], "csv": [3, 8], "interval_end_motif": [3, 6], "endmotifinterv": 3, "filter_bam": [4, 6], "region_fil": [4, 8], "max_length": 4, "min_length": 4, "accept": [4, 8], "creat": [4, 5, 8], "read1": [4, 8], "exce": [4, 8], "do": [4, 14], "intersect": [4, 5], "genome2list": [4, 6], "genome_fil": [4, 7, 8], "text": [4, 10], "format": [4, 7, 8, 12], "agg_bw": [4, 6], "median_window_s": [4, 7, 8], "mean": [4, 7, 8], "strand_loc": 4, "bigwig": [4, 7, 8], "aggreg": [4, 7, 8], "signal": [4, 8], "along": 4, "For": [4, 12, 17], "wp": [4, 6, 11, 16, 17], "note": [4, 8], "median": [4, 7, 8], "trim": 4, "half": 4, "while": [4, 15], "There": 4, "wai": [4, 5], "suppli": 4, "smaller": [4, 12], "e": [4, 5, 8, 15, 16], "g": [4, 8, 16], "you": [4, 10, 12, 13, 14, 15], "5kb": 4, "1kb": 4, "4kb": 4, "provid": [4, 8, 12, 16], "origin": [4, 9, 16], "were": [4, 8], "onc": 4, "strand": [4, 12], "agg_scor": 4, "gaps_b": 5, "short_arm": 5, "ucsc": [5, 8], "gap": 5, "track": [5, 8], "hg19": [5, 8], "hg38": [5, 8], "b37": [5, 8], "broad": 5, "institut": 5, "grch37": 5, "also": [5, 8, 13], "differ": [5, 16], "few": 5, "absenc": 5, "chr": 5, "prefix": 5, "we": [5, 12, 14, 15], "ad": [5, 8, 16], "hoc": [5, 8, 16], "drop": 5, "between": [5, 9], "perfect": 5, "solut": [5, 16], "get_arm": 5, "arm": [5, 8], "short": [5, 8, 9], "acrocentr": 5, "empti": 5, "valueerror": 5, "invalid": 5, "get_contig_gap": 5, "contiggap": [5, 6], "make": [5, 10, 15], "synonym": 5, "grch38": [5, 8], "in_tcmer": 5, "check": 5, "in_telomere_or_centromer": 5, "overlaps_gap": 5, "type": [5, 8, 14], "gzip": [5, 8, 12], "writ": 5, "ucsc_hg19": 5, "version": [5, 10, 12, 13], "has_short_arm": 5, "noarm": 5, "in_gap": 5, "ucsc_hg19_gap_b": [5, 6], "b37_gap_b": [5, 6], "human_g1k_v37": [5, 8], "1000": [5, 7, 8], "project": [5, 17], "ucsc_hg38_gap_b": [5, 6], "basic": [6, 17], "featur": [6, 8, 11, 16, 17], "protect": [6, 8, 11, 16, 17], "multi_wp": [6, 7], "adjust_wp": [6, 7], "delfi": [6, 11, 14, 16, 17], "motif": [6, 11, 16, 17], "cleavag": [6, 11, 17], "profil": [6, 11, 17], "util": [6, 17], "120": [7, 8, 9], "180": [7, 8], "raw": [7, 8, 9], "snyder": [7, 9], "2016": [7, 9], "equival": 7, "l": 7, "lowest": 7, "long": [7, 9], "highest": 7, "shape": 7, "n": 7, "site_b": [7, 8], "interval_s": [7, 8], "5000": [7, 8], "site": [7, 9], "accord": [7, 8, 9], "should": [7, 8, 12], "same": [7, 8, 9, 12], "everi": 7, "interb": 7, "savgol_window_s": [7, 8], "21": [7, 8], "savgol_poly_deg": [7, 8], "subtract_edg": 7, "edge_s": 7, "500": [7, 8], "appli": [7, 8], "savitski": [7, 8], "golai": [7, 8], "1964": 7, "wg": [7, 16], "degre": [7, 8], "polynomi": [7, 8], "first": [7, 8], "last": [7, 8], "subtract": [7, 8, 9], "whole": [7, 8, 16], "packag": [8, 14, 17], "standalon": [8, 17], "program": [8, 17], "extract": [8, 16, 17], "cell": [8, 9, 16, 17], "free": [8, 9, 16, 17], "dna": [8, 9, 16, 17], "usag": [8, 15], "h": 8, "defin": [8, 9], "o": 8, "": [8, 9, 13], "q": 8, "w": 8, "v": 8, "valu": [8, 9, 12], "scale": 8, "factor": 8, "enabl": 8, "displai": 8, "detail": [8, 13], "inform": [8, 10, 12], "retriev": 8, "group": 8, "c": 8, "p": 8, "select": 8, "requir": [8, 12], "see": [8, 10], "guid": [8, 17], "more": [8, 12], "placehold": 8, "implement": 8, "termin": [8, 13, 14], "summari": [8, 9], "st": 8, "dev": 8, "min": 8, "max": 8, "lo": 8, "hi": 8, "bp": 8, "slide": 8, "due": 8, "current": 8, "b": 8, "m": 8, "integ": 8, "dure": [8, 13], "To": [8, 10], "human": [8, 12], "when": [8, 13], "denot": 8, "categori": 8, "browser": 8, "unus": 8, "indic": 8, "merg": 8, "5mb": 8, "so": [8, 14], "certain": [8, 9], "flag": 8, "secondari": 8, "supplementari": 8, "mate": 8, "r": 8, "high": 8, "low": [8, 15], "edg": 8, "savgol": 8, "poli": 8, "deg": 8, "constant": 8, "wiggl": 8, "modifi": 8, "header_lin": 8, "bed3": [8, 12], "3": [8, 13], "proport": [8, 9], "measur": 8, "subprocess": 8, "smallest": 8, "consid": 8, "longest": 8, "similar": [8, 12], "one": [8, 12], "stdin": 8, "tabular": 8, "row": [8, 12], "file_out": 8, "annot": 8, "found": [8, 9], "kent": 8, "2002": 8, "support": [8, 9], "reference_genom": 8, "possibl": [8, 9, 15], "liber": 8, "case": 8, "longer": 8, "wip": 8, "compress": [8, 12], "suffix": 8, "ha": [9, 16, 17], "follow": [9, 10, 12, 13, 14, 15], "distribut": 9, "specif": [9, 10, 14], "total": 9, "sampl": 9, "simpli": 9, "metric": 9, "design": [9, 15, 16], "It": [9, 12, 15, 16], "quantifi": 9, "level": 9, "across": 9, "assess": 9, "fulli": 9, "span": 9, "typic": 9, "center": 9, "around": 9, "particular": 9, "endpoint": 9, "within": 9, "correl": 9, "locat": 9, "nucleosom": 9, "transcript": 9, "tss": 9, "dnase": 9, "hypersensit": 9, "dhss": 9, "introduc": 9, "identifi": 9, "abnorm": 9, "cfdna": [9, 16], "pattern": [9, 16], "In": [9, 16], "paper": [9, 17], "categor": 9, "patient": 9, "cancer": [9, 16], "tumor": [9, 16], "tissu": [9, 16], "ratio": 9, "correct": 9, "sinc": 9, "thei": 9, "potenti": 9, "detect": [9, 16], "condit": [9, 16], "diseas": [9, 16], "2022": 9, "definit": 9, "nucleotid": 9, "author": 9, "show": 9, "relationship": 9, "methyl": 9, "cpg": 9, "think": 10, "ve": 10, "encount": 10, "bug": [10, 17], "pleas": [10, 13, 17], "report": [10, 17], "github": [10, 13, 17], "issu": [10, 13, 17], "tracker": 10, "code": [10, 16, 17], "exampl": [10, 12], "demonstr": 10, "problem": 10, "ex": [10, 16], "error": [10, 11], "messag": 10, "clear": 10, "explan": 10, "why": 10, "someth": 10, "wrong": 10, "work": 10, "search": 10, "befor": 10, "new": 10, "often": [10, 16], "solv": 10, "quickli": 10, "avoid": 10, "duplic": 10, "introduct": [11, 17], "input": [11, 17], "instal": [11, 17], "prerequisit": 11, "structur": [11, 17], "quickstart": [11, 17], "import": 11, "modul": 11, "help": [11, 17], "compat": 12, "almost": 12, "readabl": 12, "about": 12, "well": [12, 16], "itself": [12, 14], "binari": 12, "save": 12, "space": 12, "disk": 12, "bai": 12, "therefor": [12, 15], "have": [12, 16], "directori": 12, "your": [12, 15], "than": [12, 13], "still": 12, "crai": 12, "deriv": 12, "block": 12, "here": [12, 17], "tbi": 12, "chr1": 12, "10000": 12, "10050": 12, "60": 12, "10100": 12, "10150": 12, "10200": 12, "10250": 12, "10300": 12, "10350": 12, "10400": 12, "10450": 12, "10500": 12, "encourag": 12, "our": 12, "comprehens": [12, 16], "databas": 12, "finaledb": 12, "access": 12, "relev": [12, 15], "learn": 12, "python": 13, "greater": 13, "pip": 13, "good": 13, "practic": 13, "virtual": 13, "environ": 13, "like": 13, "conda": 13, "aris": 13, "fill": 13, "out": [13, 15], "repositori": 13, "importerror": 13, "mac": 13, "run": [13, 14], "command": [13, 14, 17], "brew": 13, "curl": 13, "integr": [14, 17], "workflow": 14, "intend": 14, "directli": 14, "interfac": [14, 16], "divid": 14, "api": [14, 17], "ft": 14, "want": 14, "assum": 14, "particularli": 15, "pertin": 15, "page": 15, "give": 15, "sens": 15, "go": 15, "under": 15, "hood": 15, "At": 15, "heart": 15, "flexibl": 15, "among": 15, "argument": 15, "interest": 15, "x": 15, "unmap": 15, "etc": 15, "through": [15, 16], "pass": 15, "rough": 15, "outlin": 15, "circul": 16, "highli": 16, "blood": 16, "plasma": 16, "healthi": 16, "mainli": 16, "hematopoiet": 16, "apoptosi": 16, "necrosi": 16, "patholog": 16, "state": 16, "addit": 16, "releas": 16, "inaccess": 16, "been": [16, 17], "establish": 16, "promis": 16, "invas": 16, "biomark": 16, "monitor": 16, "shown": 16, "chang": 16, "status": 16, "howev": 16, "variou": 16, "sourc": [16, 17], "absent": 16, "poorli": 16, "document": 16, "unmaintain": 16, "offer": 16, "fast": 16, "toolkit": [16, 17], "friendli": 16, "easi": 16, "maintain": 16, "analysi": 17, "websit": 17, "http": 17, "epifluidlab": 17, "io": 17, "doc": 17, "pypi": 17, "org": 17, "cli": 17, "sub": 17, "scientif": 17, "public": 17, "cite": 17, "written": 17, "readi": 17, "made": 17, "bibtex": 17, "articl": 17, "come": 17, "soon": 17, "jame": 17, "wenhan": 17, "email": 17, "lijw21": 17, "wfu": 17, "edu": 17, "ravi": 17, "bandaru": 17, "northwestern": 17, "yape": 17, "liu": 17, "academ": 17, "research": 17, "mit": 17}, "objects": {"finaletoolkit.frag": [[3, 0, 1, "", "EndMotifFreqs"], [3, 0, 1, "", "EndMotifsIntervals"], [7, 2, 1, "", "adjust_wps"], [1, 2, 1, "", "cleavage_profile"], [0, 2, 1, "", "coverage"], [2, 2, 1, "", "delfi"], [2, 2, 1, "", "delfi_gc_correct"], [2, 2, 1, "", "delfi_merge_bins"], [3, 2, 1, "", "end_motifs"], [0, 2, 1, "", "frag_length"], [0, 2, 1, "", "frag_length_bins"], [3, 2, 1, "", "interval_end_motifs"], [7, 2, 1, "", "multi_wps"], [3, 2, 1, "", "region_end_motifs"], [7, 2, 1, "", "wps"]], "finaletoolkit.frag.EndMotifFreqs": [[3, 1, 1, "", "from_file"], [3, 1, 1, "", "motif_diversity_score"], [3, 1, 1, "", "to_tsv"]], "finaletoolkit.frag.EndMotifsIntervals": [[3, 1, 1, "", "freq"], [3, 1, 1, "", "from_file"], [3, 1, 1, "", "mds_bed"], [3, 1, 1, "", "motif_diversity_score"], [3, 1, 1, "", "to_bed"], [3, 1, 1, "", "to_bedgraph"], [3, 1, 1, "", "to_tsv"]], "finaletoolkit.genome": [[5, 0, 1, "", "ContigGaps"], [5, 0, 1, "", "GenomeGaps"], [5, 2, 1, "", "b37_gap_bed"], [5, 2, 1, "", "ucsc_hg19_gap_bed"], [5, 2, 1, "", "ucsc_hg38_gap_bed"]], "finaletoolkit.genome.ContigGaps": [[5, 1, 1, "", "get_arm"], [5, 1, 1, "", "in_gap"], [5, 1, 1, "", "in_tcmere"]], "finaletoolkit.genome.GenomeGaps": [[5, 1, 1, "", "b37"], [5, 1, 1, "", "get_arm"], [5, 1, 1, "", "get_contig_gaps"], [5, 1, 1, "", "hg38"], [5, 1, 1, "", "in_tcmere"], [5, 1, 1, "", "overlaps_gap"], [5, 1, 1, "", "to_bed"], [5, 1, 1, "", "ucsc_hg19"]], "finaletoolkit.utils": [[4, 2, 1, "", "agg_bw"], [4, 2, 1, "", "filter_bam"], [4, 2, 1, "", "genome2list"]]}, "objtypes": {"0": "py:class", "1": "py:method", "2": "py:function"}, "objnames": {"0": ["py", "class", "Python class"], "1": ["py", "method", "Python method"], "2": ["py", "function", "Python function"]}, "titleterms": {"basic": 0, "featur": [0, 9], "paramet": [0, 2, 3, 4, 5, 7], "return": [0, 3, 4, 5, 7], "cleavag": [1, 8, 9], "profil": [1, 8, 9], "delfi": [2, 8, 9], "end": [3, 8, 9], "motif": [3, 8, 9], "frag": [4, 8], "file": [4, 12], "util": [4, 5], "genom": 5, "rais": 5, "api": 6, "window": [7, 9], "protect": [7, 9], "score": [7, 9], "wp": [7, 8, 9], "cli": 8, "sub": 8, "command": 8, "coverag": [8, 9], "posit": 8, "argument": 8, "name": 8, "length": [8, 9], "bin": 8, "interv": 8, "filter": 8, "bam": [8, 12], "adjust": 8, "agg": 8, "bw": 8, "gc": 8, "correct": 8, "md": [8, 9], "gap": 8, "bed": 8, "fragment": [9, 12], "divers": 9, "help": 10, "user": 11, "guid": 11, "input": 12, "data": 12, "sam": 12, "cram": 12, "instal": 13, "prerequisit": 13, "error": 13, "quickstart": 14, "get": 14, "start": 14, "import": 14, "modul": 14, "structur": 15, "introduct": 16, "finaletoolkit": 17, "about": 17, "document": 17, "citat": 17, "contact": 17, "licens": 17}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 57}, "alltitles": {"Basic Features": [[0, "basic-features"]], "Parameters": [[0, "parameters"], [0, "id1"], [0, "id3"], [2, "parameters"], [3, "parameters"], [3, "id1"], [3, "id2"], [3, "id5"], [3, "id7"], [3, "id8"], [3, "id11"], [3, "id12"], [3, "id14"], [3, "id16"], [4, "parameters"], [4, "id1"], [4, "id3"], [5, "parameters"], [5, "id3"], [5, "id5"], [5, "id7"], [5, "id9"], [5, "id12"], [5, "id14"], [5, "id16"], [5, "id17"], [5, "id18"], [7, "parameters"], [7, "id1"], [7, "id3"]], "Returns": [[0, "returns"], [0, "id2"], [0, "id4"], [4, "returns"], [4, "id2"], [5, "returns"], [5, "id1"], [5, "id2"], [5, "id4"], [5, "id6"], [5, "id8"], [5, "id10"], [5, "id13"], [5, "id15"], [7, "returns"], [7, "id2"]], "Cleavage Profile": [[1, "cleavage-profile"], [9, "cleavage-profile"]], "DELFI": [[2, "delfi"], [9, "delfi"]], "End-Motifs": [[3, "end-motifs"]], "Return": [[3, "return"], [3, "id6"], [3, "id13"], [3, "id15"], [3, "id17"], [4, "return"]], "Frag File Utilities": [[4, "frag-file-utilities"]], "Genome Utilities": [[5, "genome-utilities"]], "Raises": [[5, "raises"], [5, "id11"]], "API": [[6, "api"]], "Window Protection Score (WPS)": [[7, "window-protection-score-wps"]], "CLI": [[8, "cli"]], "Sub-commands": [[8, "Sub-commands"]], "coverage": [[8, "coverage"]], "Positional Arguments": [[8, "positional-arguments"], [8, "positional-arguments_repeat1"], [8, "positional-arguments_repeat2"], [8, "positional-arguments_repeat3"], [8, "positional-arguments_repeat4"], [8, "positional-arguments_repeat5"], [8, "positional-arguments_repeat6"], [8, "positional-arguments_repeat7"], [8, "positional-arguments_repeat8"], [8, "positional-arguments_repeat9"], [8, "positional-arguments_repeat10"], [8, "positional-arguments_repeat11"], [8, "positional-arguments_repeat12"], [8, "positional-arguments_repeat13"], [8, "positional-arguments_repeat14"]], "Named Arguments": [[8, "named-arguments"], [8, "named-arguments_repeat1"], [8, "named-arguments_repeat2"], [8, "named-arguments_repeat3"], [8, "named-arguments_repeat4"], [8, "named-arguments_repeat5"], [8, "named-arguments_repeat6"], [8, "named-arguments_repeat7"], [8, "named-arguments_repeat8"], [8, "named-arguments_repeat9"], [8, "named-arguments_repeat10"], [8, "named-arguments_repeat11"], [8, "named-arguments_repeat12"], [8, "named-arguments_repeat13"]], "frag-length-bins": [[8, "frag-length-bins"]], "frag-length-intervals": [[8, "frag-length-intervals"]], "wps": [[8, "wps"]], "delfi": [[8, "delfi"]], "filter-bam": [[8, "filter-bam"]], "adjust-wps": [[8, "adjust-wps"]], "agg-bw": [[8, "agg-bw"]], "delfi-gc-correct": [[8, "delfi-gc-correct"]], "end-motifs": [[8, "end-motifs"]], "interval-end-motifs": [[8, "interval-end-motifs"]], "mds": [[8, "mds"]], "interval-mds": [[8, "interval-mds"]], "gap-bed": [[8, "gap-bed"]], "cleavage-profile": [[8, "cleavage-profile"]], "Features": [[9, "features"]], "Fragment Length": [[9, "fragment-length"]], "Fragment Coverage": [[9, "fragment-coverage"]], "Windowed Protection Score (WPS)": [[9, "windowed-protection-score-wps"]], "End Motifs": [[9, "end-motifs"]], "Motif Diversity Score (MDS)": [[9, "motif-diversity-score-mds"]], "Help": [[10, "help"]], "User Guide": [[11, "user-guide"]], "Input Data": [[12, "input-data"]], "SAM": [[12, "sam"]], "BAM": [[12, "bam"]], "CRAM": [[12, "cram"]], "Fragment File": [[12, "fragment-file"]], "Installation": [[13, "installation"], [13, "id1"]], "Prerequisites": [[13, "prerequisites"]], "Errors": [[13, "errors"]], "Quickstart": [[14, "quickstart"]], "Getting Started": [[14, "getting-started"]], "Importing Modules": [[14, "importing-modules"]], "Structure": [[15, "structure"]], "Introduction": [[16, "introduction"]], "FinaleToolkit": [[17, "finaletoolkit"]], "About": [[17, "about"]], "Documentation": [[17, "documentation"]], "Citations": [[17, "citations"]], "Contact": [[17, "contact"]], "License": [[17, "license"]]}, "indexentries": {"coverage() (in module finaletoolkit.frag)": [[0, "finaletoolkit.frag.coverage"]], "frag_length() (in module finaletoolkit.frag)": [[0, "finaletoolkit.frag.frag_length"]], "frag_length_bins() (in module finaletoolkit.frag)": [[0, "finaletoolkit.frag.frag_length_bins"]], "cleavage_profile() (in module finaletoolkit.frag)": [[1, "finaletoolkit.frag.cleavage_profile"]], "delfi() (in module finaletoolkit.frag)": [[2, "finaletoolkit.frag.delfi"]], "delfi_gc_correct() (in module finaletoolkit.frag)": [[2, "finaletoolkit.frag.delfi_gc_correct"]], "delfi_merge_bins() (in module finaletoolkit.frag)": [[2, "finaletoolkit.frag.delfi_merge_bins"]], "endmotiffreqs (class in finaletoolkit.frag)": [[3, "finaletoolkit.frag.EndMotifFreqs"]], "endmotifsintervals (class in finaletoolkit.frag)": [[3, "finaletoolkit.frag.EndMotifsIntervals"]], "end_motifs() (in module finaletoolkit.frag)": [[3, "finaletoolkit.frag.end_motifs"]], "freq() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.freq"]], "from_file() (finaletoolkit.frag.endmotiffreqs class method)": [[3, "finaletoolkit.frag.EndMotifFreqs.from_file"]], "from_file() (finaletoolkit.frag.endmotifsintervals class method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.from_file"]], "interval_end_motifs() (in module finaletoolkit.frag)": [[3, "finaletoolkit.frag.interval_end_motifs"]], "mds_bed() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.mds_bed"]], "motif_diversity_score() (finaletoolkit.frag.endmotiffreqs method)": [[3, "finaletoolkit.frag.EndMotifFreqs.motif_diversity_score"]], "motif_diversity_score() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.motif_diversity_score"]], "region_end_motifs() (in module finaletoolkit.frag)": [[3, "finaletoolkit.frag.region_end_motifs"]], "to_bed() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.to_bed"]], "to_bedgraph() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.to_bedgraph"]], "to_tsv() (finaletoolkit.frag.endmotiffreqs method)": [[3, "finaletoolkit.frag.EndMotifFreqs.to_tsv"]], "to_tsv() (finaletoolkit.frag.endmotifsintervals method)": [[3, "finaletoolkit.frag.EndMotifsIntervals.to_tsv"]], "agg_bw() (in module finaletoolkit.utils)": [[4, "finaletoolkit.utils.agg_bw"]], "filter_bam() (in module finaletoolkit.utils)": [[4, "finaletoolkit.utils.filter_bam"]], "genome2list() (in module finaletoolkit.utils)": [[4, "finaletoolkit.utils.genome2list"]], "contiggaps (class in finaletoolkit.genome)": [[5, "finaletoolkit.genome.ContigGaps"]], "genomegaps (class in finaletoolkit.genome)": [[5, "finaletoolkit.genome.GenomeGaps"]], "b37() (finaletoolkit.genome.genomegaps class method)": [[5, "finaletoolkit.genome.GenomeGaps.b37"]], "b37_gap_bed() (in module finaletoolkit.genome)": [[5, "finaletoolkit.genome.b37_gap_bed"]], "get_arm() (finaletoolkit.genome.contiggaps method)": [[5, "finaletoolkit.genome.ContigGaps.get_arm"]], "get_arm() (finaletoolkit.genome.genomegaps method)": [[5, "finaletoolkit.genome.GenomeGaps.get_arm"]], "get_contig_gaps() (finaletoolkit.genome.genomegaps method)": [[5, "finaletoolkit.genome.GenomeGaps.get_contig_gaps"]], "hg38() (finaletoolkit.genome.genomegaps class method)": [[5, "finaletoolkit.genome.GenomeGaps.hg38"]], "in_gap() (finaletoolkit.genome.contiggaps method)": [[5, "finaletoolkit.genome.ContigGaps.in_gap"]], "in_tcmere() (finaletoolkit.genome.contiggaps method)": [[5, "finaletoolkit.genome.ContigGaps.in_tcmere"]], "in_tcmere() (finaletoolkit.genome.genomegaps method)": [[5, "finaletoolkit.genome.GenomeGaps.in_tcmere"]], "overlaps_gap() (finaletoolkit.genome.genomegaps method)": [[5, "finaletoolkit.genome.GenomeGaps.overlaps_gap"]], "to_bed() (finaletoolkit.genome.genomegaps method)": [[5, "finaletoolkit.genome.GenomeGaps.to_bed"]], "ucsc_hg19() (finaletoolkit.genome.genomegaps class method)": [[5, "finaletoolkit.genome.GenomeGaps.ucsc_hg19"]], "ucsc_hg19_gap_bed() (in module finaletoolkit.genome)": [[5, "finaletoolkit.genome.ucsc_hg19_gap_bed"]], "ucsc_hg38_gap_bed() (in module finaletoolkit.genome)": [[5, "finaletoolkit.genome.ucsc_hg38_gap_bed"]], "adjust_wps() (in module finaletoolkit.frag)": [[7, "finaletoolkit.frag.adjust_wps"]], "multi_wps() (in module finaletoolkit.frag)": [[7, "finaletoolkit.frag.multi_wps"]], "wps() (in module finaletoolkit.frag)": [[7, "finaletoolkit.frag.wps"]]}}) \ No newline at end of file diff --git a/docs/_documentation/cli_reference/index.rst b/docs/_documentation/cli_reference/index.rst index 2df0e731..e8ce5b0a 100644 --- a/docs/_documentation/cli_reference/index.rst +++ b/docs/_documentation/cli_reference/index.rst @@ -3,6 +3,5 @@ CLI ========================================= .. argparse:: - :module: finaletoolkit.cli - :func: main_cli_parser + :ref: finaletoolkit.cli.main_cli.main_cli_parser :prog: finaletoolkit \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index f1d4cfae..278b4db3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -13,14 +13,13 @@ # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration -extensions = [] - templates_path = ['_templates'] exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] extensions = [ 'sphinx.ext.autodoc', 'sphinxarg.ext', + 'sphinx_click', ] # -- Options for HTML output ------------------------------------------------- diff --git a/docs/index.rst b/docs/index.rst index 5c53cdd7..9e850a13 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -52,4 +52,4 @@ Contact License ----------------- -For academic research, please refer to MIT license. For commerical usage, please contact the authors. \ No newline at end of file +For academic research, please refer to MIT license. \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 96ea77b1..0be3710a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,7 @@ classifiers = [ ] dependencies = [ "numpy", + "click", "pysam", "pybedtools", "pybigwig", @@ -36,9 +37,6 @@ dependencies = [ "pandas", "cython", "statsmodels", - "sphinx<7.0.0", - "sphinx_rtd_theme", - "sphinx-argparse", "loess", ] diff --git a/src/finaletoolkit/cli/main_cli.py b/src/finaletoolkit/cli/main_cli.py index fd6b4111..3e308e64 100644 --- a/src/finaletoolkit/cli/main_cli.py +++ b/src/finaletoolkit/cli/main_cli.py @@ -18,811 +18,155 @@ from finaletoolkit.frag.cleavage_profile import _cli_cleavage_profile from finaletoolkit.genome.gaps import _cli_gap_bed -# TODO: implement subcommands read from stdin -# TODO: implement pipelining def main_cli_parser(): - parser = argparse.ArgumentParser( - description='Calculates fragmentation features given a CRAM, BAM, SAM,' - ' or Frag.gz file.', - epilog='') - subparsers = parser.add_subparsers(title='subcommands', - dest='subcommand') - - # Common arguments - - # Subcommand 1: frag-coverage - parser_command1 = subparsers.add_parser( - 'coverage', - description=( - 'Calculates fragmentation coverage over intervals in a BED file given ' - 'a SAM, BAM, CRAM, or Frag.gz file' - ) - ) - # TODO: accept tabix - - parser_command1.add_argument( - 'input_file', - help='SAM, BAM, CRAM, or Frag.gz file containing fragment data' - ) - parser_command1.add_argument( - 'interval_file', - help='BED file containing intervals over which coverage is calculated' - ) - parser_command1.add_argument( - '-o', - '--output_file', - default='-', - help='BED file where coverage is printed' - ) - parser_command1.add_argument( - '-s', - '--scale-factor', - default=1e6, - type=float, - help='Amount coverage will be multiplied by' - ) - parser_command1.add_argument( - '-q', - '--quality_threshold', - default=30, - type=int - ) - parser_command1.add_argument( - '-w', - '--workers', - default=1, - type=int, - help='Number of worker processes to use. Default is 1.' - ) - parser_command1.add_argument( - '-v', - '--verbose', - action='store_true', - default=0 - ) + parser = argparse.ArgumentParser(description='FinaleToolkit is a package and standalone program to extract fragmentation features of cell-free DNA from paired-end sequencing data.', epilog='') + subparsers = parser.add_subparsers() + + parser_command1 = subparsers.add_parser('coverage', description='Calculates fragmentation coverage over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.') + parser_command1.add_argument('input_file', help='Path to a BAM/SAM/CRAM/Fragment file containing fragment data.') + parser_command1.add_argument('interval_file', help='Path to a BED file containing intervals to calculate coverage over.') + parser_command1.add_argument('-o', '--output_file', default='-', help='A BED file containing coverage values over the intervals specified in interval file.') + parser_command1.add_argument('-s', '--scale-factor', default=1e6, type=float, help='Scale factor for coverage values.') + parser_command1.add_argument('-q', '--quality_threshold', default=30, type=int, help='Minimum mapping quality threshold.') + parser_command1.add_argument('-w', '--workers', default=1, type=int, help='Number of worker processes.') + parser_command1.add_argument('-v', '--verbose', action='store_true', help='Enable verbose mode to display detailed processing information.') parser_command1.set_defaults(func=coverage) - # Subcommand 2: frag-length - parser_command2 = subparsers.add_parser( - 'frag-length', prog='finaletoolkit-frag-length', - description='Calculates fragment lengths given a CRAM/BAM/SAM file', - ) - parser_command2.add_argument( - 'input_file', - type=str, - help='bam or frag.gz file containing fragment data.', - ) - parser_command2.add_argument( - '-c', - '--contig', - type=str, - help='contig or chromosome to select fragments from. Required if ' - 'using --start or --stop.', - ) - parser_command2.add_argument( - '-S', - '--start', - type=int, - help='0-based left-most coordinate of interval to select fragments' - 'from. Must also use --contig.', - ) - parser_command2.add_argument( - '-E', - '--stop', - help='1-based right-most coordinate of interval to select fragments' - 'from. Must also use --contig.', - type=int, - ) - parser_command2.add_argument( - '-p', - '--intersect_policy', - default='midpoint', - type=str, - help='Specifies what policy is used to include fragments in the given ' - 'interval. Default is "midpoint". Policies include:\n' - '- midpoint: the average of end coordinates of a fragment lies' - 'in the interval.\n' - '- any: any part of the fragment is in the interval.', - ) - parser_command2.add_argument( - '-o', - '--output_file', - default='-', - type=str, - help='File to write results to. "-" may be used to write to stdout. ' - 'Default is "-".', - ) - parser_command2.add_argument( - '-q', - '--quality_threshold', - default=30, - type=int, - help="Minimum MAPQ. Default is 30." - ) - parser_command2.add_argument( - '-v', - '--verbose', - action='count', - default=0, - help='Verbose logging.' - ) - parser_command2.set_defaults(func=_cli_frag_length) - - # Subcommand 3: frag_length_bins() - parser_command3 = subparsers.add_parser( - 'frag-length-bins', prog='finaletoolkit-frag-length-bins', - description='computes frag lengths of fragments and agregates in bins ' - 'by length. Either writes bins and counts to tsv or prints a histogram' - ) - parser_command3.add_argument( - 'input_file', - help='BAM or SAM file containing fragment data' - ) - parser_command3.add_argument( - '-c', - '--contig', - type=str, - help='contig or chromosome to select fragments from. Required if ' - 'using --start or --stop.', - ) - parser_command3.add_argument( - '-S', - '--start', - type=int, - help='0-based left-most coordinate of interval to select fragments' - 'from. Must also use --contig.', - ) - parser_command3.add_argument( - '-p', - '--intersect_policy', - default='midpoint', - type=str, - help='Specifies what policy is used to include fragments in the given ' - 'interval. Default is "midpoint". Policies include:\n' - '- midpoint: the average of end coordinates of a fragment lies' - 'in the interval.\n' - '- any: any part of the fragment is in the interval.', - ) - parser_command3.add_argument( - '-E', - '--stop', - help='1-based right-most coordinate of interval to select fragments' - 'from. Must also use --contig.', - type=int, - ) - parser_command3.add_argument( - '--bin-size', - type=int, - help='Used to specify a custom bin size instead of automatically' - ' calculating one.') - parser_command3.add_argument( - '-o', - '--output_file', - default='-', - type=str, - help='File to write results to. "-" may be used to write to stdout. ' - 'Default is "-".', - ) - parser_command3.add_argument( - '--contig-by-contig', - action='store_true', - help='Placeholder, not implemented.' - ) - parser_command3.add_argument( - '--histogram', - action='store_true', - help='Draws a histogram in the terminal.' - ) - parser_command3.add_argument( - '-q', - '--quality_threshold', - default=30, - type=int, - help="Minimum MAPQ. Default is 30." - ) - parser_command3.add_argument( - '-v', - '--verbose', - action='count', - default=0, - help='Verbose logging.' - ) + parser_command3 = subparsers.add_parser('frag-length-bins', prog='finaletoolkit-frag-length-bins', description='Retrieves fragment lengths grouped in bins given a BAM/SAM/CRAM/Fragment file.') + parser_command3.add_argument('input_file', help='Path to a BAM/SAM/CRAM/Fragment file containing fragment data.') + parser_command3.add_argument('-c', '--contig', type=str, help='Specify the contig or chromosome to select fragments from. (Required if using --start or --stop.)') + parser_command3.add_argument('-S', '--start', type=int, help='Specify the 0-based left-most coordinate of the interval to select fragments from. (Must also specify --contig.)') + parser_command3.add_argument('-p', '--intersect_policy', default='midpoint', type=str, help='Specifies what policy is used to include fragments in the given interval. See User Guide for more information.') + parser_command3.add_argument('-E', '--stop', help='Specify the 1-based right-most coordinate of the interval to select fragments from. (Must also specify --contig.)', type=int) + parser_command3.add_argument('--bin-size', type=int, help='Specify the size of the bins to group fragment lengths into.') + parser_command3.add_argument('-o', '--output_file', default='-', type=str, help='A .TSV file containing containing fragment lengths binned according to the specified bin size.') + parser_command3.add_argument('--contig-by-contig', action='store_true', help='Placeholder, not implemented.') + parser_command3.add_argument('--histogram', action='store_true', help='Enable histogram mode to display histogram in terminal.') + parser_command3.add_argument('-q', '--quality_threshold', default=30, type=int, help="Minimum mapping quality threshold.") + parser_command3.add_argument('-v', '--verbose', action='count', default=0, help='Enable verbose mode to display detailed processing information.') parser_command3.set_defaults(func=frag_length_bins) - # Subcommand 3_1: frag_length_intervals - parser_command3_1 = subparsers.add_parser( - 'frag-length-intervals', - description='Calculates frag lengths statistics over user-specified ' - 'genomic intervals.' - ) - parser_command3_1.add_argument( - 'input_file', - help='BAM or SAM file containing PE WGS of cfDNA' - ) - parser_command3_1.add_argument( - 'interval_file', - help='BED file containing intervals over which to produce statistics' - ) - parser_command3_1.add_argument( - '-p', - '--intersect_policy', - default='midpoint', - type=str, - help='Specifies what policy is used to include fragments in the given ' - 'interval. Default is "midpoint". Policies include:\n' - '- midpoint: the average of end coordinates of a fragment lies' - 'in the interval.\n' - '- any: any part of the fragment is in the interval.', - ) - parser_command3_1.add_argument( - '-o', - '--output-file', - default='-', - help='File to print results to. if "-", will print to stdout. Default' - 'is "-".' - ) - parser_command3_1.add_argument( - '-q', - '--quality-threshold', - default=30, - type=int, - help='minimum MAPQ to filter for' - ) - parser_command3_1.add_argument( - '-w', - '--workers', - default=1, - type=int, - help='Number of subprocesses to use' - ) - parser_command3_1.add_argument( - '-v', - '--verbose', - default=0, - action='count', - help='Determines how much is written to stderr' - ) + parser_command3_1 = subparsers.add_parser('frag-length-intervals', description='Retrieves fragment length summary statistics over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.') + parser_command3_1.add_argument('input_file', help='Path to a BAM/SAM/CRAM/Fragment file containing fragment data.') + parser_command3_1.add_argument('interval_file', help='Path to a BED file containing intervals to retrieve fragment length summary statistics over.') + parser_command3_1.add_argument('-p', '--intersect_policy', default='midpoint', type=str, help='Specifies what policy is used to include fragments in the given interval. See User Guide for more information.') + parser_command3_1.add_argument('-o', '--output-file', default='-', help='A BED file containing fragment length summary statistics (mean, median, st. dev, min, max) over the intervals specified in the interval file.') + parser_command3_1.add_argument('-q', '--quality-threshold', default=30, type=int, help='Minimum mapping quality threshold.') + parser_command3_1.add_argument('-w', '--workers', default=1, type=int, help='Number of worker processes.') + parser_command3_1.add_argument('-v', '--verbose', default=0, action='count', help='Enable verbose mode to display detailed processing information.') parser_command3_1.set_defaults(func=frag_length_intervals) - # Subcommand 4: wps (on interval bed file) - parser_command4 = subparsers.add_parser( - 'wps', - prog='finaletoolkit-wps', - description='Calculates Windowed Protection Score over a region ' - 'around sites specified in a BED file from alignments in a ' - 'CRAM/BAM/SAM/Frag.gz file' - ) - parser_command4.add_argument( - 'input_file', - help='bam or sam file containing paired-end reads of cfDNA WGS' - ) - parser_command4.add_argument( - 'site_bed', - help='bed file containing sites over which to calculate wps' - ) - parser_command4.add_argument( - '-o', - '--output_file', - default='-', - help='BigWig file to write results to. Default is stdout' - ) - parser_command4.add_argument( - '-i', - '--interval_size', - default=5000, - type=int - ) - parser_command4.add_argument( - '-W', - '--window_size', - default=120, - type=int - ) - parser_command4.add_argument( - '-lo', - '--fraction_low', - default=120, - type=int - ) - parser_command4.add_argument( - '-hi', - '--fraction_high', - default=180, - type=int - ) - parser_command4.add_argument( - '-q', - '--quality_threshold', - default=30, - type=int - ) - parser_command4.add_argument( - '-w', - '--workers', - default=1, - type=int - ) - parser_command4.add_argument( - '-v', - '--verbose', - action='count', - default=0) + parser_command4 = subparsers.add_parser('wps', prog='finaletoolkit-wps', description='Calculates Windowed Protection Score (WPS) over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.') + parser_command4.add_argument('input_file', help='Path to a BAM/SAM/CRAM/Fragment file containing fragment data.') + parser_command4.add_argument('site_bed', help='Path to a BED file containing intervals to calculate WPS over.') + parser_command4.add_argument('-o', '--output_file', default='-', help='A bigWig file containing the WPS results over the intervals specified in interval file.') + parser_command4.add_argument('-i', '--interval_size', default=5000, type=int, help='Size in bp of each interval in the interval file.') + parser_command4.add_argument('-W', '--window_size', default=120, type=int, help='Size of the sliding window used to calculate WPS scores.') + parser_command4.add_argument('-lo', '--fraction_low', default=120, type=int, help='Minimum length for a fragment to be included in WPS calculation.') + parser_command4.add_argument('-hi', '--fraction_high', default=180, type=int, help='Maximum length for a fragment to be included in WPS calculation.') + parser_command4.add_argument('-q', '--quality_threshold', default=30, type=int, help="Minimum mapping quality threshold.") + parser_command4.add_argument('-w', '--workers', default=1, type=int, help='Number of worker processes.') + parser_command4.add_argument('-v', '--verbose', action='count', default=0, help='Enable verbose mode to display detailed processing information.') parser_command4.set_defaults(func=multi_wps) - # Subcommand 5: delfi - parser_command5 = subparsers.add_parser( - 'delfi', - prog='finaletoolkit-delfi', - description='Calculates DELFI score over genome.' - '\nNOTE: due to some ' - 'ad hoc implementation details, currently the only accepted reference ' - "genome is hg19." - ) - parser_command5.add_argument( - 'input_file', - help="SAM, BAM, CRAM, or Frag.gz file containing fragment reads.") - parser_command5.add_argument( - 'autosomes', - help="Tab-delimited file where column one is chromosomes and column " - "two is the length of said chromosome." - ) - parser_command5.add_argument( - 'reference_file', - help="2bit file for reference sequence used during alignment." - ) - parser_command5.add_argument( - 'bins_file', - help="BED format file containing bins over which to calculate delfi. " - "To replicate Cristiano and colleage's methodology, use 100kb bins " - "over human autosomes." - ) - parser_command5.add_argument( - '-b', '--blacklist_file', - help="BED file containing darkregions to ignore when calculating DELFI." - ) - parser_command5.add_argument( - '-g', '--gap_file', - help='BED4 format file with columns "chrom","start","stop","type". ' - '"type" should be "centromere", "telomere", or "short arm"; all others' - ' are ignored. This information corresponds to "gap" track for hg19 in' - ' UCSC Genome Browser.' - ) - parser_command5.add_argument( - '-o', '--output_file', default='-', - help='BED, bed.gz, tsv, or csv file to write results to. If "-", ' - 'writes tab-deliniated data to stdout. Default is "-".') - parser_command5.add_argument( - '-W', '--window_size', default=5000000, type=int, - help="Currently unused.") - parser_command5.add_argument( - '-gc', '--gc_correct', action='store_true', - help="Indicate whther or not gc correction is applied.") - parser_command5.add_argument( - '-m', '--merge_bins', action='store_true', - help="Indicate whther or not bins are merged to 5Mb bins.") - parser_command5.add_argument( - '-q', '--quality_threshold', default=30, type=int, - help="MAPQ to be filtered.") - parser_command5.add_argument( - '-w', '--workers', default=1, type=int, - help="Maximum number of subprocesses to spawn. Should be close to " - "number of cores.") - parser_command5.add_argument('-v', '--verbose', action='count', default=0) + parser_command5 = subparsers.add_parser('delfi', prog='finaletoolkit-delfi', description='Calculates DELFI score over genome. NOTE: Due to some ad hoc implementation details, currently the only accepted reference genome is hg19.') + parser_command5.add_argument('input_file', help="Path to a BAM/SAM/CRAM/Fragment file containing fragment data.") + parser_command5.add_argument('autosomes', help="Tab-delimited file containing (1) autosome name and (2) integer length of chromosome in base pairs.") + parser_command5.add_argument('reference_file', help="The .2bit file for the associate reference genome sequence used during alignment.") + parser_command5.add_argument('bins_file', help="A BED file containing bins over which to calculate DELFI. To replicate Cristiano et al.'s methodology, use 100kb bins over human autosomes.") + parser_command5.add_argument('-b', '--blacklist_file', help="BED file containing regions to ignore when calculating DELFI.") + parser_command5.add_argument('-g', '--gap_file', help='BED4 format file containing columns for "chrom", "start", "stop", and "type". The "type" column should denote whether the entry corresponds to a "centromere", "telomere", or "short arm", and entries not falling into these categories are ignored. This information corresponds to the "gap" track for hg19 in the UCSC Genome Browser.') + parser_command5.add_argument('-o', '--output_file', default='-', help='BED, bed.gz, TSV, or CSV file to write results to. If "-", writes to stdout.') + parser_command5.add_argument('-W', '--window_size', default=5000000, type=int, help="Currently unused.") + parser_command5.add_argument('-gc', '--gc_correct', action='store_true', help="Indicates whether to apply GC correction.") + parser_command5.add_argument('-m', '--merge_bins', action='store_true', help="Indicates whether to merge bins to 5Mb size.") + parser_command5.add_argument('-q', '--quality_threshold', default=30, type=int, help="Minimum mapping quality threshold.") + parser_command5.add_argument('-w', '--workers', default=1, type=int, help="Number of worker processes.") + parser_command5.add_argument('-v', '--verbose', action='count', default=0, help='Enable verbose mode to display detailed processing information.') parser_command5.set_defaults(func=delfi) - # Subcommand 6: filter_bam - parser_command6 = subparsers.add_parser( - 'filter-bam', - prog='finaletoolkit-filter-bam', - description='Filters a BAM file so that all reads are in mapped pairs' - ', exceed a certain MAPQ, are not flagged for quality, are read1, are' - ' not secondary or supplementary alignments, and are on the same ' - 'reference sequence as the mate.' - ) - parser_command6.add_argument( - 'input_file', - help='BAM file with PE WGS' - ) - parser_command6.add_argument( - '-r', - '--region-file', - default=None, - help='BED file containing regions to read fragments from. Default is' - ' None.' - ) - parser_command6.add_argument( - '-o', - '--output-file', - default='-', - help='Path to write filtered BAM. Defualt is "-". If set to "-",' - ' the BAM file will be written to stdout.' - ) - parser_command6.add_argument( - '-q', - '--quality_threshold', - type=int, - default=30, - help='Minimum mapping quality to filter for. Defualt is 30.' - ) - parser_command6.add_argument( - '-hi', - '--fraction-high', - type=int, - default=None, - help='Maximum fragment size. Default is None' - ) - parser_command6.add_argument( - '-lo', - '--fraction-low', - type=int, - default=None, - help='Minimum fragment size. Default is None' - ) - parser_command6.add_argument( - '-w', - '--workers', - type=int, - default=1, - help='Number of worker processes to spawn.' - ) - parser_command6.add_argument( - '-v', - '--verbose', - action='count', - help='Specify verbosity. Number of printed statements is proportional ' - 'to number of vs.' - ) + parser_command6 = subparsers.add_parser('filter-bam', prog='finaletoolkit-filter-bam', description='Filters a BAM file so that all reads are in mapped pairs, exceed a certain MAPQ, are not flagged for quality, are read1, are not secondary or supplementary alignments, and are on the same reference sequence as the mate.') + parser_command6.add_argument('input_file', help='Path to BAM file.') + parser_command6.add_argument('-r', '--region-file', default=None, help='Only output alignments overlapping the intervals in this BED file will be included.') + parser_command6.add_argument('-o', '--output-file', default='-', help='Output BAM file path.') + parser_command6.add_argument('-q', '--quality_threshold', type=int, default=30, help='Minimum mapping quality threshold.') + parser_command6.add_argument('-hi', '--fraction-high', type=int, default=None, help='Maximum length for a fragment to be included in output BAM.') + parser_command6.add_argument('-lo', '--fraction-low', type=int, default=None, help='Minimum length for a fragment to be included in output BAM.') + parser_command6.add_argument('-w', '--workers', type=int, default=1, help='Number of worker processes.') + parser_command6.add_argument('-v', '--verbose', action='count', help='Enable verbose mode to display detailed processing information.') parser_command6.set_defaults(func=filter_bam) - # Subcommand 7: adjust WPS - parser_command7 = subparsers.add_parser( - 'adjust-wps', - prog='finaletoolkit-adjust-wps', - description='Reads WPS data from a WIG file and applies a median filter' - ' and a Savitsky-Golay filter (Savitsky and Golay, 1964).' - ) - parser_command7.add_argument( - 'input_file', - help='BigWig file with WPS data.' - ) - parser_command7.add_argument( - 'interval_file', - help='BED file containing intervals over which wps was calculated' - ) - parser_command7.add_argument( - 'genome_file', - help='GENOME file containing chromosome/contig names and lengths. ' - 'Needed to write head for BigWig.' - ) - parser_command7.add_argument( - '-o', - '--output-file', - default='-', - help='WIG file to print filtered WPS data. If "-", will write to ' - 'stdout. Default is "-".' - ) - parser_command7.add_argument( - '-m', - '--median-window-size', - default=1000, - type=int, - help='Size of window for median filter. Default is 1000.' - ) - parser_command7.add_argument( - '-s', - '--savgol-window-size', - default=21, - type=int, - help='Size of window for Savitsky-Golay filter. Default is 21.' - ) - parser_command7.add_argument( - '-p', - '--savgol-poly-deg', - default=2, - type=int, - help='Degree polynomial for Savitsky-Golay filter. Default is 2.' - ) - parser_command7.add_argument( - '-w', - '--workers', - default=1, - type=int, - help='Number of subprocesses to use. Default is 1.' - ) - parser_command7.add_argument( - '--mean', - action='store_true', - ) - parser_command7.add_argument( - '--subtract-edges', - action='store_true', - ) - parser_command7.add_argument( - '-v', - '--verbose', - action='count', - help='Specify verbosity. Number of printed statements is proportional to number of vs.' - ) + parser_command7 = subparsers.add_parser('adjust-wps', prog='finaletoolkit-adjust-wps', description='Adjusts raw Windowed Protection Score (WPS) by applying a median filter and Savitsky-Golay filter.') + parser_command7.add_argument('input_file', help='A bigWig file containing the WPS results over the intervals specified in interval file.') + parser_command7.add_argument('interval_file', help='Path to a BED file containing intervals to WPS was calculated over.') + parser_command7.add_argument('genome_file', help='A .chrom.sizes file containing chromosome sizes.') + parser_command7.add_argument('-o', '--output-file', default='-', help='A bigWig file containing the adjusted WPS results over the intervals specified in interval file.') + parser_command7.add_argument('-m', '--median-window-size', default=1000, type=int, help='Size of the median filter window used to adjust WPS scores.') + parser_command7.add_argument('-s', '--savgol-window-size', default=21, type=int, help='Size of the Savitsky-Golay filter window used to adjust WPS scores.') + parser_command7.add_argument('-p', '--savgol-poly-deg', default=2, type=int, help='Degree polynomial for Savitsky-Golay filter.') + parser_command7.add_argument('-w', '--workers', default=1, type=int, help='Number of worker processes.') + parser_command7.add_argument('--mean', action='store_true', help='A mean filter is used instead of median.') + parser_command7.add_argument('--subtract-edges', action='store_true', help='Take the median of the first and last 500 bases in a window and subtract from the whole interval.') + parser_command7.add_argument('-v', '--verbose', action='count', help='Enable verbose mode to display detailed processing information.') parser_command7.set_defaults(func=adjust_wps) - # Subcommand 8: aggregate BigWig/WPS - parser_command8 = subparsers.add_parser( - 'agg-bw', - prog='finaletoolkit-agg-wps', - description='Reads data from a BigWig file and aggregates over' - ' intervals in a BED file.' - ) - parser_command8.add_argument( - 'input_file', - help='BigWig file with data.' - ) - parser_command8.add_argument( - 'interval_file', - help='BED file containing intervals over which wps was calculated' - ) - parser_command8.add_argument( - '-o', - '--output-file', - default='-', - help='WIG file to print filtered WPS data. If "-", will write to ' - 'stdout. Default is "-".' - ) - parser_command8.add_argument( - '-m', - '--median-window-size', - default=1000, - type=int, - help='Size of window for median filter. Default is 1000.' - ) - parser_command8.add_argument( - '-v', - '--verbose', - action='count', - help='Specify verbosity. Number of printed statements is proportional to number of vs.' - ) + parser_command8 = subparsers.add_parser('agg-bw', prog='finaletoolkit-agg-wps', description='Aggregates a bigWig signal over constant-length intervals defined in a BED file.') + parser_command8.add_argument('input_file', help=' A bigWig file containing signals over the intervals specified in interval file.') + parser_command8.add_argument('interval_file', help='Path to a BED file containing intervals over which signals were calculated over.') + parser_command8.add_argument('-o', '--output-file', default='-', help='A wiggle file containing the aggregate signal over the intervals specified in interval file.') + parser_command8.add_argument('-m', '--median-window-size', default=0, type=int, help='Size of the median filter window used to adjust WPS scores. Only modify if aggregating WPS signals.') + parser_command8.add_argument('-v', '--verbose', action='count', help='Enable verbose mode to display detailed processing information.') parser_command8.set_defaults(func=agg_bw) - # Subcommand 9: delfi gc correct - parser_command9 = subparsers.add_parser( - 'delfi-gc-correct', - prog='finaletoolkit-delfi-gc-correct', - description='Performs gc-correction on raw delfi data.' - ) - parser_command9.add_argument( - 'input_file', - help='BED3+3 file containing raw data' - ) - parser_command9.add_argument( - '-o', - '--output-file', - default='-', - help='BED3+3 to print GC-corrected DELFI fractions. If "-", will write' - ' to stdout. Default is "-".' - ) - parser_command9.add_argument( - '--header-lines', - default=1, - type=int, - help='Number of header lines in BED. Default is 1.' - ) - parser_command9.add_argument( - '-v', - '--verbose', - action='count', - help='Specify verbosity. Number of printed statements is proportional ' - 'to number of vs.' - ) + parser_command9 = subparsers.add_parser('delfi-gc-correct', prog='finaletoolkit-delfi-gc-correct', description='Performs gc-correction on raw delfi data.') + parser_command9.add_argument('input_file', help='BED3+3 file containing raw data') + parser_command9.add_argument('-o', '--output-file', default='-', help='BED3+3 to print GC-corrected DELFI fractions. If "-", will write to stdout. Default is "-".') + parser_command9.add_argument('--header-lines', default=1, type=int, help='Number of header lines in BED. Default is 1.') + parser_command9.add_argument('-v', '--verbose', action='count', help='Specify verbosity. Number of printed statements is proportional to number of vs.') parser_command9.set_defaults(func=cli_delfi_gc_correct) - # Subcommand 10: end motifs - parser_command10 = subparsers.add_parser( - 'end-motifs', - prog='finaletoolkit-end-motifs', - description="Measures frequency of k-mer 5' end motifs and tabulates" - " data into a tab-delimited file." - ) - parser_command10.add_argument( - 'input_file', - help='SAM, BAM, or tabix-indexed file with fragment data.' - ) - parser_command10.add_argument( - 'refseq_file', - help='2bit file containing reference sequence that fragments were' - ' aligned to.' - ) - parser_command10.add_argument( - '-k', - default=4, - type=int, - help='Length of k-mer. Default is 4.' - ) - parser_command10.add_argument( - '-o', - '--output-file', - default='-', - help='TSV to print k-mer frequencies. If "-", will write' - ' to stdout. Default is "-".' - ) - parser_command10.add_argument( - '-q', - '--quality-threshold', - default=20, - type=int, - help='Minimum MAPQ of reads. Default is 20.' - ) - parser_command10.add_argument( - '-w', - '--workers', - default=1, - type=int, - help='Number of subprocesses to use. Default is 1.' - ) - parser_command10.add_argument( - '-v', - '--verbose', - default=0, - action='count', - help='Specify verbosity. Number of printed statements is proportional ' - 'to number of vs.' - ) + parser_command10 = subparsers.add_parser('end-motifs', prog='finaletoolkit-end-motifs', description="Measures frequency of k-mer 5' end motifs and tabulates data into a tab-delimited file.") + parser_command10.add_argument('input_file', help='SAM, BAM, or tabix-indexed file with fragment data.') + parser_command10.add_argument('refseq_file', help='2bit file containing reference sequence that fragments were aligned to.') + parser_command10.add_argument('-k', default=4, type=int, help='Length of k-mer. Default is 4.') + parser_command10.add_argument('-o', '--output-file', default='-', help='TSV to print k-mer frequencies. If "-", will write to stdout. Default is "-".') + parser_command10.add_argument('-q', '--quality-threshold', default=20, type=int, help='Minimum MAPQ of reads. Default is 20.') + parser_command10.add_argument('-w', '--workers', default=1, type=int, help='Number of subprocesses to use. Default is 1.') + parser_command10.add_argument('-v', '--verbose', default=0, action='count', help='Specify verbosity. Number of printed statements is proportional to number of vs.') parser_command10.set_defaults(func=end_motifs) - # subcommand 10a: interval-end-motifs - parser_command10a = subparsers.add_parser( - 'interval-end-motifs', - prog='finaletoolkit-interval-end-motifs', - description="Measures frequency of k-mer 5' end motifs in each " - "region specified in a BED file and writes data into a table." - ) - parser_command10a.add_argument( - 'input_file', - help='SAM, BAM, or tabix-indexed file with fragment data.' - ) - parser_command10a.add_argument( - 'refseq_file', - help='2bit file containing reference sequence that fragments were' - ' aligned to.' - ) - parser_command10a.add_argument( - 'intervals', - help='BED file containing intervals or list of tuples' - ) - parser_command10a.add_argument( - '-k', - default=4, - type=int, - help='Length of k-mer. Default is 4.' - ) - parser_command10a.add_argument( - '-lo', '--fraction-low', - default=10, - type=int, - help='Smallest fragment length to consider. Default is 10' - ) - parser_command10a.add_argument( - '-hi', '--fraction-high', - default=600, - type=int, - help='Longest fragment length to consider. Default is 600' - ) - parser_command10a.add_argument( - '-o', - '--output-file', - default='-', - help="File path to write results to. Either tsv or csv." - ) - parser_command10a.add_argument( - '-q', - '--quality-threshold', - default=20, - type=int, - help='Minimum MAPQ of reads. Default is 20.' - ) - parser_command10a.add_argument( - '-w', - '--workers', - default=1, - type=int, - help='Number of subprocesses to use. Default is 1.' - ) - parser_command10a.add_argument( - '-v', - '--verbose', - default=0, - action='count', - help='Specify verbosity. Number of printed statements is proportional ' - 'to number of vs.' - ) - parser_command10a.set_defaults(func=interval_end_motifs) + parser_command10a = subparsers.add_parser('interval-end-motifs', prog='finaletoolkit-interval-end-motifs', description="Measures frequency of k-mer 5' end motifs in each region specified in a BED file and writes data into a table.") + parser_command10a.add_argument('input_file', help='SAM, BAM, or tabix-indexed file with fragment data.') + parser_command10a.add_argument('refseq_file', help='2bit file containing reference sequence that fragments were aligned to.') + parser_command10a.add_argument('intervals', help='BED file containing intervals or list of tuples') + parser_command10a.add_argument('-k', default=4, type=int, help='Length of k-mer. Default is 4.') + parser_command10a.add_argument('-lo', '--fraction-low', default=10, type=int, help='Smallest fragment length to consider. Default is 10') + parser_command10a.add_argument('-hi', '--fraction-high', default=600, type=int, help='Longest fragment length to consider. Default is 600') + parser_command10a.add_argument('-o', '--output-file', default='-', help="File path to write results to. Either tsv or csv.") + parser_command10a.add_argument('-q', '--quality-threshold', default=20, type=int, help='Minimum MAPQ of reads. Default is 20.') + parser_command10a.add_argument('-w', '--workers', default=1, type=int, help='Number of subprocesses to use. Default is 1.') + parser_command10a.add_argument('-v', '--verbose', default=0, action='count', help='Specify verbosity. Number of printed statements is proportional to number of vs.') + parser_command10a.set_defaults(func=interval_end_motifs) - # Subcommand 11: MDS - parser_command11 = subparsers.add_parser( - 'mds', - prog='finaletoolkit-mds', - description='Reads k-mer frequencies from a file and calculates a ' - 'motif diversity score (MDS) using normalized Shannon entropy as ' - 'described by Jiang et al (2020). This function is generalized for ' - 'any k-mer instead of just 4-mers.' - ) - parser_command11.add_argument( - 'file_path', - nargs='?', - default='-', - help='Tab-delimited or similar file containing one column for all ' - 'k-mers a one column for frequency. Reads from stdin by default.' - ) - parser_command11.add_argument( - '-s', - '--sep', - default='\t', - help='Separator used in tabular file. Default is tab.' - ) - parser_command11.add_argument( - '--header', - default=0, - type=int, - help='Number of header rows to ignore. Default is 0' - ) + parser_command11 = subparsers.add_parser('mds', prog='finaletoolkit-mds', description='Reads k-mer frequencies from a file and calculates a motif diversity score (MDS) using normalized Shannon entropy as described by Jiang et al (2020). This function is generalized for any k-mer instead of just 4-mers.') + parser_command11.add_argument('file_path', nargs='?', default='-', help='Tab-delimited or similar file containing one column for all k-mers a one column for frequency. Reads from stdin by default.') + parser_command11.add_argument('-s', '--sep', default='\t', help='Separator used in tabular file. Default is tab.') + parser_command11.add_argument('--header', default=0, type=int, help='Number of header rows to ignore. Default is 0') parser_command11.set_defaults(func=_cli_mds) - - # Subcommand 11a: interval-mds - parser_command11a = subparsers.add_parser( - 'interval-mds', - prog='finaletoolkit-interval-mds', - description='Reads k-mer frequencies from a file and calculates a ' - 'motif diversity score (MDS) for each interval using normalized ' - 'Shannon entropy as ' - 'described by Jiang et al (2020). This function is generalized for ' - 'any k-mer instead of just 4-mers.' - ) - parser_command11a.add_argument( - 'file_path', - nargs='?', - default='-', - help='Tab-delimited or similar file containing one column for all ' - 'k-mers a one column for frequency. Reads from stdin by default.' - ) - parser_command11a.add_argument( - '-s', - '--sep', - default='\t', - help='Separator used in tabular file. Default is tab.' - ) - parser_command11a.add_argument( - 'file_out', - default='-' - ) + parser_command11a = subparsers.add_parser('interval-mds', prog='finaletoolkit-interval-mds', description='Reads k-mer frequencies from a file and calculates a motif diversity score (MDS) for each interval using normalized Shannon entropy as described by Jiang et al (2020). This function is generalized for any k-mer instead of just 4-mers.') + parser_command11a.add_argument('file_path', nargs='?', default='-', help='Tab-delimited or similar file containing one column for all k-mers a one column for frequency. Reads from stdin by default.') + parser_command11a.add_argument('-s', '--sep', default='\t', help='Separator used in tabular file. Default is tab.') + parser_command11a.add_argument('file_out', default='-') parser_command11a.set_defaults(func=_cli_interval_mds) - - # Subcommand 12: gap bed - parser_command12 = subparsers.add_parser( - 'gap-bed', - prog='finaletoolkit-gap-bed', - description='Creates a BED4 file containing centromeres, ' - 'telomeres, and short-arm intervals, similar to the gaps ' - 'annotation track for hg19 found on the UCSC Genome Browser ' - '(Kent et al 2002). Currently only supports hg19, b37, ' - 'human_g1k_v37, hg38, and GRCh38', - epilog='Gap is used liberally in this command, and in the case ' - 'hg38/GRCh38, may refer to regions where there no longer are ' - 'gaps in the reference sequence.' - ) - parser_command12.add_argument( - 'reference_genome', - choices=['hg19', 'b37','human_g1k_v37', 'hg38', 'GRCh38'], - help='Reference genome to provide gaps for.' - ) - parser_command12.add_argument( - 'output_file', - help='Path to write bed file to. If "-" used, writes to stdout.' - ) + parser_command12 = subparsers.add_parser('gap-bed', prog='finaletoolkit-gap-bed', description='Creates a BED4 file containing centromeres, telomeres, and short-arm intervals, similar to the gaps annotation track for hg19 found on the UCSC Genome Browser (Kent et al 2002). Currently only supports hg19, b37, human_g1k_v37, hg38, and GRCh38', epilog='Gap is used liberally in this command, and in the case hg38/GRCh38, may refer to regions where there no longer are gaps in the reference sequence.') + parser_command12.add_argument('reference_genome', choices=['hg19', 'b37','human_g1k_v37', 'hg38', 'GRCh38'], help='Reference genome to provide gaps for.') + parser_command12.add_argument('output_file', help='Path to write bed file to. If "-" used, writes to stdout.') parser_command12.set_defaults(func=_cli_gap_bed) - # Subcommand 13: cleavage profile parser_command13 = subparsers.add_parser( 'cleavage-profile', prog='finaletoolkit-cleavage-profile', @@ -872,7 +216,6 @@ def main_cli_parser(): type=int, help='Number of subprocesses to use. Default is 1.' ) - # TODO: include what each level of verbosity entails. parser_command13.add_argument( '-v', '--verbose', @@ -900,4 +243,4 @@ def main_cli(): parser.print_help() if __name__ == '__main__': - main_cli() + main_cli() \ No newline at end of file From c328630484efc59364a70bff0c8979eaf6c4c30f Mon Sep 17 00:00:00 2001 From: Ravi Bandaru <80599578+ravibandaru-lab@users.noreply.github.com> Date: Thu, 16 May 2024 09:14:48 -0500 Subject: [PATCH 26/79] Update documentation and argparse help. --- .../_documentation/user_guide/index.doctree | Bin 3030 -> 3079 bytes .../user_guide/intersectpolicy.doctree | Bin 0 -> 6512 bytes .../_documentation/cli_reference/index.html | 630 +++++++++++++++++- .../_documentation/user_guide/features.html | 1 + .../html/_documentation/user_guide/help.html | 1 + .../html/_documentation/user_guide/index.html | 6 + .../_documentation/user_guide/inputdata.html | 1 + .../user_guide/installation.html | 1 + .../user_guide/intersectpolicy.html | 492 ++++++++++++++ .../_documentation/user_guide/quickstart.html | 7 +- .../_documentation/user_guide/structure.html | 7 +- .../html/_documentation/user_guide/what.html | 1 + .../_documentation/user_guide/index.rst.txt | 1 + .../user_guide/intersectpolicy.rst.txt | 21 + docs/_build/html/index.html | 1 + docs/_build/html/objects.inv | Bin 1010 -> 1031 bytes docs/_build/html/searchindex.js | 10 +- docs/_documentation/user_guide/index.rst | 1 + .../user_guide/intersectpolicy.rst | 21 + src/finaletoolkit/cli/main_cli.py | 298 +++++++++ 20 files changed, 1490 insertions(+), 10 deletions(-) create mode 100644 docs/_build/doctrees/_documentation/user_guide/intersectpolicy.doctree create mode 100644 docs/_build/html/_documentation/user_guide/intersectpolicy.html create mode 100644 docs/_build/html/_sources/_documentation/user_guide/intersectpolicy.rst.txt create mode 100644 docs/_documentation/user_guide/intersectpolicy.rst diff --git a/docs/_build/doctrees/_documentation/user_guide/index.doctree b/docs/_build/doctrees/_documentation/user_guide/index.doctree index 4203c15da4e89f5c8980755d00dc189b14963496..89ebb1f295f7844744c0824b0d87996f965acaba 100644 GIT binary patch delta 109 zcmca6-Y&t?z&iEMMwZV^jGB|rGf9bN=9Q!t6{jYb6y)b*CRa{ro8s4_0+N|5#2mzw z;kP-3S%I0Ow}&sas3^Z^av+=V=J{;Lm}Sy4Qi^*x^AdAYODYRei>K61$w==k&QJu> KDVrO)LKy+6$tacp delta 63 zcmZpdxF*ihz&iExMwZV^lhv4WH&10&U}o&zyp8PvvrKA6QgIJwUSe))No7H5@s!#r S8L6Gc8HzwUY4awoP(}dw0~l2R diff --git a/docs/_build/doctrees/_documentation/user_guide/intersectpolicy.doctree b/docs/_build/doctrees/_documentation/user_guide/intersectpolicy.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2c78caeadf49acfb1436f67baa0749f6d068dc00 GIT binary patch literal 6512 zcmc&&TW=h<6}By}q}5$^EVPK7PSB)rP|E8b;EjhH4=x+~&y`ac8(oN}SM08JH4ps_ed|k~`ZEIL7v!Oj{m8lQ+LmOcKm=$pJUl!+m+u^s z=MSB~((hhye`Z}JjK@bk5{9u1smje_D1$7bvCg07Z~rm>G{0%ODH$u7r2);&1#kq6 zi!h~e{x~;lmR)n9dgb~BMFY)cTrX!GHqRCw=Qml`bTrq3wx-O+gILqluJJyUf(Mh_ z@`Cm9BYI?Ycn-&tywGbtA<#nSY}0i8T5UFG=1XmN&1J!3n(t-{QOy*{f`YU1xLbhS}@?R>6>d zG|{);xpSxgUg<{F|A6aXWrP0vJSKuZl2ROS-G{oWUn@da_4fAO2cr$9_W_M*O0-P(_B;}M zPW~Ygo*aTpX_9I;5n@E+5Z_vQNhX9hEF~y>$!OafGaj%ObXa~@qf&?WR*QeLFM zLK(4Y`#Hp~we0bEHotxD@V_9$^u!3ut z_sZVhvpQCpurWK;68NXKz|-r)XRbc{;u~7u1aiurvn5COxqDDf2eKvQpE zkAaAXiG(*0Kbc~TIPL9K(fB`j^B*tg%`coc*JsphMdypQyjHkZ+NM-tUaYKZ3HWDQ z!0F*F6uNAk(-QI`El_ct11kmQFlsIP&w2K~*lS6c+W2hfSZ<+XxhkF2#cQJ?n8k-B z5-QyrLIcjP&TfFc0exApy9&NGRk{D&4%b}|Iqy}ms>(!NaYKp=K!n>GDlelBy7*}- zvb$#h%*8zeMGCQsrS5qTirQWa9ugrGV6Vp%_o4c9cEzYXDz|NU!zD=LM8NH(CAH`M zQYgAzPuU%ut8ShLh5tRfBkd*RYnK*>-;SeN@cX*0cFXS5uR8ln7cX3BuRcBX3ZtL7 z?Yu~blW#lw*U!0s?O~5d2g~=cS6$7 z-A8?L&#EoszH9CG@4b}2knQ_FuUEK)zdDuhPs_@9*SoJgA>)y~NKK`2d0Q)}?tHed zkQ1}j-Yk@iD2|JS1YA#EGFHXovpMBXF5mkf)dm)?lT#tQ{}3x&>fS!D-A(d2VeJfh zx%>;xul#HZo}|esS(u$)i+kTR+6}gCSlXU!a;?g*_A9WuFJEh6d@4WPDc_`KIXodN zks8gGrn!vXD(=#GBdeM7>bV)gbA=@?=g-BIA(SlRG5q(spyl>Sj@S}s%x!M4o`jKM=Vc6~Uoua<27kc*-pxMjbv z30ida!Hfu7X(2+sjP7VX1VlG&RslKj2tX7(;yQo0@s?RjXyU^ucwonYbJ&Wd3&4!x9 znjHCzkC?ze@O#;w{JB|C5!#CWCmHfu!BJP;xET6E2Iz*mrt6J>p`RJx`d{Q5yzE?v z)dyLEEo_h3HIBgi?T(Mw1+{32hVkQxv=@YSCy08PbOJVBV$>deopVSYq*gbN}y1^8LTr zpF8&FC-&zr_UF&|$xPSs>PZ6UqUq_lj~(Z+<2ugR>y~Z>uobtOed(6Et6gSR+rf6b zuj10>GQ$F_pxB(Q_zE-Il!6b&102yniW)zT^_3Z7&E1`n*sXSTi>^$`FFLG9wrjJp z%9#sh2^A-hneC(JW;u{TATS64PMw8!OZroI=t=$?WDh#($V2r074TAQSQnlt@^Vdf cAz$WkAhOUxY-FRo6x!NYmJxeoXM^7V0H^J25C8xG literal 0 HcmV?d00001 diff --git a/docs/_build/html/_documentation/cli_reference/index.html b/docs/_build/html/_documentation/cli_reference/index.html index 7139c959..98eb8e4f 100644 --- a/docs/_build/html/_documentation/cli_reference/index.html +++ b/docs/_build/html/_documentation/cli_reference/index.html @@ -348,7 +348,15 @@

CLI#

FinaleToolkit is a package and standalone program to extract fragmentation features of cell-free DNA from paired-end sequencing data.

+<<<<<<< Updated upstream
usage: finaletoolkit [-h] {coverage,frag-length-bins,frag-length-intervals,wps,delfi,filter-bam,adjust-wps,agg-bw,delfi-gc-correct,end-motifs,interval-end-motifs,mds,interval-mds,gap-bed,cleavage-profile} ...
+=======
+<<<<<<< Updated upstream
+
usage: finaletoolkit [-h] {coverage,frag-length,frag-length-bins,frag-length-intervals,wps,delfi,filter-bam,adjust-wps,agg-bw,delfi-gc-correct,end-motifs,interval-end-motifs,mds,interval-mds,gap-bed,cleavage-profile} ...
+=======
+
usage: finaletoolkit [-h] {coverage,frag-length-bins,frag-length-intervals,cleavage-profile,wps,adjust-wps,delfi,delfi-gc-correct,end-motifs,interval-end-motifs,mds,interval-mds,filter-bam,agg-bw,gap-bed} ...
+>>>>>>> Stashed changes
+>>>>>>> Stashed changes
 
@@ -396,10 +404,24 @@

Named Arguments

frag-length-bins#

Retrieves fragment lengths grouped in bins given a BAM/SAM/CRAM/Fragment file.

finaletoolkit frag-length-bins [-h] [-c CONTIG] [-S START] [-p INTERSECT_POLICY] [-E STOP] [--bin-size BIN_SIZE] [-o OUTPUT_FILE] [--contig-by-contig] [--histogram] [-q QUALITY_THRESHOLD] [-v] input_file
+=======
+<<<<<<< Updated upstream
+
+

frag-length#

+

Calculates fragment lengths given a CRAM/BAM/SAM file

+
finaletoolkit frag-length [-h] [-c CONTIG] [-S START] [-E STOP] [-p INTERSECT_POLICY] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-v] input_file
+=======
+
+

frag-length-bins#

+

Retrieves fragment lengths grouped in bins given a BAM/SAM/CRAM/Fragment file.

+
finaletoolkit frag-length-bins [-h] [-c CONTIG] [-S START] [-p {midpoint,any}] [-E STOP] [--bin-size BIN_SIZE] [-o OUTPUT_FILE] [--contig-by-contig] [--histogram] [-q QUALITY_THRESHOLD] [-v] input_file
+>>>>>>> Stashed changes
+>>>>>>> Stashed changes
 
@@ -420,7 +442,62 @@

Named Arguments +

frag-length-bins#

+

computes frag lengths of fragments and agregates in bins by length. Either writes bins and counts to tsv or prints a histogram

+
finaletoolkit frag-length-bins [-h] [-c CONTIG] [-S START] [-p INTERSECT_POLICY] [-E STOP] [--bin-size BIN_SIZE] [-o OUTPUT_FILE] [--contig-by-contig] [--histogram] [-q QUALITY_THRESHOLD] [-v] input_file
+
+
+
+

Positional Arguments#

+
+
input_file
+

BAM or SAM file containing fragment data

+
+
+
+
+

Named Arguments#

+
+
-c, --contig
+

contig or chromosome to select fragments from. Required if using –start or –stop.

+
+
-S, --start
+

0-based left-most coordinate of interval to select fragmentsfrom. Must also use –contig.

+
+
-p, --intersect_policy
+

Specifies what policy is used to include fragments in the given interval. Default is “midpoint”. Policies include: +- midpoint: the average of end coordinates of a fragment liesin the interval. +- any: any part of the fragment is in the interval.

+======= +

Possible choices: midpoint, any

+

Specifies what policy is used to include fragments in the given interval. See User Guide for more information.

+>>>>>>> Stashed changes +>>>>>>> Stashed changes

Default: “midpoint”

-E, --stop
@@ -454,8 +531,17 @@

Named Arguments

frag-length-intervals#

+<<<<<<< Updated upstream

Retrieves fragment length summary statistics over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

+======= +<<<<<<< Updated upstream +

Calculates frag lengths statistics over user-specified genomic intervals.

+>>>>>>> Stashed changes
finaletoolkit frag-length-intervals [-h] [-p INTERSECT_POLICY] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file interval_file
+=======
+

Retrieves fragment length summary statistics over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

+
finaletoolkit frag-length-intervals [-h] [-p {midpoint,any}] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file interval_file
+>>>>>>> Stashed changes
 
@@ -473,7 +559,18 @@

Positional Arguments#

-p, --intersect_policy
+<<<<<<< Updated upstream

Specifies what policy is used to include fragments in the given interval. See User Guide for more information.

+======= +<<<<<<< Updated upstream +

Specifies what policy is used to include fragments in the given interval. Default is “midpoint”. Policies include: +- midpoint: the average of end coordinates of a fragment liesin the interval. +- any: any part of the fragment is in the interval.

+======= +

Possible choices: midpoint, any

+

Specifies what policy is used to include fragments in the given interval. See User Guide for more information.

+>>>>>>> Stashed changes +>>>>>>> Stashed changes

Default: “midpoint”

-o, --output-file
@@ -495,6 +592,53 @@

Named Arguments +

cleavage-profile#

+

Calculates cleavage proportion over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

+
finaletoolkit cleavage-profile [-h] [-o OUTPUT_FILE] [-lo FRACTION_LOW] [-hi FRACTION_HIGH] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file interval_file
+
+
+
+

Positional Arguments#

+
+
input_file
+

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

+
+
interval_file
+

Path to a BED file containing intervals to calculates cleavage proportion over.

+
+
+
+
+

Named Arguments#

+
+
-o, --output_file
+

A bigWig file containing the cleavage proportion results over the intervals specified in interval file.

+

Default: “-”

+
+
-lo, --fraction_low
+

Minimum length for a fragment to be included in cleavage proportion calculation.

+

Default: 120

+
+
-hi, --fraction_high
+

Maximum length for a fragment to be included in cleavage proportion calculation.

+

Default: 180

+
+
-q, --quality-threshold
+

Minimum mapping quality threshold.

+

Default: 20

+
+
-w, --workers
+

Number of worker processes.

+

Default: 1

+
+
-v, --verbose
+

Enable verbose mode to display detailed processing information.

+

Default: 0

+
+
+
+

wps#

Calculates Windowed Protection Score (WPS) over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

@@ -505,10 +649,24 @@

wps#

Positional Arguments#

input_file
+<<<<<<< Updated upstream

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

site_bed

Path to a BED file containing intervals to calculate WPS over.

+======= +<<<<<<< Updated upstream +

bam or sam file containing paired-end reads of cfDNA WGS

+
+
site_bed
+

bed file containing sites over which to calculate wps

+======= +

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

+
+
site_bed
+

Path to a BED file containing intervals to calculate WPS over.

+>>>>>>> Stashed changes +>>>>>>> Stashed changes
@@ -516,7 +674,12 @@

Positional Arguments#

-o, --output_file
+<<<<<<< Updated upstream

A bigWig file containing the WPS results over the intervals specified in interval file.

+======= +<<<<<<< Updated upstream +

BigWig file to write results to. Default is stdout

+>>>>>>> Stashed changes

Default: “-”

-i, --interval_size
@@ -544,20 +707,69 @@

Named Arguments

delfi#

Calculates DELFI score over genome. NOTE: Due to some ad hoc implementation details, currently the only accepted reference genome is hg19.

finaletoolkit delfi [-h] [-b BLACKLIST_FILE] [-g GAP_FILE] [-o OUTPUT_FILE] [-W WINDOW_SIZE] [-gc] [-m] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file autosomes reference_file bins_file
+=======
+
+

adjust-wps#

+

Adjusts raw Windowed Protection Score (WPS) by applying a median filter and Savitsky-Golay filter.

+
finaletoolkit adjust-wps [-h] [-o OUTPUT_FILE] [-m MEDIAN_WINDOW_SIZE] [-s SAVGOL_WINDOW_SIZE] [-p SAVGOL_POLY_DEG] [-w WORKERS] [--mean] [--subtract-edges] [-v] input_file interval_file genome_file
+>>>>>>> Stashed changes
 
+<<<<<<< Updated upstream

Positional Arguments#

+======= +
+

Positional Arguments#

+<<<<<<< Updated upstream +>>>>>>> Stashed changes
input_file

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

@@ -619,8 +831,15 @@

filter-bam
finaletoolkit filter-bam [-h] [-r REGION_FILE] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-hi FRACTION_HIGH] [-lo FRACTION_LOW] [-w WORKERS] [-v] input_file
 

+<<<<<<< Updated upstream

Positional Arguments#

+======= +
+

Positional Arguments#

+======= +>>>>>>> Stashed changes +>>>>>>> Stashed changes
input_file

Path to BAM file.

@@ -657,10 +876,79 @@

Named Arguments

adjust-wps#

Adjusts raw Windowed Protection Score (WPS) by applying a median filter and Savitsky-Golay filter.

finaletoolkit adjust-wps [-h] [-o OUTPUT_FILE] [-m MEDIAN_WINDOW_SIZE] [-s SAVGOL_WINDOW_SIZE] [-p SAVGOL_POLY_DEG] [-w WORKERS] [--mean] [--subtract-edges] [-v] input_file interval_file genome_file
+=======
+
+

delfi#

+

Calculates DELFI featrues over genome, returning information about (GC-corrected) short fragments, long fragments, DELFI ratio, and total fragments. NOTE: Due to some ad hoc implementation details, currently the only accepted reference genome is hg19.

+
finaletoolkit delfi [-h] [-b BLACKLIST_FILE] [-g GAP_FILE] [-o OUTPUT_FILE] [-W WINDOW_SIZE] [-gc] [-m] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file autosomes reference_file bins_file
+
+
+
+

Positional Arguments#

+
+
input_file
+

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

+
+
autosomes
+

Tab-delimited file containing (1) autosome name and (2) integer length of chromosome in base pairs.

+
+
reference_file
+

The .2bit file for the associate reference genome sequence used during alignment.

+
+
bins_file
+

A BED file containing bins over which to calculate DELFI. To replicate Cristiano et al.’s methodology, use 100kb bins over human autosomes.

+
+
+
+
+

Named Arguments#

+
+
-b, --blacklist_file
+

BED file containing regions to ignore when calculating DELFI.

+
+
-g, --gap_file
+

BED4 format file containing columns for “chrom”, “start”, “stop”, and “type”. The “type” column should denote whether the entry corresponds to a “centromere”, “telomere”, or “short arm”, and entries not falling into these categories are ignored. This information corresponds to the “gap” track for hg19 in the UCSC Genome Browser.

+
+
-o, --output_file
+

BED, bed.gz, TSV, or CSV file to write DELFI data to. If “-”, writes to stdout.

+

Default: “-”

+
+
-W, --window_size
+

Currently unused.

+

Default: 5000000

+
+
-gc, --gc_correct
+

Indicates whether to apply GC correction.

+

Default: False

+
+
-m, --merge_bins
+

Indicates whether to merge bins to 5Mb size.

+

Default: False

+
+
-q, --quality_threshold
+

Minimum mapping quality threshold.

+

Default: 30

+
+
-w, --workers
+

Number of worker processes.

+

Default: 1

+
+
-v, --verbose
+

Enable verbose mode to display detailed processing information.

+

Default: 0

+
+
+
+
+
+

delfi-gc-correct#

+

Performs gc-correction on raw delfi data.

+
finaletoolkit delfi-gc-correct [-h] [-o OUTPUT_FILE] [--header-lines HEADER_LINES] [-v] input_file
 
@@ -724,17 +1012,252 @@

agg-bwPositional Arguments#

input_file
+<<<<<<< Updated upstream

A bigWig file containing signals over the intervals specified in interval file.

+======= +

BED file containing raw DELFI data. Raw DELFI data should only have columns for “contig”, “start”, “stop”, “arm”, “short”, “long”, “gc”, “num_frags”, “ratio”.

+
+
+
+
+

Named Arguments#

+
+
-o, --output-file
+

BED to print GC-corrected DELFI fractions. If “-”, will write to stdout.

+

Default: “-”

+
+
--header-lines
+

Number of header lines in BED.

+

Default: 1

+
+
-v, --verbose
+

Enable verbose mode to display detailed processing information.

+
+
+
+
+
+

end-motifs#

+

Measures frequency of k-mer 5’ end motifs.

+
finaletoolkit end-motifs [-h] [-k K] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file refseq_file
+
+
+
+

Positional Arguments#

+
+
input_file
+

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

+
+
refseq_file
+

The .2bit file for the associate reference genome sequence used during alignment.

+
+
+
+
+

Named Arguments#

+
+
-k
+

Length of k-mer.

+

Default: 4

+
+
-o, --output-file
+

TSV to print k-mer frequencies. If “-”, will write to stdout.

+

Default: “-”

+
+
-q, --quality-threshold
+

Minimum mapping quality threshold.

+

Default: 20

+
+
-w, --workers
+

Number of worker processes.

+

Default: 1

+
+
-v, --verbose
+

Enable verbose mode to display detailed processing information.

+

Default: 0

+
+
+
+
+
+

interval-end-motifs#

+

Measures frequency of k-mer 5’ end motifs in each region specified in a BED file and writes data into a table.

+
finaletoolkit interval-end-motifs [-h] [-k K] [-lo FRACTION_LOW] [-hi FRACTION_HIGH] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file refseq_file intervals
+
+
+
+

Positional Arguments#

+
+
input_file
+

Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

+
+
refseq_file
+

The .2bit file for the associate reference genome sequence used during alignment.

+
+
intervals
+

Path to a BED file containing intervals to retrieve end motif frequencies over.

+
+
+
+
+

Named Arguments#

+
+
-k
+

Length of k-mer.

+

Default: 4

+
+
-lo, --fraction-low
+

Minimum length for a fragment to be included in end motif frequency.

+

Default: 10

+
+
-hi, --fraction-high
+

Maximum length for a fragment to be included in end motif frequency.

+

Default: 600

+
+
-o, --output-file
+

Path to TSV or CSV file to write end motif frequencies to.

+

Default: “-”

+
+
-q, --quality-threshold
+

Minimum mapping quality threshold.

+

Default: 20

+
+
-w, --workers
+

Number of worker processes.

+

Default: 1

+
+
-v, --verbose
+

Enable verbose mode to display detailed processing information.

+

Default: 0

+
+
+
+
+
+

mds#

+

Reads k-mer frequencies from a file and calculates a motif diversity score (MDS) using normalized Shannon entropy as described by Jiang et al (2020).

+
finaletoolkit mds [-h] [-s SEP] [--header HEADER] [file_path]
+
+
+
+

Positional Arguments#

+
+
file_path
+

Tab-delimited or similar file containing one column for all k-mers a one column for frequency. Reads from stdin by default.

+

Default: “-”

+
+
+
+
+

Named Arguments#

+
+
-s, --sep
+

Separator used in tabular file.

+

Default: “ “

+
+
--header
+

Number of header rows to ignore. Default is 0

+

Default: 0

+
+
+
+
+
+

interval-mds#

+

Reads k-mer frequencies from a file and calculates a motif diversity score (MDS) for each interval using normalized Shannon entropy as described by Jiang et al (2020).

+
finaletoolkit interval-mds [-h] [-s SEP] [file_path] file_out
+
+
+
+

Positional Arguments#

+
+
file_path
+

Tab-delimited or similar file containing one column for all k-mers a one column for frequency. Reads from stdin by default.

+

Default: “-”

+
+
file_out
+

Path to the output BED/BEDGraph file containing MDS for each interval.

+

Default: “-”

+
+
+
+
+

Named Arguments#

+
+
-s, --sep
+

Separator used in tabular file.

+

Default: “ “

+
+
+
+
+
+

filter-bam#

+

Filters a BAM file so that all reads are in mapped pairs, exceed a certain MAPQ, are not flagged for quality, are read1, are not secondary or supplementary alignments, and are on the same reference sequence as the mate.

+
finaletoolkit filter-bam [-h] [-r REGION_FILE] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-hi FRACTION_HIGH] [-lo FRACTION_LOW] [-w WORKERS] [-v] input_file
+
+
+
+

Positional Arguments#

+
+
input_file
+

Path to BAM file.

+
+
+
+
+

Named Arguments#

+
+
-r, --region-file
+

Only output alignments overlapping the intervals in this BED file will be included.

+
+
-o, --output-file
+

Output BAM file path.

+

Default: “-”

+
+
-q, --quality_threshold
+

Minimum mapping quality threshold.

+

Default: 30

+
+
-hi, --fraction-high
+

Maximum length for a fragment to be included in output BAM.

+
+
-lo, --fraction-low
+

Minimum length for a fragment to be included in output BAM.

+
+
-w, --workers
+

Number of worker processes.

+

Default: 1

+
+
-v, --verbose
+

Enable verbose mode to display detailed processing information.

+
+
+
+
+
+

agg-bw#

+

Aggregates a bigWig signal over constant-length intervals defined in a BED file.

+
finaletoolkit agg-bw [-h] [-o OUTPUT_FILE] [-m MEDIAN_WINDOW_SIZE] [-v] input_file interval_file
+>>>>>>> Stashed changes
+
+
+
+

Positional Arguments#

+
+
input_file
+

BigWig file with WPS data.

+>>>>>>> Stashed changes
interval_file

Path to a BED file containing intervals over which signals were calculated over.

-
-

Named Arguments#

+
+

Named Arguments#

-o, --output-file

A wiggle file containing the aggregate signal over the intervals specified in interval file.

@@ -750,6 +1273,7 @@

Named Arguments

delfi-gc-correct#

Performs gc-correction on raw delfi data.

@@ -935,6 +1459,8 @@

Named Arguments

+======= +>>>>>>> Stashed changes

gap-bed#

Creates a BED4 file containing centromeres, telomeres, and short-arm intervals, similar to the gaps annotation track for hg19 found on the UCSC Genome Browser (Kent et al 2002). Currently only supports hg19, b37, human_g1k_v37, hg38, and GRCh38

@@ -949,12 +1475,13 @@

Positional Arguments

cleavage-profile#

wip

@@ -1000,6 +1527,8 @@

Named Arguments

+======= +>>>>>>> Stashed changes

@@ -1065,7 +1594,15 @@

Named ArgumentsNamed Arguments +<<<<<<< Updated upstream
  • wps
  • +
    Returns:
    +

      +
    • bins (ndarray)

    • +
    • counts (ndarray)

    • +
    +

    +
    +

    @@ -562,7 +561,7 @@

    Returns# diff --git a/docs/_build/html/_documentation/api_reference/cleavageprofile.html b/docs/_build/html/_documentation/api_reference/cleavageprofile.html index dbca4936..ea79403a 100644 --- a/docs/_build/html/_documentation/api_reference/cleavageprofile.html +++ b/docs/_build/html/_documentation/api_reference/cleavageprofile.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -357,11 +356,36 @@
    -

    Cleavage Profile#

    +

    Cleavage Profile#

    -finaletoolkit.frag.cleavage_profile(input_file: str, contig: str, start: int, stop: int, fraction_low: int = 1, fraction_high: int = 10000000, quality_threshold: int = 30, verbose: bool | int = 0) ndarray#
    -
    +finaletoolkit.frag.cleavage_profile(input_file: str, chrom_size: int, contig: str, start: int, stop: int, left: int = 0, right: int = 0, fraction_low: int = 1, fraction_high: int = 10000000, quality_threshold: int = 30, verbose: bool | int = 0) ndarray# +

    Cleavage profile calculated over a single interval.

    +
    +
    Parameters:
    +
      +
    • input_file (str) – SAM, BAM, CRAM, or FRAG file with fragment information.

    • +
    • chrom_size (int) – length of contig.

    • +
    • contig (str) – Chromosome or contig

    • +
    • start (int) – 0-based start coordinate

    • +
    • stop (int) – 1-based end coordinate

    • +
    • left (int) – Amount to subtract from start coordinate. Useful if only given +coordinates of CpG.

    • +
    • right (int) – Amount to add to stop coordinate.

    • +
    • fraction_low (int) – Minimum fragment size to include

    • +
    • fraction_high (int) – Maximum fragment size to include

    • +
    • quality_threshold (int) – Minimum MAPQ

    • +
    • verbose (bool or in)

    • +
    +
    +
    Returns:
    +

    cleavage_proportions – Array of cleavage proportions over given interval.

    +
    +
    Return type:
    +

    NDArray

    +
    +
    +

    @@ -458,7 +482,7 @@

    Cleavage Profile

    - Created using Sphinx 6.2.1. + Created using Sphinx 7.3.7.

    diff --git a/docs/_build/html/_documentation/api_reference/delfi.html b/docs/_build/html/_documentation/api_reference/delfi.html index 87f67f40..75ce6ce0 100644 --- a/docs/_build/html/_documentation/api_reference/delfi.html +++ b/docs/_build/html/_documentation/api_reference/delfi.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -357,60 +356,49 @@
    -

    DELFI#

    +

    DELFI#

    -finaletoolkit.frag.delfi(input_file: str, autosomes: str, bins_file: str, reference_file: str, blacklist_file: str = None, gap_file: Union(str, GenomeGaps) = None, output_file: str = None, gc_correct: bool = True, merge_bins: bool = True, window_size: int = 5000000, subsample_coverage: float = 2, quality_threshold: int = 30, workers: int = 1, preprocessing: bool = True, verbose: int | bool = False) pandas.DataFrame#
    +finaletoolkit.frag.delfi(input_file: str, autosomes: str, bins_file: str, reference_file: str, blacklist_file: str = None, gap_file: Union(str, GenomeGaps) = None, output_file: str = None, gc_correct: bool = True, merge_bins: bool = True, window_size: int = 5000000, subsample_coverage: float = 2, quality_threshold: int = 30, workers: int = 1, preprocessing: bool = True, verbose: int | bool = False) pandas.DataFrame#

    A function that replicates the methodology of Christiano et al (2019).

    -
    -

    Parameters#

    -
    -
    input_file: str

    Path string pointing to a bam file containing PE -fragment reads.

    -
    -
    autosomes: str

    Path string to a .genome file containing only autosomal -chromosomes

    -
    -
    bins_file: str

    Path string to a BED file containing 100kb bins for reference -genome of choice. Cristiano et al uses

    -
    -
    reference_file: str

    Path string to .2bit file.

    -
    -
    blacklist_file: str

    Path string to BED file containing genome blacklist.

    -
    -
    gap_file: str

    Path string to a BED4+ file where each interval is a centromere +

    +
    Parameters:
    +
      +
    • input_file (str) – Path string pointing to a bam file containing PE +fragment reads.

    • +
    • autosomes (str) – Path string to a .genome file containing only autosomal +chromosomes

    • +
    • bins_file (str) – Path string to a BED file containing 100kb bins for reference +genome of choice. Cristiano et al uses

    • +
    • reference_file (str) – Path string to .2bit file.

    • +
    • blacklist_file (str) – Path string to BED file containing genome blacklist.

    • +
    • gap_file (str) – Path string to a BED4+ file where each interval is a centromere or telomere. A bed file can be used only if the fourth field for each entry corresponding to a telomere or centromere is -labled “telomere” or “centromere, respectively.

      -
    -
    output_file: str, optional

    Path to output tsv.

    -
    -
    window_size: int

    Size of non-overlapping windows to cover genome. Default is -5 megabases.

    -
    -
    subsample_coverage: int, optional

    The depth at which to subsample the input_bam. Default is 2.

    -
    -
    workers: int, optional

    Number of worker processes to use. Default is 1.

    -
    -
    preprocessing: bool, optional

    Christiano et al (2019)

    -
    -
    verbose: int or bool, optional

    Determines how many print statements and loading bars appear in -stdout. Default is False.

    +labled “telomere” or “centromere, respectively.

    +
  • output_file (str, optional) – Path to output tsv.

  • +
  • window_size (int) – Size of non-overlapping windows to cover genome. Default is +5 megabases.

  • +
  • subsample_coverage (int, optional) – The depth at which to subsample the input_bam. Default is 2.

  • +
  • workers (int, optional) – Number of worker processes to use. Default is 1.

  • +
  • preprocessing (bool, optional) – Christiano et al (2019)

  • +
  • verbose (int or bool, optional) – Determines how many print statements and loading bars appear in +stdout. Default is False.

  • +
    -
    -finaletoolkit.frag.delfi_gc_correct(windows: DataFrame, alpha: float = 0.75, it: int = 8, verbose: bool = False)#
    +finaletoolkit.frag.delfi_gc_correct(windows: DataFrame, alpha: float = 0.75, it: int = 8, verbose: bool = False)#

    Helper function that takes window data and performs GC adjustment.

    -finaletoolkit.frag.delfi_merge_bins(hundred_kb_bins: DataFrame, gc_corrected: bool = True, add_chr: bool = False, verbose: bool = False)#
    +finaletoolkit.frag.delfi_merge_bins(hundred_kb_bins: DataFrame, gc_corrected: bool = True, add_chr: bool = False, verbose: bool = False)#
    @@ -510,7 +498,7 @@

    Parameters

    - Created using Sphinx 6.2.1. + Created using Sphinx 7.3.7.

    diff --git a/docs/_build/html/_documentation/api_reference/endmotifs.html b/docs/_build/html/_documentation/api_reference/endmotifs.html index 739b9ddc..3adf1e8e 100644 --- a/docs/_build/html/_documentation/api_reference/endmotifs.html +++ b/docs/_build/html/_documentation/api_reference/endmotifs.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -357,47 +356,46 @@
    -

    End-Motifs#

    +

    End-Motifs#

    -class finaletoolkit.frag.EndMotifFreqs(kmer_frequencies: Iterable[tuple[str, float]], k: int, quality_threshold: int = 20)#
    +class finaletoolkit.frag.EndMotifFreqs(kmer_frequencies: Iterable[tuple[str, float]], k: int, quality_threshold: int = 20)#

    Class that stores frequencies of end-motif k-mer frequencies and contains methods to manipulate this data.

    -
    -

    Parameters#

    -
    -
    kmer_frequenciesIterable

    A Iterable of tuples, each containing a str representing a k-mer -and a float representing its frequency

    -
    -
    kint

    Size of k-mers

    -
    -
    quality_threshold: int, optional

    Minimum mapping quality used. Default is 30.

    +
    +
    Parameters:
    +
      +
    • kmer_frequencies (Iterable) – A Iterable of tuples, each containing a str representing a k-mer +and a float representing its frequency

    • +
    • k (int) – Size of k-mers

    • +
    • quality_threshold (int, optional) – Minimum mapping quality used. Default is 30.

    • +
    -classmethod from_file(file_path: str | Path, quality_threshold: int, sep: str = '\t', header: int = 0) EndMotifFreqs#
    +classmethod from_file(file_path: str | Path, quality_threshold: int, sep: str = '\t', header: int = 0) EndMotifFreqs#

    Reads kmer frequency from a two-column tab-delimited file.

    -
    -

    Parameters#

    -
    -
    file_pathstr

    Path string containing path to file.

    +
    +
    Parameters:
    +
      +
    • file_path (str) – Path string containing path to file.

    • +
    • sep (str, optional) – Delimiter used in file.

    • +
    • header (int, optional) – Number of lines to ignore at the head of the file.

    • +
    -
    sepstr, optional

    Delimiter used in file.

    +
    Returns:
    +

    kmer_freqs

    -
    headerint, optional

    Number of lines to ignore at the head of the file.

    +
    Return type:
    +

    EndMotifFreqs

    -
    -
    -

    Return#

    -

    kmer_freqs : EndMotifFreqs

    -
    -motif_diversity_score() float#
    +motif_diversity_score() float#

    Calculates a motif diversity score (MDS) using normalized Shannon entropy as described by Jiang et al (2020). This function is generalized for any k instead of just 4-mers.

    @@ -405,34 +403,32 @@

    Return
    -to_tsv(output_file: str | Path, sep: str = '\t')#
    +to_tsv(output_file: str | Path, sep: str = '\t')#

    Prints k-mer frequencies to a tsv

    -
    -class finaletoolkit.frag.EndMotifsIntervals(intervals: Iterable[tuple[tuple, dict]], k: int, quality_threshold: int = 20)#
    +class finaletoolkit.frag.EndMotifsIntervals(intervals: Iterable[tuple[tuple, dict]], k: int, quality_threshold: int = 20)#

    Class that stores frequencies of end-motif k-mers over user-specified intervals and contains methods to manipulate this data.

    -
    -

    Parameters#

    -
    -
    intervalsIterable

    A collection of tuples, each containing a tuple representing +

    +
    Parameters:
    +
      +
    • intervals (Iterable) – A collection of tuples, each containing a tuple representing a genomic interval (chrom, 0-based start, 1-based stop) and a -dict that maps kmers to frequencies in the interval.

      -
    -
    kint

    Size of k-mers

    -
    -
    quality_threshold: int, optional

    Minimum mapping quality used. Default is 30.

    +dict that maps kmers to frequencies in the interval.

    +
  • k (int) – Size of k-mers

  • +
  • quality_threshold (int, optional) – Minimum mapping quality used. Default is 30.

  • +
    -freq(kmer: str) list[Tuple[str, int, int, float]]#
    +freq(kmer: str) list[tuple[str, int, int, float]]#

    Returns a list of intervals and associated frquency for given kmer. Results are in the form (chrom, 0-based start, 1-based stop, frequency).

    @@ -440,37 +436,37 @@

    Parameters
    -classmethod from_file(file_path: str, quality_threshold: int, sep: str = ',') EndMotifFreqs#
    +classmethod from_file(file_path: str, quality_threshold: int, sep: str = ',') EndMotifFreqs#

    Reads kmer frequency from a tab-delimited file. Expected columns -are contig, start, stop, name, count, *kmers. Because +are contig, start, stop, name, count, *kmers. Because exporting to file includes an option to turn counts to a fraction, this doesn’t perfectly correspond to replicating the other file.

    -
    -

    Parameters#

    -
    -
    file_pathstr

    Path string containing path to file.

    +
    +
    Parameters:
    +
      +
    • file_path (str) – Path string containing path to file.

    • +
    • quality_threshold (int) – MAPQ filter used. Only used for some calculations.

    • +
    • sep (str, optional) – Delimiter used in file.

    • +
    -
    quality_thresholdint

    MAPQ filter used. Only used for some calculations.

    +
    Returns:
    +

    kmer_freqs

    -
    sepstr, optional

    Delimiter used in file.

    +
    Return type:
    +

    EndMotifFreqs

    -
    -
    -

    Return#

    -

    kmer_freqs : EndMotifFreqs

    -

    -mds_bed(output_file: str | Path, sep: str = '\t')#
    +mds_bed(output_file: str | Path, sep: str = '\t')#

    Writes MDS for each interval to a bed/bedgraph file.

    -motif_diversity_score() list[tuple[tuple, float]]#
    +motif_diversity_score() list[tuple[tuple, float]]#

    Calculates a motif diversity score (MDS) for each interval using normalized Shannon entropy as described by Jiang et al (2020). This function is generalized for any k instead of just 4-mers.

    @@ -478,165 +474,145 @@

    Return#<
    -to_bed(kmer: str, output_file: str | Path, calc_freq: bool = True, sep: str = '\t')#
    +to_bed(kmer: str, output_file: str | Path, calc_freq: bool = True, sep: str = '\t')#

    Take frequency of specified kmer and writes to BED.

    -
    -

    Parameters#

    -
    -
    output_file: str

    File to write frequencies to.

    -
    -
    calc_freq: bool, optional

    Calculates frequency of motifs if true. Otherwise, writes counts -for each motif. Default is true.

    -
    -
    sep: str, optional

    Separator for table. Tab-separated by default.

    +
    +
    Parameters:
    +
      +
    • output_file (str) – File to write frequencies to.

    • +
    • calc_freq (bool, optional) – Calculates frequency of motifs if true. Otherwise, writes counts +for each motif. Default is true.

    • +
    • sep (str, optional) – Separator for table. Tab-separated by default.

    • +
    -
    -to_bedgraph(kmer: str, output_file: str | Path, calc_freq: bool = True, sep: str = '\t')#
    +to_bedgraph(kmer: str, output_file: str | Path, calc_freq: bool = True, sep: str = '\t')#

    Take frequency of specified kmer and writes to bedgraph.

    -
    -

    Parameters#

    -
    -
    output_file: str

    File to write frequencies to.

    -
    -
    calc_freq: bool, optional

    Calculates frequency of motifs if true. Otherwise, writes counts -for each motif. Default is true.

    -
    -
    sep: str, optional

    Separator for table. Tab-separated by default.

    +
    +
    Parameters:
    +
      +
    • output_file (str) – File to write frequencies to.

    • +
    • calc_freq (bool, optional) – Calculates frequency of motifs if true. Otherwise, writes counts +for each motif. Default is true.

    • +
    • sep (str, optional) – Separator for table. Tab-separated by default.

    • +
    -
    -to_tsv(output_file: str | Path, calc_freq: bool = True, sep: str = '\t')#
    +to_tsv(output_file: str | Path, calc_freq: bool = True, sep: str = '\t')#

    Writes all intervals and associated frquencies to file. Columns -are contig, start, stop, name, count, *kmers.

    -
    -

    Parameters#

    -
    -
    output_file: str

    File to write frequencies to.

    -
    -
    calc_freq: bool, optional

    Calculates frequency of motifs if true. Otherwise, writes counts -for each motif. Default is true.

    -
    -
    sep: str, optional

    Separator for table. Tab-separated by default.

    +are contig, start, stop, name, count, *kmers.

    +
    +
    Parameters:
    +
      +
    • output_file (str) – File to write frequencies to.

    • +
    • calc_freq (bool, optional) – Calculates frequency of motifs if true. Otherwise, writes counts +for each motif. Default is true.

    • +
    • sep (str, optional) – Separator for table. Tab-separated by default.

    • +
    -
    -

    -finaletoolkit.frag.region_end_motifs(input_file: str, contig: str, start: int, stop: int, refseq_file: str | Path, k: int = 4, fraction_low: int = 10, fraction_high: int = 600, both_strands: bool = True, output_file: None | str = None, quality_threshold: int = 20, verbose: bool | int = False) dict#
    +finaletoolkit.frag.region_end_motifs(input_file: str, contig: str, start: int, stop: int, refseq_file: str | Path, k: int = 4, fraction_low: int = 10, fraction_high: int = 600, both_strands: bool = True, output_file: None | str = None, quality_threshold: int = 20, verbose: bool | int = False) dict#

    Function that reads fragments in the specified region from a BAM, SAM, or tabix indexed file and returns the 5’ k-mer (default is 4-mer) end motif counts as a dictionary. This function reproduces the methodology of Zhou et al (2023).

    -
    -

    Parameters#

    -
    -
    input_filestr

    Path of SAM, BAM, CRAM, or Frag.gz containing pair-end reads.

    -
    -
    contigstr

    Name of contig or chromosome for region.

    -
    -
    startint

    0-based start coordinate.

    -
    -
    stopint

    1-based end coordinate.

    -
    -
    refseq_filestr or Path

    2bit file with reference sequence input_file was aligned to.

    -
    -
    kint, optional

    Length of end motif kmer. Default is 4.

    -
    -
    fraction_low: int, optional

    Minimum fragment length.

    +
    +
    Parameters:
    +
      +
    • input_file (str) – Path of SAM, BAM, CRAM, or Frag.gz containing pair-end reads.

    • +
    • contig (str) – Name of contig or chromosome for region.

    • +
    • start (int) – 0-based start coordinate.

    • +
    • stop (int) – 1-based end coordinate.

    • +
    • refseq_file (str or Path) – 2bit file with reference sequence input_file was aligned to.

    • +
    • k (int, optional) – Length of end motif kmer. Default is 4.

    • +
    • fraction_low (int, optional) – Minimum fragment length.

    • +
    • fraction_high (int, optional) – Maximum fragment length.

    • +
    • both_strands (bool, optional) – Choose whether to use forward 5’ ends only or use 5’ ends for +both ends of PE reads.

    • +
    • output_file (None or str, optional)

    • +
    • quality_threshold (int, optional)

    • +
    • verbose (bool or int, optional)

    • +
    -
    fraction_high: int, optional

    Maximum fragment length.

    +
    Returns:
    +

    end_motif_freq

    -
    both_strands: bool, optional

    Choose whether to use forward 5’ ends only or use 5’ ends for -both ends of PE reads.

    +
    Return type:
    +

    dict

    -

    output_file : None or str, optional -quality_threshold : int, optional -verbose : bool or int, optional

    -
    -
    -

    Return#

    -

    end_motif_freq : dict

    -
    -finaletoolkit.frag.end_motifs(input_file: str, refseq_file: str | Path, k: int = 4, fraction_low: int = 10, fraction_high: int = 600, both_strands: bool = False, output_file: None | str = None, quality_threshold: int = 30, workers: int = 1, verbose: bool | int = False) EndMotifFreqs#
    +finaletoolkit.frag.end_motifs(input_file: str, refseq_file: str | Path, k: int = 4, fraction_low: int = 10, fraction_high: int = 600, both_strands: bool = False, output_file: None | str = None, quality_threshold: int = 30, workers: int = 1, verbose: bool | int = False) EndMotifFreqs#

    Function that reads fragments from a BAM, SAM, or tabix indexed file and returns the 5’ k-mer (default is 4-mer) end motif frequencies as a dictionary. Optionally writes data to a tsv. This function reproduces the methodology of Zhou et al (2023).

    -
    -

    Parameters#

    -
    -
    input_filestr

    SAM, BAM, CRAM, or Frag.gz file with paired-end reads.

    -
    -
    refseq_filestr or Path

    2bit file with sequence of reference genome input_file is -aligned to.

    -
    -
    kint, optional

    Length of end motif kmer. Default is 4.

    -
    -
    output_fileNone or str, optional

    File path to write results to. Either tsv or csv.

    +
    +
    Parameters:
    +
      +
    • input_file (str) – SAM, BAM, CRAM, or Frag.gz file with paired-end reads.

    • +
    • refseq_file (str or Path) – 2bit file with sequence of reference genome input_file is +aligned to.

    • +
    • k (int, optional) – Length of end motif kmer. Default is 4.

    • +
    • output_file (None or str, optional) – File path to write results to. Either tsv or csv.

    • +
    • quality_threshold (int, optional) – Minimum MAPQ to filter.

    • +
    • workers (int, optional) – Number of worker processes.

    • +
    • verbose (bool or int, optional)

    • +
    -
    quality_thresholdint, optional

    Minimum MAPQ to filter.

    +
    Returns:
    +

    end_motif_freq

    -
    workersint, optional

    Number of worker processes.

    +
    Return type:
    +

    EndMotifFreqs

    -

    verbose : bool or int, optional

    -
    -
    -

    Return#

    -

    end_motif_freq : EndMotifFreqs

    -
    -finaletoolkit.frag.interval_end_motifs(input_file: str, refseq_file: str | Path, intervals: str | Iterable[Tuple[str, int, int, str]], k: int = 4, fraction_low: int = 10, fraction_high: int = 600, both_strands: bool = True, output_file: None | str = None, quality_threshold: int = 30, workers: int = 1, verbose: bool | int = False) EndMotifsIntervals#
    +finaletoolkit.frag.interval_end_motifs(input_file: str, refseq_file: str | Path, intervals: str | Iterable[tuple[str, int, int, str]], k: int = 4, fraction_low: int = 10, fraction_high: int = 600, both_strands: bool = True, output_file: None | str = None, quality_threshold: int = 30, workers: int = 1, verbose: bool | int = False) EndMotifsIntervals#

    Function that reads fragments from a BAM, SAM, or tabix indexed file and user-specified intervals and returns the 5’ k-mer (default is 4-mer) end motif. Optionally writes data to a tsv.

    -
    -

    Parameters#

    -
    -
    input_filestr

    Path of SAM, BAM, CRAM, or Frag.gz containing pair-end reads.

    -
    -
    refseq_filestr or Path

    Path of 2bit file for reference genome that reads are aligned to.

    -
    -
    intervalsstr or tuple

    Path of BED file containing intervals or list of tuples -(chrom, start, stop, name).

    -
    -
    kint, optional

    Length of end motif kmer. Default is 4.

    -
    -
    output_fileNone or str, optional

    File path to write results to. Either tsv or csv.

    +
    +
    Parameters:
    +
      +
    • input_file (str) – Path of SAM, BAM, CRAM, or Frag.gz containing pair-end reads.

    • +
    • refseq_file (str or Path) – Path of 2bit file for reference genome that reads are aligned to.

    • +
    • intervals (str or tuple) – Path of BED file containing intervals or list of tuples +(chrom, start, stop, name).

    • +
    • k (int, optional) – Length of end motif kmer. Default is 4.

    • +
    • output_file (None or str, optional) – File path to write results to. Either tsv or csv.

    • +
    • quality_threshold (int, optional) – Minimum MAPQ to filter.

    • +
    • workers (int, optional) – Number of worker processes.

    • +
    • verbose (bool or int, optional)

    • +
    -
    quality_thresholdint, optional

    Minimum MAPQ to filter.

    +
    Returns:
    +

    end_motif_freq

    -
    workersint, optional

    Number of worker processes.

    +
    Return type:
    +

    EndMotifIntervals

    -

    verbose : bool or int, optional

    -
    -
    -

    Return#

    -

    end_motif_freq : EndMotifIntervals

    -
    @@ -752,7 +728,7 @@

    Return# diff --git a/docs/_build/html/_documentation/api_reference/fragfile.html b/docs/_build/html/_documentation/api_reference/fragfile.html index 0f2242ae..100c4cc8 100644 --- a/docs/_build/html/_documentation/api_reference/fragfile.html +++ b/docs/_build/html/_documentation/api_reference/fragfile.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -357,58 +356,40 @@
    -

    Frag File Utilities#

    +

    Frag File Utilities#

    -finaletoolkit.utils.filter_bam(input_file: str, region_file: str = None, output_file: str = None, max_length: int = None, min_length: int = None, quality_threshold: int = 30, workers: int = 1, verbose: bool = False)#
    +finaletoolkit.utils.filter_bam(input_file: str, region_file: str | None = None, output_file: str | None = None, max_length: int | None = None, min_length: int | None = None, quality_threshold: int = 30, workers: int = 1, verbose: bool = False)#

    Accepts the path to a BAM file and creates a bam file where all reads are read1 in a proper pair, exceed the specified quality threshold, do not intersect a region in the given blacklist file, and intersects with a region in the region bed.

    -
    -

    Parameters#

    -
    -
    input_bamstr

    Path string or AlignmentFile pointing to the BAM file to be -filtered.

    +
    +
    Parameters:
    +
      +
    • input_bam (str) – Path string or AlignmentFile pointing to the BAM file to be +filtered.

    • +
    • region_file (str, option)

    • +
    • output_file (str, optional)

    • +
    • min_length (int, optional)

    • +
    • max_length (int, optional)

    • +
    • quality_threshold (int, optional)

    • +
    • workers (int, optional)

    • +
    • verbose (bool, optional)

    • +
    -
    -

    region_file : str, option -output_file : str, optional -min_length : int, optional -max_length : int, optional -quality_threshold : int, optional -workers : int, optional -verbose : bool, optional

    -
    -
    -

    Returns#

    -

    output_file : str

    -
    -
    - -
    -
    -finaletoolkit.utils.genome2list(genome_file: str) list#
    -

    Reads a GENOME text file into a list of tuples (chrom, length)

    -
    -

    Parameters#

    -
    -
    genome_filestr

    String containing path to GENOME format file

    +
    Returns:
    +

    output_file

    -
    -
    -

    Returns#

    -
    -
    chromsstr

    List of tuples containing chrom/contig names and lengths

    +
    Return type:
    +

    str

    -
    -
    -finaletoolkit.utils.agg_bw(input_file: str, interval_file: str, output_file: str, median_window_size: int = 0, mean: bool = False, strand_location: int = 5, verbose: bool = False)#
    +finaletoolkit.utils.agg_bw(input_file: str, interval_file: str, output_file: str, median_window_size: int = 0, mean: bool = False, strand_location: int = 5, verbose: bool = False)#

    Takes a BigWig and an interval BED and aggregates signal along the intervals.

    For aggregating WPS signals, note that the median filter trims the @@ -424,29 +405,170 @@

    Returns# was used, supply the 5kb bed file and median filter window size to this function.

    Do not do both of these at once.

    -
    -

    Parameters#

    -

    input_file : str -interval_file : str -output_file : str -median_window_size : int, optional

    -
    -

    default is 0

    -
    -
    -
    meanbool

    use mean instead

    +
    +
    Parameters:
    +
      +
    • input_file (str)

    • +
    • interval_file (str)

    • +
    • output_file (str)

    • +
    • median_window_size (int, optional) – default is 0

    • +
    • mean (bool) – use mean instead

    • +
    • strand_location (int) – which column (starting at 0) of the interval file contains the +strand. Default is 5.

    • +
    • verbose (int or bool, optional) – default is False

    • +
    -
    strand_locationint

    which column (starting at 0) of the interval file contains the -strand. Default is 5.

    +
    Returns:
    +

    agg_scores

    -
    verboseint or bool, optional

    default is False

    +
    Return type:
    +

    NDArray

    -
    -
    -

    Return#

    -

    agg_scores : NDArray

    -
    +

    + +
    +
    +finaletoolkit.utils.chrom_sizes_to_list(chrom_sizes_file: str | Path) list[tuple[str][int]]#
    +

    Reads chromosome names and sizes from a CHROMSIZE file into a list.

    +
    +
    Parameters:
    +

    chrom_sizes_file (str or Path) – Tab-delimited file with column for chrom names and column for +chrom sizes.

    +
    +
    Returns:
    +

    chrom names and sizes.

    +
    +
    Return type:
    +

    list of string, int tuples

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.chrom_sizes_to_dict(chrom_sizes_file: str | Path) list[tuple[str][int]]#
    +

    Reads chromosome names and sizes from a CHROMSIZE file into a dict.

    +
    +
    Parameters:
    +

    chrom_sizes_file (str or Path) – Tab-delimited file with column for chrom names and column for +chrom sizes.

    +
    +
    Returns:
    +

    Chrom names are keys and values are int chrom sizes.

    +
    +
    Return type:
    +

    dict

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.frag_generator(input_file: str | pysam.AlignmentFile | pysam.TabixFile | Path, contig: str, quality_threshold: int = 30, start: int = None, stop: int = None, fraction_low: int = 120, fraction_high: int = 180, intersect_policy: str = 'midpoint', verbose: bool = False) Generator[tuple]#
    +

    Reads from BAM, SAM, or BED file and returns tuples containing +contig (chromosome), start, stop (end), mapq, and strand for each fragment. +Optionally may filter for mapq, size, and intersection with a region.

    +
    +
    Parameters:
    +
      +
    • input_file (str or AlignmentFile)

    • +
    • contig (str)

    • +
    • quality_threshold (int, optional)

    • +
    • start (int, optional)

    • +
    • stop (int, optional)

    • +
    • fraction_low (int, optional) – Specifies lowest fragment length included in array. Default is +120, equivalent to long fraction.

    • +
    • fraction_high (int, optional) – Specifies highest fragment length included in array. Default is +120, equivalent to long fraction.

    • +
    • intersect_policy (str, optional) – Specifies what policy is used to include fragments in the +given interval. Default is “midpoint”. Policies include: +- midpoint: the average of end coordinates of a fragment lies +in the interval. +- any: any part of the fragment is in the interval.

    • +
    • verbose (bool, optional)

    • +
    +
    +
    Returns:
    +

    frag_ends – Generator that yields tuples containing the region covered by +each fragment in input_file.

    +
    +
    Return type:
    +

    Generator

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.frag_array(input_file: str | AlignmentFile | TabixFile | Path, contig: str, quality_threshold: int = 30, start: int | None = None, stop: int | None = None, fraction_low: int = 120, fraction_high: int = 180, intersect_policy: str = 'midpoint', verbose: bool = False) ndarray[Any, dtype[_ScalarType_co]]#
    +

    Reads from BAM, SAM, or BED file and returns a three column matrix +with fragment start and stop positions and strand.

    +
    +
    Parameters:
    +
      +
    • input_file (str or AlignmentFile)

    • +
    • contig (str)

    • +
    • quality_threshold (int, optional)

    • +
    • start (int, optional)

    • +
    • stop (int, optional)

    • +
    • fraction_low (int, optional) – Specifies lowest fragment length included in array. Default is +120, equivalent to long fraction.

    • +
    • fraction_high (int, optional) – Specifies highest fragment length included in array. Default is +120, equivalent to long fraction. +intersect_policy : str, optional +Specifies what policy is used to include fragments in the +given interval. Default is “midpoint”. Policies include: +- midpoint: the average of end coordinates of a fragment lies +in the interval. +- any: any part of the fragment is in the interval.

    • +
    • verbose (bool, optional)

    • +
    +
    +
    Returns:
    +

    frag_ends – ‘NDArray’ with shape (n, 3) where column 1 contains fragment +start position and column 2 contains fragment stop position, and +column3 is 1 of on the + strand and is 0 if on the - strand. +If no fragments exist in the specified minimum-maximum interval, +the returned ‘ndarray’ will have a shape of (0, 3)

    +
    +
    Return type:
    +

    NDArray

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.low_quality_read_pairs(read, min_mapq=30)#
    +

    Return True if the sequenced read described in read is not a +properly paired read with a Phred score exceeding min_mapq. Based +on epifluidlab/cofragr +mmary_in_intervals.py

    +

    Equivalent to -F 3852 -f 3

    +
    +
    Parameters:
    +
      +
    • read (pysam.AlignedSegment) – Sequenced read to check for quality, perfect pairing and if it +is mapped.

    • +
    • min_mapq (int, optional) – Minimum Phred score for map quality of read. Defaults to 30.

    • +
    +
    +
    Returns:
    +

    is_low_quality – True if read is low quality, unmapped, not properly paired.

    +
    +
    Return type:
    +

    bool

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.overlaps(contigs_1: ndarray[Any, dtype[_ScalarType_co]], starts_1: ndarray[Any, dtype[_ScalarType_co]], stops_1: ndarray[Any, dtype[_ScalarType_co]], contigs_2: ndarray[Any, dtype[_ScalarType_co]], starts_2: ndarray[Any, dtype[_ScalarType_co]], stops_2: ndarray[Any, dtype[_ScalarType_co]]) ndarray[Any, dtype[_ScalarType_co]]#
    +

    Function that performs vectorized computation of overlaps. Returns +an array of same shape as contig_1 that is true if the intervals +for set 1 each have any overlap with an interval in set 2.

    @@ -498,8 +620,13 @@

    Return @@ -546,7 +673,7 @@

    Return

    - Created using Sphinx 6.2.1. + Created using Sphinx 7.3.7.

    diff --git a/docs/_build/html/_documentation/api_reference/genomeutils.html b/docs/_build/html/_documentation/api_reference/genomeutils.html index 62ab23e5..d5778c9a 100644 --- a/docs/_build/html/_documentation/api_reference/genomeutils.html +++ b/docs/_build/html/_documentation/api_reference/genomeutils.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -356,16 +355,16 @@
    -

    Genome Utilities#

    +

    Genome Utilities#

    -class finaletoolkit.genome.GenomeGaps(gaps_bed: Path | str = None)#
    +class finaletoolkit.genome.GenomeGaps(gaps_bed: Path | str | None = None)#

    Reads telomere, centromere, and short_arm intervals from a bed file or generates these intervals from UCSC gap and centromere tracks for hg19 and hg38.

    -classmethod b37()#
    +classmethod b37()#

    Creates a GenomeGaps for the Broad Institute GRCh37 reference genome i.e b37. This reference genome is also based on GRCh37, but differs from the UCSC hg19 reference in a few ways, @@ -374,18 +373,19 @@

    Genome Utilities -

    Returns#

    -
    -
    gapsGenomeGaps

    GenomeGaps for the b37 reference genome.

    +
    +
    Returns:
    +

    gaps – GenomeGaps for the b37 reference genome.

    +
    +
    Return type:
    +

    GenomeGaps

    -

    -get_arm(contig: str, start: int, stop: int) str#
    +get_arm(contig: str, start: int, stop: int) str#

    Returns the chromosome arm the interval is in. If in the short arm of an acrocentric chromosome or intersects a centromere, returns an empty string.

    @@ -397,257 +397,224 @@

    Returnsint

    End of interval.

    -
    -

    Returns#

    -
    -
    armstr

    Arm that interval is in.

    +
    +
    Returns:
    +

    arm – Arm that interval is in.

    -
    -
    -
    -

    Raises#

    -
    -
    ValueError

    Raised for invalid coordinates

    +
    Return type:
    +

    str

    +
    +
    Raises:
    +

    ValueError – Raised for invalid coordinates

    -

    -get_contig_gaps(contig: str) ContigGaps#
    +get_contig_gaps(contig: str) ContigGaps#

    Creates a ContigGaps for the specified chromosome

    -
    -

    Parameters#

    -
    -
    contigstr

    Chromosome to make ContigGaps for

    +
    +
    Parameters:
    +

    contig (str) – Chromosome to make ContigGaps for

    -
    -
    -
    -

    Returns#

    -
    -
    ContigGaps

    Contains centromere and telomere intervals for chromosome

    +
    Returns:
    +

    Contains centromere and telomere intervals for chromosome

    +
    +
    Return type:
    +

    ContigGaps

    -
    -classmethod hg38()#
    +classmethod hg38()#

    Creates a GenomeGaps for the hg38 reference genome. This sequences uses chromosome names that start with ‘chr’ and is synonymous with the GRCh38 reference genome. -Returns -——- -gaps : GenomeGaps

    -
    -

    GenomeGaps for the hg38 reference genome.

    -
    +:returns: gaps – GenomeGaps for the hg38 reference genome. +:rtype: GenomeGaps

    -in_tcmere(contig: str, start: int, stop: int) bool#
    +in_tcmere(contig: str, start: int, stop: int) bool#

    Checks if specified interval is in a centromere or telomere

    -
    -

    Parameters#

    -
    -
    contigstr

    Chromosome name

    -
    -
    startint

    Start of interval

    +
    +
    Parameters:
    +
      +
    • contig (str) – Chromosome name

    • +
    • start (int) – Start of interval

    • +
    • stop (int) – End of interval

    • +
    -
    stopint

    End of interval

    +
    Returns:
    +

    in_telomere_or_centromere – True if in a centromere or telomere

    -
    -
    -
    -

    Returns#

    -
    -
    in_telomere_or_centromerebool

    True if in a centromere or telomere

    +
    Return type:
    +

    bool

    -
    -overlaps_gap(contig: str, start: int, stop: int) bool#
    +overlaps_gap(contig: str, start: int, stop: int) bool#

    Checks if specified interval overlaps a gap interval

    -
    -

    Parameters#

    -
    -
    contigstr

    Chromosome name

    -
    -
    startint

    Start of interval

    +
    +
    Parameters:
    +
      +
    • contig (str) – Chromosome name

    • +
    • start (int) – Start of interval

    • +
    • stop (int) – End of interval

    • +
    -
    stopint

    End of interval

    +
    Returns:
    +

    in_telomere_or_centromere – True if in a centromere or telomere

    -
    -
    -
    -

    Returns#

    -
    -
    in_telomere_or_centromerebool

    True if in a centromere or telomere

    +
    Return type:
    +

    bool

    -
    -to_bed(output_file: str)#
    +to_bed(output_file: str)#

    Prints gap intervals in GenomeGaps to a BED4 file where the name is the type of gap interval.

    -
    -

    Parameters#

    -
    -
    output_filestr

    File to write to. Optionally gzipped. If output_file == ‘-‘, +

    +
    Parameters:
    +

    output_file (str) – File to write to. Optionally gzipped. If output_file == ‘-‘, results will be writted to stdout.

    -
    -classmethod ucsc_hg19()#
    +classmethod ucsc_hg19()#

    Creates a GenomeGaps for the UCSC hg19 reference genome. This sequences uses chromosome names that start with ‘chr’ and is based on a version of the GRCh37 reference genome.

    -
    -

    Returns#

    -
    -
    gapsGenomeGaps

    GenomeGaps for the UCSC hg19 reference genome.

    +
    +
    Returns:
    +

    gaps – GenomeGaps for the UCSC hg19 reference genome.

    +
    +
    Return type:
    +

    GenomeGaps

    -

    -class finaletoolkit.genome.ContigGaps(contig: str, centromere: Tuple[int, int], telomeres: Iterable[Tuple[int, int]], has_short_arm: bool = False)#
    +class finaletoolkit.genome.ContigGaps(contig: str, centromere: tuple[int, int], telomeres: Iterable[tuple[int, int]], has_short_arm: bool = False)#
    -get_arm(start: int, stop: int)#
    +get_arm(start: int, stop: int)#

    Returns name of chromosome arm the interval is in. Returns “NOARM” if in a centromere, telomere, or short arm of an acrocentric chromosome.

    -
    -

    Parameters#

    -
    -
    startint

    Start of interval.

    +
    +
    Parameters:
    +
      +
    • start (int) – Start of interval.

    • +
    • stop (int) – End of interval.

    • +
    -
    stopint

    End of interval.

    +
    Returns:
    +

    Name of the chromosome arm.

    -
    -
    -
    -

    Returns#

    -
    -
    str

    Name of the chromosome arm.

    +
    Return type:
    +

    str

    -
    -
    -
    -

    Raises#

    -
    -
    ValueError

    Raised if invalid coordinates are given.

    +
    Raises:
    +

    ValueError – Raised if invalid coordinates are given.

    -
    -in_gap(start: int, stop: int) bool#
    +in_gap(start: int, stop: int) bool#

    Checks if specified interval is in a gap.

    -
    -

    Parameters#

    -
    -
    startint

    Start of interval.

    +
    +
    Parameters:
    +
      +
    • start (int) – Start of interval.

    • +
    • stop (int) – End of Interval.

    • +
    -
    stopint

    End of Interval.

    +
    Returns:
    +

    True if there is an overlap.

    -
    -
    -
    -

    Returns#

    -
    -
    bool

    True if there is an overlap.

    +
    Return type:
    +

    bool

    -
    -in_tcmere(start: int, stop: int) bool#
    +in_tcmere(start: int, stop: int) bool#

    Checks if specified interval is in a centromere or telomere.

    -
    -

    Parameters#

    -
    -
    startint

    Start of interval.

    +
    +
    Parameters:
    +
      +
    • start (int) – Start of interval.

    • +
    • stop (int) – End of Interval.

    • +
    -
    stopint

    End of Interval.

    +
    Returns:
    +

    True if there is an overlap.

    -
    -
    -
    -

    Returns#

    -
    -
    bool

    True if there is an overlap.

    +
    Return type:
    +

    bool

    -
    -finaletoolkit.genome.ucsc_hg19_gap_bed(output_file: str)#
    +finaletoolkit.genome.ucsc_hg19_gap_bed(output_file: str)#

    Creates BED4 of centromeres, telomeres, and short arms for the UCSC hg19 reference sequence.

    -
    -

    Parameters#

    -
    -
    output_filestr

    Output path

    +
    +
    Parameters:
    +

    output_file (str) – Output path

    -
    -finaletoolkit.genome.b37_gap_bed(output_file: str)#
    +finaletoolkit.genome.b37_gap_bed(output_file: str)#

    Creates BED4 of centromeres, telomeres, and short arms for the Broad Institute GRCh37 (b37) reference sequence. Also useful for files aligned to human_g1k_v37 (1000 Genomes Project).

    -
    -

    Parameters#

    -
    -
    output_filestr

    Output path

    +
    +
    Parameters:
    +

    output_file (str) – Output path

    -
    -finaletoolkit.genome.ucsc_hg38_gap_bed(output_file: str)#
    +finaletoolkit.genome.ucsc_hg38_gap_bed(output_file: str)#

    Creates BED4 of centromeres, telomeres, and short arms for the UCSC hg38 reference sequence.

    -
    -

    Parameters#

    -
    -
    output_filestr

    Output path

    +
    +
    Parameters:
    +

    output_file (str) – Output path

    -
    @@ -755,7 +722,7 @@

    Parameters

    - Created using Sphinx 6.2.1. + Created using Sphinx 7.3.7.

    diff --git a/docs/_build/html/_documentation/api_reference/index.html b/docs/_build/html/_documentation/api_reference/index.html index 809d8dc1..25ae42ad 100644 --- a/docs/_build/html/_documentation/api_reference/index.html +++ b/docs/_build/html/_documentation/api_reference/index.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -354,7 +353,7 @@
    -

    API#

    +

    API#

    • Basic Features
        @@ -389,8 +388,13 @@

        API#
      • Frag File Utilities
      • Genome Utilities
          @@ -486,7 +490,7 @@

          API# diff --git a/docs/_build/html/_documentation/api_reference/wps.html b/docs/_build/html/_documentation/api_reference/wps.html index cee02ba6..f2d6f9a7 100644 --- a/docs/_build/html/_documentation/api_reference/wps.html +++ b/docs/_build/html/_documentation/api_reference/wps.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -357,134 +356,104 @@
          -

          Window Protection Score (WPS)#

          +

          Window Protection Score (WPS)#

          -finaletoolkit.frag.wps(input_file: str | AlignmentFile, contig: str, start: int | str, stop: int | str, output_file: str = None, window_size: int = 120, fraction_low: int = 120, fraction_high: int = 180, quality_threshold: int = 30, verbose: bool | int = 0) ndarray#
          +finaletoolkit.frag.wps(input_file: str | AlignmentFile, contig: str, start: int | str, stop: int | str, output_file: str | None = None, window_size: int = 120, fraction_low: int = 120, fraction_high: int = 180, quality_threshold: int = 30, verbose: bool | int = 0) ndarray#

          Return (raw) Windowed Protection Scores as specified in Snyder et al (2016) over a region [start,stop).

          -
          -

          Parameters#

          -
          -
          input_filestr or pysam.AlignmentFile

          BAM, SAM or tabix file containing paired-end fragment reads or its -path. AlignmentFile must be opened in read mode.

          -
          -
          -

          contig : str -start : int -stop : int -output_file : string, optional -window_size : int, optional

          -
          -

          Size of window to calculate WPS. Default is k = 120, equivalent -to L-WPS.

          -
          -
          -
          fraction_lowint, optional

          Specifies lowest fragment length included in calculation. -Default is 120, equivalent to long fraction.

          +
          +
          Parameters:
          +
            +
          • input_file (str or pysam.AlignmentFile) – BAM, SAM or tabix file containing paired-end fragment reads or its +path. AlignmentFile must be opened in read mode.

          • +
          • contig (str)

          • +
          • start (int)

          • +
          • stop (int)

          • +
          • output_file (string, optional)

          • +
          • window_size (int, optional) – Size of window to calculate WPS. Default is k = 120, equivalent +to L-WPS.

          • +
          • fraction_low (int, optional) – Specifies lowest fragment length included in calculation. +Default is 120, equivalent to long fraction.

          • +
          • fraction_high (int, optional) – Specifies highest fragment length included in calculation. +Default is 180, equivalent to long fraction.

          • +
          • quality_threshold (int, optional)

          • +
          • workers (int, optional)

          • +
          • verbose (bool, optional)

          • +
          -
          fraction_highint, optional

          Specifies highest fragment length included in calculation. -Default is 180, equivalent to long fraction.

          +
          Returns:
          +

          scores – np struct array of with columns contig, start, and wps.

          -
          -

          quality_threshold : int, optional -workers : int, optional -verbose : bool, optional

          -
          -
          -

          Returns#

          -
          -
          scoresnumpy.ndarray

          np array of shape (n, 2) where column 1 is the coordinate and -column 2 is the score and n is the number of coordinates in -region [start,stop)

          +
          Return type:
          +

          numpy.ndarray

          -
          -finaletoolkit.frag.multi_wps(input_file: AlignmentFile | str, site_bed: str, output_file: str | None = None, window_size: int = 120, interval_size: int = 5000, fraction_low: int = 120, fraction_high: int = 180, quality_threshold: int = 30, workers: int = 1, verbose: bool | int = 0) ndarray#
          +finaletoolkit.frag.multi_wps(input_file: AlignmentFile | str, site_bed: str, output_file: None | str = None, window_size: int = 120, interval_size: int = 5000, fraction_low: int = 120, fraction_high: int = 180, quality_threshold: int = 30, workers: int = 1, verbose: bool | int = 0) ndarray#

          Function that aggregates WPS over sites in BED file according to the method described by Snyder et al (2016).

          -
          -

          Parameters#

          -
          -
          input_filestr or pysam.AlignmentFile

          BAM, SAM, or tabix file containing paired-end fragment reads or its -path. AlignmentFile must be opened in read mode.

          -
          -
          site_bed: str

          Bed file containing intervals to perform WPS on.

          -
          -
          -

          output_file : string, optional -window_size : int, optional

          -
          -

          Size of window to calculate WPS. Default is k = 120, equivalent -to L-WPS.

          -
          -
          -
          interval_sizeint, optional

          Size of each interval specified in the bed file. Should be the -same for every interbal. Default is 5000.

          -
          -
          fraction_lowint, optional

          Specifies lowest fragment length included in calculation. -Default is 120, equivalent to long fraction.

          -
          -
          fraction_highint, optional

          Specifies highest fragment length included in calculation. -Default is 120, equivalent to long fraction.

          +
          +
          Parameters:
          +
            +
          • input_file (str or pysam.AlignmentFile) – BAM, SAM, or tabix file containing paired-end fragment reads or its +path. AlignmentFile must be opened in read mode.

          • +
          • site_bed (str) – Bed file containing intervals to perform WPS on.

          • +
          • output_file (string, optional)

          • +
          • window_size (int, optional) – Size of window to calculate WPS. Default is k = 120, equivalent +to L-WPS.

          • +
          • interval_size (int, optional) – Size of each interval specified in the bed file. Should be the +same for every interbal. Default is 5000.

          • +
          • fraction_low (int, optional) – Specifies lowest fragment length included in calculation. +Default is 120, equivalent to long fraction.

          • +
          • fraction_high (int, optional) – Specifies highest fragment length included in calculation. +Default is 120, equivalent to long fraction.

          • +
          • quality_threshold (int, optional)

          • +
          • workers (int, optional)

          • +
          • verbose (bool, optional)

          • +
          -
          -

          quality_threshold : int, optional -workers : int, optional -verbose : bool, optional

          -
          -
          -

          Returns#

          -
          -
          scoresnumpy.ndarray

          np array of shape (n, 2) where column 1 is the coordinate and +

          Returns:
          +

          scores – np array of shape (n, 2) where column 1 is the coordinate and column 2 is the score and n is the number of coordinates in region [start,stop)

          +
          Return type:
          +

          numpy.ndarray

          +
          -
          -finaletoolkit.frag.adjust_wps(input_file: str, interval_file: str, output_file: str, genome_file: str, median_window_size: int = 1000, savgol_window_size: int = 21, savgol_poly_deg: int = 2, mean: bool = False, subtract_edges: bool = False, edge_size: int = 500, workers: int = 1, verbose: Union(bool, int) = False)#
          +finaletoolkit.frag.adjust_wps(input_file: str, interval_file: str, output_file: str, genome_file: str, median_window_size: int = 1000, savgol_window_size: int = 21, savgol_poly_deg: int = 2, mean: bool = False, subtract_edges: bool = False, edge_size: int = 500, workers: int = 1, verbose: Union(bool, int) = False)#

          Adjusts raw WPS data in a BigWig by applying a median filter and Savitsky-Golay filter (Savitsky and Golay, 1964).

          -
          -

          Parameters#

          -
          -
          input_filestr

          Path string to a BigWig containing raw WPS data.

          -
          -
          interval_filestr

          BED format file containing intervals over which WPS was -calculated on.

          -
          -
          output_filestr

          BigWig file to write adjusted WPS to.

          -
          -
          genome_filestr

          The genome file for the reference genome that WGS was aligned +

          +
          Parameters:
          +
            +
          • input_file (str) – Path string to a BigWig containing raw WPS data.

          • +
          • interval_file (str) – BED format file containing intervals over which WPS was +calculated on.

          • +
          • output_file (str) – BigWig file to write adjusted WPS to.

          • +
          • genome_file (str) – The genome file for the reference genome that WGS was aligned to. A tab delimited file where column 1 contains the name of -chromosomes and column 2 contains chromosome length.

            -
          -
          median_window_sizeint, optional

          Size of median filter window. Default is 1000.

          -
          -
          savgol_window_sizeint, optional

          Size of Savitsky Golay filter window. Default is 21.

          -
          -
          savgol_poly_degint, optional

          Degree polynomial for Savitsky Golay filter. Default is 2.

          -
          -
          meanbool, optional

          If true, a mean filter is used instead of median. Default is -False.

          -
          -
          subtract_edgesbool, optional

          If true, take the median of the first and last 500 bases in a -window and subtract from the whole interval. Default is False.

          -
          -
          workersint, optional

          Number of processes to use. Default is 1.

          -
          -
          verbosebool or int, optional

          Default is False.

          +chromosomes and column 2 contains chromosome length.

          +
        • median_window_size (int, optional) – Size of median filter window. Default is 1000.

        • +
        • savgol_window_size (int, optional) – Size of Savitsky Golay filter window. Default is 21.

        • +
        • savgol_poly_deg (int, optional) – Degree polynomial for Savitsky Golay filter. Default is 2.

        • +
        • mean (bool, optional) – If true, a mean filter is used instead of median. Default is +False.

        • +
        • subtract_edges (bool, optional) – If true, take the median of the first and last 500 bases in a +window and subtract from the whole interval. Default is False.

        • +
        • workers (int, optional) – Number of processes to use. Default is 1.

        • +
        • verbose (bool or int, optional) – Default is False.

        • +

    -

    @@ -584,7 +553,7 @@

    Parameters

    - Created using Sphinx 6.2.1. + Created using Sphinx 7.3.7.

    diff --git a/docs/_build/html/_documentation/cli_reference/index.html b/docs/_build/html/_documentation/cli_reference/index.html index c0247381..f3f4ca76 100644 --- a/docs/_build/html/_documentation/cli_reference/index.html +++ b/docs/_build/html/_documentation/cli_reference/index.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -345,22 +344,32 @@
    -

    CLI#

    +

    CLI#

    FinaleToolkit is a package and standalone program to extract fragmentation features of cell-free DNA from paired-end sequencing data.

    -
    usage: finaletoolkit [-h] {coverage,frag-length-bins,frag-length-intervals,cleavage-profile,wps,adjust-wps,delfi,delfi-gc-correct,end-motifs,interval-end-motifs,mds,interval-mds,filter-bam,agg-bw,gap-bed} ...
    +
    usage: finaletoolkit [-h] [-v]
    +                     {coverage,frag-length-bins,frag-length-intervals,cleavage-profile,wps,adjust-wps,delfi,delfi-gc-correct,end-motifs,interval-end-motifs,mds,interval-mds,filter-bam,agg-bw,gap-bed}
    +                     ...
     
    +
    +

    Named Arguments#

    +
    +
    -v, --version
    +

    show program’s version number and exit

    +
    +
    +
    -

    Sub-commands#

    +

    Sub-commands#

    -

    coverage#

    +

    coverage#

    Calculates fragmentation coverage over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

    finaletoolkit coverage [-h] [-o OUTPUT_FILE] [-s SCALE_FACTOR] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file interval_file
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    @@ -370,8 +379,8 @@

    Positional Arguments

    -
    -

    Named Arguments#

    +
    +

    Named Arguments#

    -o, --output_file

    A BED file containing coverage values over the intervals specified in interval file.

    @@ -397,21 +406,22 @@

    Named Arguments -

    frag-length-bins#

    +

    frag-length-bins#

    Retrieves fragment lengths grouped in bins given a BAM/SAM/CRAM/Fragment file.

    -
    finaletoolkit frag-length-bins [-h] [-c CONTIG] [-S START] [-p {midpoint,any}] [-E STOP] [--bin-size BIN_SIZE] [-o OUTPUT_FILE] [--contig-by-contig] [--histogram] [-q QUALITY_THRESHOLD] [-v] input_file
    +
    finaletoolkit frag-length-bins [-h] [-c CONTIG] [-S START] [-p {midpoint,any}] [-E STOP] [--bin-size BIN_SIZE] [-o OUTPUT_FILE] [--contig-by-contig] [--histogram] [-q QUALITY_THRESHOLD] [-v]
    +                               input_file
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    -
    -

    Named Arguments#

    +
    +

    Named Arguments#

    -c, --contig

    Specify the contig or chromosome to select fragments from. (Required if using –start or –stop.)

    @@ -454,13 +464,13 @@

    Named Arguments -

    frag-length-intervals#

    +

    frag-length-intervals#

    Retrieves fragment length summary statistics over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

    finaletoolkit frag-length-intervals [-h] [-p {midpoint,any}] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file interval_file
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    @@ -470,8 +480,8 @@

    Positional Arguments -

    Named Arguments#

    +
    +

    Named Arguments#

    -p, --intersect_policy

    Possible choices: midpoint, any

    @@ -498,13 +508,13 @@

    Named Arguments -

    cleavage-profile#

    +

    cleavage-profile#

    Calculates cleavage proportion over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

    finaletoolkit cleavage-profile [-h] [-o OUTPUT_FILE] [-lo FRACTION_LOW] [-hi FRACTION_HIGH] [-q QUALITY_THRESHOLD] [-l LEFT] [-r RIGHT] [-w WORKERS] [-v] input_file interval_file
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    @@ -514,8 +524,8 @@

    Positional Arguments -

    Named Arguments#

    +
    +

    Named Arguments#

    -o, --output_file

    A bigWig file containing the cleavage proportion results over the intervals specified in interval file.

    @@ -553,13 +563,13 @@

    Named Arguments -

    wps#

    +

    wps#

    Calculates Windowed Protection Score (WPS) over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

    finaletoolkit wps [-h] [-o OUTPUT_FILE] [-i INTERVAL_SIZE] [-W WINDOW_SIZE] [-lo FRACTION_LOW] [-hi FRACTION_HIGH] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file site_bed
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    @@ -569,8 +579,8 @@

    Positional Arguments -

    Named Arguments#

    +
    +

    Named Arguments#

    -o, --output_file

    A bigWig file containing the WPS results over the intervals specified in interval file.

    @@ -608,13 +618,13 @@

    Named Arguments -

    adjust-wps#

    +

    adjust-wps#

    Adjusts raw Windowed Protection Score (WPS) by applying a median filter and Savitsky-Golay filter.

    finaletoolkit adjust-wps [-h] [-o OUTPUT_FILE] [-m MEDIAN_WINDOW_SIZE] [-s SAVGOL_WINDOW_SIZE] [-p SAVGOL_POLY_DEG] [-w WORKERS] [--mean] [--subtract-edges] [-v] input_file interval_file genome_file
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file

    A bigWig file containing the WPS results over the intervals specified in interval file.

    @@ -627,8 +637,8 @@

    Positional Arguments -

    Named Arguments#

    +
    +

    Named Arguments#

    -o, --output-file

    A bigWig file containing the adjusted WPS results over the intervals specified in interval file.

    @@ -665,13 +675,13 @@

    Named Arguments -

    delfi#

    +

    delfi#

    Calculates DELFI featrues over genome, returning information about (GC-corrected) short fragments, long fragments, DELFI ratio, and total fragments. NOTE: Due to some ad hoc implementation details, currently the only accepted reference genome is hg19.

    finaletoolkit delfi [-h] [-b BLACKLIST_FILE] [-g GAP_FILE] [-o OUTPUT_FILE] [-W WINDOW_SIZE] [-gc] [-m] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file autosomes reference_file bins_file
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    @@ -687,8 +697,8 @@

    Positional Arguments -

    Named Arguments#

    +
    +

    Named Arguments#

    -b, --blacklist_file

    BED file containing regions to ignore when calculating DELFI.

    @@ -728,21 +738,21 @@

    Named Arguments -

    delfi-gc-correct#

    +

    delfi-gc-correct#

    Performs gc-correction on raw delfi data.

    finaletoolkit delfi-gc-correct [-h] [-o OUTPUT_FILE] [--header-lines HEADER_LINES] [-v] input_file
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file

    BED file containing raw DELFI data. Raw DELFI data should only have columns for “contig”, “start”, “stop”, “arm”, “short”, “long”, “gc”, “num_frags”, “ratio”.

    -
    -

    Named Arguments#

    +
    +

    Named Arguments#

    -o, --output-file

    BED to print GC-corrected DELFI fractions. If “-”, will write to stdout.

    @@ -759,13 +769,13 @@

    Named Arguments -

    end-motifs#

    +

    end-motifs#

    Measures frequency of k-mer 5’ end motifs.

    finaletoolkit end-motifs [-h] [-k K] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file refseq_file
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    @@ -775,8 +785,8 @@

    Positional Arguments -

    Named Arguments#

    +
    +

    Named Arguments#

    -k

    Length of k-mer.

    @@ -802,13 +812,13 @@

    Named Arguments -

    interval-end-motifs#

    +

    interval-end-motifs#

    Measures frequency of k-mer 5’ end motifs in each region specified in a BED file and writes data into a table.

    finaletoolkit interval-end-motifs [-h] [-k K] [-lo FRACTION_LOW] [-hi FRACTION_HIGH] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file refseq_file intervals
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    @@ -821,8 +831,8 @@

    Positional Arguments -

    Named Arguments#

    +
    +

    Named Arguments#

    -k

    Length of k-mer.

    @@ -856,13 +866,13 @@

    Named Arguments -

    mds#

    +

    mds#

    Reads k-mer frequencies from a file and calculates a motif diversity score (MDS) using normalized Shannon entropy as described by Jiang et al (2020).

    finaletoolkit mds [-h] [-s SEP] [--header HEADER] [file_path]
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    file_path

    Tab-delimited or similar file containing one column for all k-mers a one column for frequency. Reads from stdin by default.

    @@ -870,8 +880,8 @@

    Positional Arguments -

    Named Arguments#

    +
    +

    Named Arguments#

    -s, --sep

    Separator used in tabular file.

    @@ -885,13 +895,13 @@

    Named Arguments

    -

    interval-mds#

    +

    interval-mds#

    Reads k-mer frequencies from a file and calculates a motif diversity score (MDS) for each interval using normalized Shannon entropy as described by Jiang et al (2020).

    finaletoolkit interval-mds [-h] [-s SEP] [file_path] file_out
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    file_path

    Tab-delimited or similar file containing one column for all k-mers a one column for frequency. Reads from stdin by default.

    @@ -903,8 +913,8 @@

    Positional Arguments -

    Named Arguments#

    +
    +

    Named Arguments#

    -s, --sep

    Separator used in tabular file.

    @@ -914,21 +924,21 @@

    Named Arguments

    -

    filter-bam#

    +

    filter-bam#

    Filters a BAM file so that all reads are in mapped pairs, exceed a certain MAPQ, are not flagged for quality, are read1, are not secondary or supplementary alignments, and are on the same reference sequence as the mate.

    finaletoolkit filter-bam [-h] [-r REGION_FILE] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-hi FRACTION_HIGH] [-lo FRACTION_LOW] [-w WORKERS] [-v] input_file
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file

    Path to BAM file.

    -
    -

    Named Arguments#

    +
    +

    Named Arguments#

    -r, --region-file

    Only output alignments overlapping the intervals in this BED file will be included.

    @@ -958,13 +968,13 @@

    Named Arguments

    -

    agg-bw#

    +

    agg-bw#

    Aggregates a bigWig signal over constant-length intervals defined in a BED file.

    finaletoolkit agg-bw [-h] [-o OUTPUT_FILE] [-m MEDIAN_WINDOW_SIZE] [-v] input_file interval_file
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    input_file
    @@ -976,8 +986,8 @@

    Positional Arguments -

    Named Arguments#

    +
    +

    Named Arguments#

    -o, --output-file

    A wiggle file containing the aggregate signal over the intervals specified in interval file.

    @@ -994,13 +1004,13 @@

    Named Arguments

    -

    gap-bed#

    +

    gap-bed#

    Creates a BED4 file containing centromeres, telomeres, and short-arm intervals, similar to the gaps annotation track for hg19 found on the UCSC Genome Browser (Kent et al 2002). Currently only supports hg19, b37, human_g1k_v37, hg38, and GRCh38

    finaletoolkit gap-bed [-h] {hg19,b37,human_g1k_v37,hg38,GRCh38} output_file
     
    -

    Positional Arguments#

    +

    Positional Arguments#

    reference_genome

    Possible choices: hg19, b37, human_g1k_v37, hg38, GRCh38

    @@ -1062,75 +1072,76 @@

    Positional Arguments

    diff --git a/docs/_build/html/_documentation/index.html b/docs/_build/html/_documentation/index.html new file mode 100644 index 00000000..4517d5cf --- /dev/null +++ b/docs/_build/html/_documentation/index.html @@ -0,0 +1,433 @@ + + + + + + + + + + + FinaleToolkit Documentation — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + + + +
    + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + + + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/_documentation/user_guide/features.html b/docs/_build/html/_documentation/user_guide/features.html index e27a38b3..746ef6db 100644 --- a/docs/_build/html/_documentation/user_guide/features.html +++ b/docs/_build/html/_documentation/user_guide/features.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -358,37 +357,37 @@
    -

    Features#

    +

    Features#

    FinaleToolkit has support for the following cell-free DNA features:

    -

    Fragment Length#

    +

    Fragment Length#

    FinaleToolkit can calculate the fragment length distribution and summary statistics of cell-free DNA fragments.

    -

    Fragment Coverage#

    +

    Fragment Coverage#

    FinaleToolkit can calculate fragment coverage (the number of reads mapped to a specific region of the genome). This coverage can be normalized by the total number of reads in the sample, or simply the raw value.

    -

    Windowed Protection Score (WPS)#

    +

    Windowed Protection Score (WPS)#

    FinaleToolkit can calculate the Windowed Protection Score (WPS), which is a metric designed by Snyder et al. 2016.

    It is used to quantify the level of protection or coverage of DNA fragments across a specific genomic region. It’s calculated by assessing the number of DNA fragments that fully span a defined window (typically 120 base pairs) centered around a particular genomic coordinate, and then subtracting the number of fragments with an endpoint falling within the same window. This score is correlated with the location of nucleosomes and other genomic features, including transcriptional start sites (TSS) and DNase I hypersensitive sites (DHSs).

    -

    DELFI#

    +

    DELFI#

    FinaleToolkit can calculate DELFI, which is a metric designed by Cristiano et al. 2019.

    DELFI is a metric that was introduced to identify abnormalities in cfDNA from their fragmentation patterns. In the original paper, DELFI was used to categorize patients with cancer and the associated tumor tissues of origin. The associated DELFI score is the ratio between the GC%-corrected short fragment count and the GC%-corrected long fragment count.

    -

    End Motifs#

    +

    End Motifs#

    FinaleToolkit can calculate the frequency of end-motif k-mers of cell-free DNA fragments. Since end motifs are specific sequences found at the ends of cfDNA fragments resulting from cleavage, they can be used to potentially detect patterns associated with certain conditions or diseases.

    -

    Motif Diversity Score (MDS)#

    +

    Motif Diversity Score (MDS)#

    FinaleToolkit can calculate the Motif Diversity Score (MDS), which is a metric designed by Jiang et al. 2020.

    The MDS is a metric that quantifies the diversity of cfDNA end motifs. It is the normalized Shannon entropy of the categorical distribution of all possible end-motif k-mers.

    -

    Cleavage Profile#

    +

    Cleavage Profile#

    FinaleToolkit can calculate the Cleavage Proportion, which is a metric designed by Zhou et al. 2022.

    The cleavage proportion is, by definition, the number of fragment ends that fall within a nucleotide location over the total number of fragment ends that overlap that nucleotide location. According to the authors, this metric shows a relationship to DNA methylation, specifically methylation at CpG sites.

    @@ -493,7 +492,7 @@

    Cleavage Profile

    - Created using Sphinx 6.2.1. + Created using Sphinx 7.3.7.

    diff --git a/docs/_build/html/_documentation/user_guide/help.html b/docs/_build/html/_documentation/user_guide/help.html index 66af5c79..264cbaa0 100644 --- a/docs/_build/html/_documentation/user_guide/help.html +++ b/docs/_build/html/_documentation/user_guide/help.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -358,7 +357,7 @@
    -

    Help#

    +

    Help#

    If you think you’ve encountered a bug in FinaleToolkit, please report it on the Github issue tracker . To be useful, bug reports must include the following information:

    diff --git a/docs/_build/html/_documentation/user_guide/index.html b/docs/_build/html/_documentation/user_guide/index.html index c5796284..07adc385 100644 --- a/docs/_build/html/_documentation/user_guide/index.html +++ b/docs/_build/html/_documentation/user_guide/index.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -355,7 +354,7 @@
    -

    User Guide#

    +

    User Guide#

    diff --git a/docs/_build/html/_documentation/user_guide/inputdata.html b/docs/_build/html/_documentation/user_guide/inputdata.html index 69c3f458..0cd27b1f 100644 --- a/docs/_build/html/_documentation/user_guide/inputdata.html +++ b/docs/_build/html/_documentation/user_guide/inputdata.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -358,24 +357,24 @@
    -

    Input Data#

    +

    Input Data#

    FinaleToolkit is compatible with almost any paired-end sequence data.

    -

    SAM#

    +

    SAM#

    A sequence alignment map (SAM) file is a human-readable file format that stores the results of sequence alignment. It contains information about the alignment of each read to the reference genome, as well as information about the read itself.

    -

    BAM#

    +

    BAM#

    A binary alignment file (BAM) provides the same information as a SAM file, but in a binary format. This can be useful for saving space on disk, but is not human-readable.

    FinaleToolkit requires that BAM files be BAI indexed. Therefore, you should have an associated .bam.bai file in the same directory of your input data.

    -

    CRAM#

    +

    CRAM#

    A compressed read alignment map file is a compressed version of a SAM file. It is a binary file that is smaller than a BAM file, but still contains all of the same information.

    FinaleToolkit requires that CRAM files be CRAI indexed. Therefore, you should have an associated .cram.crai file in the same directory of your input data.

    -

    Fragment File#

    +

    Fragment File#

    A fragment file (.frag.gz) file that is derived from information in a BAM file. A fragment file is a block-gzipped BED3+2 file (similar to a tab-separated value file) that contains the following columns (with one row entry for each fragment): chrom, start, stop, mapq, and strand.

    Here, mapq is the mapping quality of the fragment, and strand is the strand of the fragment. The strand column can be either + or -.

    FinaleToolkit requires that fragment files be Tabix indexed. Therefore, you should have an associated .frag.gz.tbi file in the same directory of your input data.

    @@ -493,7 +492,7 @@

    Fragment File

    - Created using Sphinx 6.2.1. + Created using Sphinx 7.3.7.

    diff --git a/docs/_build/html/_documentation/user_guide/installation.html b/docs/_build/html/_documentation/user_guide/installation.html index dcb7c381..66395bf1 100644 --- a/docs/_build/html/_documentation/user_guide/installation.html +++ b/docs/_build/html/_documentation/user_guide/installation.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -358,13 +357,13 @@
    -

    Installation#

    +

    Installation#

    -

    Prerequisites#

    +

    Prerequisites#

    The only prerequisite for installing FinaleToolkit is a Python version that is greater than 3.8.

    -

    Installation#

    +

    Installation#

    FinaleToolkit can be installed with with pip.

    Using pip:

    pip install finaletoolkit
    @@ -373,7 +372,7 @@ 

    Installationpip, it’s good practice to use a virtual environment, like a conda environment.

    -

    Errors#

    +

    Errors#

    If any errors arise during the installation, please fill out a detailed issue in the GitHub repository.

    If you are getting an ImportError on Mac when running FinaleToolkit, please run the following command in the terminal:

    $ brew install curl
    @@ -477,7 +476,7 @@ 

    Errors

    - Created using Sphinx 6.2.1. + Created using Sphinx 7.3.7.

    diff --git a/docs/_build/html/_documentation/user_guide/intersectpolicy.html b/docs/_build/html/_documentation/user_guide/intersectpolicy.html index 2ca1103f..efbcbfd8 100644 --- a/docs/_build/html/_documentation/user_guide/intersectpolicy.html +++ b/docs/_build/html/_documentation/user_guide/intersectpolicy.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -358,17 +357,17 @@
    -

    Intersect Policy#

    +

    Intersect Policy#

    When you give the Fragment Generator an interval of start and end to pull fragments from, which fragments will it return?

    What if a fragment has 1bp of overlap within the just on the edge of the window? Does it also return that fragment as well?

    These questions are answered by the intersect_policy argument, which shows up in many of the CLI and API commands.

    intersect_policy can either be midpoint or any.

    -

    Midpoint#

    +

    Midpoint#

    midpoint: The midpoint of the fragment determines whether the fragment will be returned or not. If the midpoint falls between start and end, then it will be returned. Else, it will not.

    -

    Any#

    +

    Any#

    any: As long as the fragment overlaps the interval between start and end in some capacity, then it will be returned. Else, it will not.

    @@ -467,7 +466,7 @@

    Any# diff --git a/docs/_build/html/_documentation/user_guide/quickstart.html b/docs/_build/html/_documentation/user_guide/quickstart.html index 37bca794..4015642a 100644 --- a/docs/_build/html/_documentation/user_guide/quickstart.html +++ b/docs/_build/html/_documentation/user_guide/quickstart.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -358,9 +357,9 @@
    -

    Quickstart#

    +

    Quickstart#

    -

    Getting Started#

    +

    Getting Started#

    If not to be integrated into a workflow, FinaleToolkit is intended to be run directly from a terminal interface.

    You can open the terminal and typing the following command:

    $ finaletoolkit
    @@ -368,7 +367,7 @@ 

    Getting Started -

    Importing Modules#

    +

    Importing Modules#

    The FinaleToolkit package itself is divided by its API functions.

    You can load all of the functions by using the following command:

    >>> import finaletoolkit as ft
    @@ -476,7 +475,7 @@ 

    Importing Modules

    - Created using Sphinx 6.2.1. + Created using Sphinx 7.3.7.

    diff --git a/docs/_build/html/_documentation/user_guide/structure.html b/docs/_build/html/_documentation/user_guide/structure.html index bb4a9520..06761ab8 100644 --- a/docs/_build/html/_documentation/user_guide/structure.html +++ b/docs/_build/html/_documentation/user_guide/structure.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -358,7 +357,7 @@
    -

    Structure#

    +

    Structure#

    While not particularly pertinent to your usage, we include this page to give you a sense of what is going on under the hood of FinaleToolkit:

    At the heart of FinaleToolkit is the Fragment Generator. This generator is designed to be as flexible as possible. It takes BAM, CRAM, SAM, and Fragment Files (among other arguments) and filters out the reads that are not of interest (e.x. unmapped reads, reads with low mapping quality, etc.). The fragments that make it through this filter are then passed to the relevant function to be processed.

    A rough outline of the structure of FinaleToolkit is therefore as follows:

    @@ -448,7 +447,7 @@

    Structure

    - Created using Sphinx 6.2.1. + Created using Sphinx 7.3.7.

    diff --git a/docs/_build/html/_documentation/user_guide/what.html b/docs/_build/html/_documentation/user_guide/what.html index 75ae49b1..0a0e3489 100644 --- a/docs/_build/html/_documentation/user_guide/what.html +++ b/docs/_build/html/_documentation/user_guide/what.html @@ -1,9 +1,8 @@ - - + @@ -29,16 +28,16 @@ - + - - - + + + @@ -358,7 +357,7 @@
    -

    Introduction#

    +

    Introduction#

    Circulating cell-free DNA (cfDNA) refers to highly fragmented DNA that circulate in blood plasma. In healthy conditions, cfDNA mainly originates from hematopoietic cells through apoptosis or necrosis. In pathological states, additional cfDNA is released from the genomes of otherwise inaccessible tissues (e.g., from tumors in cancer).

    CfDNA fragmentation patterns have been established as a promising non-invasive biomarker for disease detection and monitoring. It has been shown that fragmentation pattern and cfDNA tissue-of-origin changes are associated with changes in different pathological statuses.

    Computational approaches can extract fragmentation features from cfDNA whole genome sequencing (WGS) data. However, various established cfDNA fragmentation features (ex. Windowed Protection Score (WPS), Motif Diversity Score (MDS), DELFI) have source code which is often absent, poorly documented, ad hoc, and unmaintained.

    @@ -446,7 +445,7 @@

    Introduction

    - Created using Sphinx 6.2.1. + Created using Sphinx 7.3.7.

    diff --git a/docs/_build/html/_sources/_documentation/api_reference/fragfile.rst.txt b/docs/_build/html/_sources/_documentation/api_reference/fragfile.rst.txt index cd565280..a4774294 100644 --- a/docs/_build/html/_sources/_documentation/api_reference/fragfile.rst.txt +++ b/docs/_build/html/_sources/_documentation/api_reference/fragfile.rst.txt @@ -3,6 +3,16 @@ Frag File Utilities .. autofunction:: finaletoolkit.utils.filter_bam -.. autofunction:: finaletoolkit.utils.genome2list - .. autofunction:: finaletoolkit.utils.agg_bw + +.. autofunction:: finaletoolkit.utils.chrom_sizes_to_list + +.. autofunction:: finaletoolkit.utils.chrom_sizes_to_dict + +.. autofunction:: finaletoolkit.utils.frag_generator + +.. autofunction:: finaletoolkit.utils.frag_array + +.. autofunction:: finaletoolkit.utils.low_quality_read_pairs + +.. autofunction:: finaletoolkit.utils.overlaps diff --git a/docs/_documentation/index.rst b/docs/_build/html/_sources/_documentation/index.rst.txt similarity index 100% rename from docs/_documentation/index.rst rename to docs/_build/html/_sources/_documentation/index.rst.txt diff --git a/docs/_documentation/api_reference/basicfeatures.rst b/docs/_build/html/_sources/documentation/api_reference/basicfeatures.rst.txt similarity index 100% rename from docs/_documentation/api_reference/basicfeatures.rst rename to docs/_build/html/_sources/documentation/api_reference/basicfeatures.rst.txt diff --git a/docs/_documentation/api_reference/cleavageprofile.rst b/docs/_build/html/_sources/documentation/api_reference/cleavageprofile.rst.txt similarity index 100% rename from docs/_documentation/api_reference/cleavageprofile.rst rename to docs/_build/html/_sources/documentation/api_reference/cleavageprofile.rst.txt diff --git a/docs/_documentation/api_reference/delfi.rst b/docs/_build/html/_sources/documentation/api_reference/delfi.rst.txt similarity index 100% rename from docs/_documentation/api_reference/delfi.rst rename to docs/_build/html/_sources/documentation/api_reference/delfi.rst.txt diff --git a/docs/_documentation/api_reference/endmotifs.rst b/docs/_build/html/_sources/documentation/api_reference/endmotifs.rst.txt similarity index 100% rename from docs/_documentation/api_reference/endmotifs.rst rename to docs/_build/html/_sources/documentation/api_reference/endmotifs.rst.txt diff --git a/docs/_documentation/api_reference/fragfile.rst b/docs/_build/html/_sources/documentation/api_reference/fragfile.rst.txt similarity index 100% rename from docs/_documentation/api_reference/fragfile.rst rename to docs/_build/html/_sources/documentation/api_reference/fragfile.rst.txt diff --git a/docs/_documentation/api_reference/genomeutils.rst b/docs/_build/html/_sources/documentation/api_reference/genomeutils.rst.txt similarity index 100% rename from docs/_documentation/api_reference/genomeutils.rst rename to docs/_build/html/_sources/documentation/api_reference/genomeutils.rst.txt diff --git a/docs/_documentation/api_reference/index.rst b/docs/_build/html/_sources/documentation/api_reference/index.rst.txt similarity index 100% rename from docs/_documentation/api_reference/index.rst rename to docs/_build/html/_sources/documentation/api_reference/index.rst.txt diff --git a/docs/_documentation/api_reference/wps.rst b/docs/_build/html/_sources/documentation/api_reference/wps.rst.txt similarity index 100% rename from docs/_documentation/api_reference/wps.rst rename to docs/_build/html/_sources/documentation/api_reference/wps.rst.txt diff --git a/docs/_documentation/cli_reference/index.rst b/docs/_build/html/_sources/documentation/cli_reference/index.rst.txt similarity index 100% rename from docs/_documentation/cli_reference/index.rst rename to docs/_build/html/_sources/documentation/cli_reference/index.rst.txt diff --git a/docs/_build/html/_sources/documentation/index.rst.txt b/docs/_build/html/_sources/documentation/index.rst.txt new file mode 100644 index 00000000..46882573 --- /dev/null +++ b/docs/_build/html/_sources/documentation/index.rst.txt @@ -0,0 +1,9 @@ +FinaleToolkit Documentation +=========================== + +.. toctree:: + :maxdepth: 1 + + user_guide/index + cli_reference/index + api_reference/index \ No newline at end of file diff --git a/docs/_documentation/user_guide/features.rst b/docs/_build/html/_sources/documentation/user_guide/features.rst.txt similarity index 100% rename from docs/_documentation/user_guide/features.rst rename to docs/_build/html/_sources/documentation/user_guide/features.rst.txt diff --git a/docs/_documentation/user_guide/help.rst b/docs/_build/html/_sources/documentation/user_guide/help.rst.txt similarity index 100% rename from docs/_documentation/user_guide/help.rst rename to docs/_build/html/_sources/documentation/user_guide/help.rst.txt diff --git a/docs/_documentation/user_guide/index.rst b/docs/_build/html/_sources/documentation/user_guide/index.rst.txt similarity index 100% rename from docs/_documentation/user_guide/index.rst rename to docs/_build/html/_sources/documentation/user_guide/index.rst.txt diff --git a/docs/_documentation/user_guide/inputdata.rst b/docs/_build/html/_sources/documentation/user_guide/inputdata.rst.txt similarity index 100% rename from docs/_documentation/user_guide/inputdata.rst rename to docs/_build/html/_sources/documentation/user_guide/inputdata.rst.txt diff --git a/docs/_documentation/user_guide/installation.rst b/docs/_build/html/_sources/documentation/user_guide/installation.rst.txt similarity index 100% rename from docs/_documentation/user_guide/installation.rst rename to docs/_build/html/_sources/documentation/user_guide/installation.rst.txt diff --git a/docs/_documentation/user_guide/intersectpolicy.rst b/docs/_build/html/_sources/documentation/user_guide/intersectpolicy.rst.txt similarity index 100% rename from docs/_documentation/user_guide/intersectpolicy.rst rename to docs/_build/html/_sources/documentation/user_guide/intersectpolicy.rst.txt diff --git a/docs/_documentation/user_guide/quickstart.rst b/docs/_build/html/_sources/documentation/user_guide/quickstart.rst.txt similarity index 100% rename from docs/_documentation/user_guide/quickstart.rst rename to docs/_build/html/_sources/documentation/user_guide/quickstart.rst.txt diff --git a/docs/_documentation/user_guide/structure.rst b/docs/_build/html/_sources/documentation/user_guide/structure.rst.txt similarity index 100% rename from docs/_documentation/user_guide/structure.rst rename to docs/_build/html/_sources/documentation/user_guide/structure.rst.txt diff --git a/docs/_documentation/user_guide/what.rst b/docs/_build/html/_sources/documentation/user_guide/what.rst.txt similarity index 100% rename from docs/_documentation/user_guide/what.rst rename to docs/_build/html/_sources/documentation/user_guide/what.rst.txt diff --git a/docs/_build/html/_sources/index.rst.txt b/docs/_build/html/_sources/index.rst.txt index 9e850a13..2e44a11a 100644 --- a/docs/_build/html/_sources/index.rst.txt +++ b/docs/_build/html/_sources/index.rst.txt @@ -21,9 +21,9 @@ Documentation .. toctree:: :maxdepth: 2 - _documentation/user_guide/index - _documentation/cli_reference/index - _documentation/api_reference/index + documentation/user_guide/index + documentation/cli_reference/index + documentation/api_reference/index ----------------- Citations diff --git a/docs/_build/html/_sources/source/api_reference/basicfeatures.rst.txt b/docs/_build/html/_sources/source/api_reference/basicfeatures.rst.txt new file mode 100644 index 00000000..45ecd1b8 --- /dev/null +++ b/docs/_build/html/_sources/source/api_reference/basicfeatures.rst.txt @@ -0,0 +1,8 @@ +Basic Features +====================================== + +.. autofunction:: finaletoolkit.frag.coverage + +.. autofunction:: finaletoolkit.frag.frag_length + +.. autofunction:: finaletoolkit.frag.frag_length_bins \ No newline at end of file diff --git a/docs/_build/html/_sources/source/api_reference/cleavageprofile.rst.txt b/docs/_build/html/_sources/source/api_reference/cleavageprofile.rst.txt new file mode 100644 index 00000000..86df9471 --- /dev/null +++ b/docs/_build/html/_sources/source/api_reference/cleavageprofile.rst.txt @@ -0,0 +1,5 @@ +Cleavage Profile +====================================== +.. autofunction:: finaletoolkit.frag.cleavage_profile + + diff --git a/docs/_build/html/_sources/source/api_reference/delfi.rst.txt b/docs/_build/html/_sources/source/api_reference/delfi.rst.txt new file mode 100644 index 00000000..6cb541bc --- /dev/null +++ b/docs/_build/html/_sources/source/api_reference/delfi.rst.txt @@ -0,0 +1,9 @@ +DELFI +====================================== + +.. autofunction:: finaletoolkit.frag.delfi + +.. autofunction:: finaletoolkit.frag.delfi_gc_correct + +.. autofunction:: finaletoolkit.frag.delfi_merge_bins + diff --git a/docs/_build/html/_sources/source/api_reference/endmotifs.rst.txt b/docs/_build/html/_sources/source/api_reference/endmotifs.rst.txt new file mode 100644 index 00000000..2c0f6629 --- /dev/null +++ b/docs/_build/html/_sources/source/api_reference/endmotifs.rst.txt @@ -0,0 +1,16 @@ +End-Motifs +====================================== + +.. autoclass:: finaletoolkit.frag.EndMotifFreqs + :members: + +.. autoclass:: finaletoolkit.frag.EndMotifsIntervals + :members: + +.. autofunction:: finaletoolkit.frag.region_end_motifs + +.. autofunction:: finaletoolkit.frag.end_motifs + +.. autofunction:: finaletoolkit.frag.interval_end_motifs + + diff --git a/docs/_build/html/_sources/source/api_reference/fragfile.rst.txt b/docs/_build/html/_sources/source/api_reference/fragfile.rst.txt new file mode 100644 index 00000000..a4774294 --- /dev/null +++ b/docs/_build/html/_sources/source/api_reference/fragfile.rst.txt @@ -0,0 +1,18 @@ +Frag File Utilities +====================================== + +.. autofunction:: finaletoolkit.utils.filter_bam + +.. autofunction:: finaletoolkit.utils.agg_bw + +.. autofunction:: finaletoolkit.utils.chrom_sizes_to_list + +.. autofunction:: finaletoolkit.utils.chrom_sizes_to_dict + +.. autofunction:: finaletoolkit.utils.frag_generator + +.. autofunction:: finaletoolkit.utils.frag_array + +.. autofunction:: finaletoolkit.utils.low_quality_read_pairs + +.. autofunction:: finaletoolkit.utils.overlaps diff --git a/docs/_build/html/_sources/source/api_reference/genomeutils.rst.txt b/docs/_build/html/_sources/source/api_reference/genomeutils.rst.txt new file mode 100644 index 00000000..1891ef15 --- /dev/null +++ b/docs/_build/html/_sources/source/api_reference/genomeutils.rst.txt @@ -0,0 +1,13 @@ +Genome Utilities +====================================== +.. autoclass:: finaletoolkit.genome.GenomeGaps + :members: + +.. autoclass:: finaletoolkit.genome.ContigGaps + :members: + +.. autofunction:: finaletoolkit.genome.ucsc_hg19_gap_bed + +.. autofunction:: finaletoolkit.genome.b37_gap_bed + +.. autofunction:: finaletoolkit.genome.ucsc_hg38_gap_bed \ No newline at end of file diff --git a/docs/_build/html/_sources/source/api_reference/index.rst.txt b/docs/_build/html/_sources/source/api_reference/index.rst.txt new file mode 100644 index 00000000..e0e470b9 --- /dev/null +++ b/docs/_build/html/_sources/source/api_reference/index.rst.txt @@ -0,0 +1,15 @@ + +API +====== + +.. toctree:: + :maxdepth: 2 + + basicfeatures + wps + delfi + endmotifs + cleavageprofile + fragfile + genomeutils + diff --git a/docs/_build/html/_sources/source/api_reference/wps.rst.txt b/docs/_build/html/_sources/source/api_reference/wps.rst.txt new file mode 100644 index 00000000..e65070c8 --- /dev/null +++ b/docs/_build/html/_sources/source/api_reference/wps.rst.txt @@ -0,0 +1,10 @@ +Window Protection Score (WPS) +====================================== + +.. autofunction:: finaletoolkit.frag.wps + +.. autofunction:: finaletoolkit.frag.multi_wps + +.. autofunction:: finaletoolkit.frag.adjust_wps + + diff --git a/docs/_build/html/_sources/source/cli_reference/index.rst.txt b/docs/_build/html/_sources/source/cli_reference/index.rst.txt new file mode 100644 index 00000000..e8ce5b0a --- /dev/null +++ b/docs/_build/html/_sources/source/cli_reference/index.rst.txt @@ -0,0 +1,7 @@ + +CLI +========================================= + +.. argparse:: + :ref: finaletoolkit.cli.main_cli.main_cli_parser + :prog: finaletoolkit \ No newline at end of file diff --git a/docs/_build/html/_sources/source/index.rst.txt b/docs/_build/html/_sources/source/index.rst.txt new file mode 100644 index 00000000..46882573 --- /dev/null +++ b/docs/_build/html/_sources/source/index.rst.txt @@ -0,0 +1,9 @@ +FinaleToolkit Documentation +=========================== + +.. toctree:: + :maxdepth: 1 + + user_guide/index + cli_reference/index + api_reference/index \ No newline at end of file diff --git a/docs/_build/html/_sources/source/user_guide/features.rst.txt b/docs/_build/html/_sources/source/user_guide/features.rst.txt new file mode 100644 index 00000000..895819e7 --- /dev/null +++ b/docs/_build/html/_sources/source/user_guide/features.rst.txt @@ -0,0 +1,56 @@ + +Features +========================================= + +**FinaleToolkit** has support for the following cell-free DNA features: + + +----------------------- +Fragment Length +----------------------- + +**FinaleToolkit** can calculate the fragment length distribution and summary statistics of cell-free DNA fragments. + +----------------------- +Fragment Coverage +----------------------- + +**FinaleToolkit** can calculate fragment coverage (the number of reads mapped to a specific region of the genome). This coverage can be normalized by the total number of reads in the sample, or simply the raw value. + +--------------------------------- +Windowed Protection Score (WPS) +--------------------------------- + +**FinaleToolkit** can calculate the Windowed Protection Score (WPS), which is a metric designed by *Snyder et al. 2016*. + +It is used to quantify the level of protection or coverage of DNA fragments across a specific genomic region. It's calculated by assessing the number of DNA fragments that fully span a defined window (typically 120 base pairs) centered around a particular genomic coordinate, and then subtracting the number of fragments with an endpoint falling within the same window. This score is correlated with the location of nucleosomes and other genomic features, including transcriptional start sites (TSS) and DNase I hypersensitive sites (DHSs). + +----------------------- +DELFI +----------------------- + +**FinaleToolkit** can calculate DELFI, which is a metric designed by *Cristiano et al. 2019*. + +DELFI is a metric that was introduced to identify abnormalities in cfDNA from their fragmentation patterns. In the original paper, DELFI was used to categorize patients with cancer and the associated tumor tissues of origin. The associated DELFI score is the ratio between the GC%-corrected short fragment count and the GC%-corrected long fragment count. + +----------------------- +End Motifs +----------------------- + +**FinaleToolkit** can calculate the frequency of end-motif k-mers of cell-free DNA fragments. Since end motifs are specific sequences found at the ends of cfDNA fragments resulting from cleavage, they can be used to potentially detect patterns associated with certain conditions or diseases. + +----------------------------- +Motif Diversity Score (MDS) +----------------------------- + +**FinaleToolkit** can calculate the Motif Diversity Score (MDS), which is a metric designed by *Jiang et al. 2020*. + +The MDS is a metric that quantifies the diversity of cfDNA end motifs. It is the normalized Shannon entropy of the categorical distribution of all possible end-motif k-mers. + +----------------------- +Cleavage Profile +----------------------- + +**FinaleToolkit** can calculate the Cleavage Proportion, which is a metric designed by *Zhou et al. 2022*. + +The cleavage proportion is, by definition, the number of fragment ends that fall within a nucleotide location over the total number of fragment ends that overlap that nucleotide location. According to the authors, this metric shows a relationship to DNA methylation, specifically methylation at CpG sites. \ No newline at end of file diff --git a/docs/_build/html/_sources/source/user_guide/help.rst.txt b/docs/_build/html/_sources/source/user_guide/help.rst.txt new file mode 100644 index 00000000..4b992bab --- /dev/null +++ b/docs/_build/html/_sources/source/user_guide/help.rst.txt @@ -0,0 +1,12 @@ + +Help +========================================= + +If you think you’ve encountered a bug in **FinaleToolkit**, please report it on the `Github issue tracker `_ . To be useful, bug reports must include the following information: + +- A reproducible code example that demonstrates the problem +- The output that you are seeing (ex. the error message) +- A clear explanation of why you think something is wrong +- The specific version of **FinaleToolkit** that you are working with. + +If you’ve encountered an error, searching the specific text of the message before opening a new issue can often help you solve the problem quickly and avoid making a duplicate report. diff --git a/docs/_build/html/_sources/source/user_guide/index.rst.txt b/docs/_build/html/_sources/source/user_guide/index.rst.txt new file mode 100644 index 00000000..23b2ed9f --- /dev/null +++ b/docs/_build/html/_sources/source/user_guide/index.rst.txt @@ -0,0 +1,15 @@ + +User Guide +========================================= + +.. toctree:: + :maxdepth: 2 + + what + inputdata + features + installation + structure + intersectpolicy + quickstart + help \ No newline at end of file diff --git a/docs/_build/html/_sources/source/user_guide/inputdata.rst.txt b/docs/_build/html/_sources/source/user_guide/inputdata.rst.txt new file mode 100644 index 00000000..97e00f49 --- /dev/null +++ b/docs/_build/html/_sources/source/user_guide/inputdata.rst.txt @@ -0,0 +1,49 @@ + +Input Data +========================================= + +**FinaleToolkit** is compatible with almost any paired-end sequence data. + +SAM +^^^^^^^^^^^ + +A sequence alignment map (SAM) file is a human-readable file format that stores the results of sequence alignment. It contains information about the alignment of each read to the reference genome, as well as information about the read itself. + +BAM +^^^^^^^^^^^ + +A binary alignment file (BAM) provides the same information as a SAM file, but in a binary format. This can be useful for saving space on disk, but is not human-readable. + +**FinaleToolkit** requires that BAM files be BAI indexed. Therefore, you should have an associated ``.bam.bai`` file in the same directory of your input data. + +CRAM +^^^^^^^^^^^ + +A compressed read alignment map file is a compressed version of a SAM file. It is a binary file that is smaller than a BAM file, but still contains all of the same information. + +**FinaleToolkit** requires that CRAM files be CRAI indexed. Therefore, you should have an associated ``.cram.crai`` file in the same directory of your input data. + +Fragment File +^^^^^^^^^^^^^^^^ + +A fragment file (`.frag.gz`) file that is derived from information in a BAM file. A fragment file is a block-gzipped BED3+2 file (similar to a tab-separated value file) that contains the following columns (with one row entry for each fragment): ``chrom``, ``start``, ``stop``, ``mapq``, and ``strand``. + +Here, ``mapq`` is the mapping quality of the fragment, and ``strand`` is the strand of the fragment. The ``strand`` column can be either ``+`` or ``-``. + +**FinaleToolkit** requires that fragment files be Tabix indexed. Therefore, you should have an associated ``.frag.gz.tbi`` file in the same directory of your input data. + +For your reference, here is an example fragment file:: + + #chrom start stop mapq strand + chr1 10000 10050 60 + + chr1 10050 10100 60 - + chr1 10100 10150 60 + + chr1 10150 10200 60 - + chr1 10200 10250 60 + + chr1 10250 10300 60 - + chr1 10300 10350 60 + + chr1 10350 10400 60 - + chr1 10400 10450 60 + + chr1 10450 10500 60 - + +We encourage you to use our comprehensive database, **FinaleDB**, to access relevant fragment files. Learn more about **FinaleDB** `here `_ . \ No newline at end of file diff --git a/docs/_build/html/_sources/source/user_guide/installation.rst.txt b/docs/_build/html/_sources/source/user_guide/installation.rst.txt new file mode 100644 index 00000000..ab857b1f --- /dev/null +++ b/docs/_build/html/_sources/source/user_guide/installation.rst.txt @@ -0,0 +1,29 @@ +========================== +Installation +========================== + +----------------------- +Prerequisites +----------------------- +The only prerequisite for installing **FinaleToolkit** is a Python version that is greater than ``3.8``. + +---------------------- +Installation +---------------------- +**FinaleToolkit** can be installed with with ``pip``. + +Using ``pip``:: + + pip install finaletoolkit + +Also when using ``pip``, it’s good practice to use a virtual environment, like a ``conda`` environment. + +------------------ +Errors +------------------ + +If any errors arise during the installation, please fill out a detailed issue in the GitHub repository. + +If you are getting an ``ImportError`` on Mac when running **FinaleToolkit**, please run the following command in the terminal:: + + $ brew install curl \ No newline at end of file diff --git a/docs/_build/html/_sources/source/user_guide/intersectpolicy.rst.txt b/docs/_build/html/_sources/source/user_guide/intersectpolicy.rst.txt new file mode 100644 index 00000000..c0572cb4 --- /dev/null +++ b/docs/_build/html/_sources/source/user_guide/intersectpolicy.rst.txt @@ -0,0 +1,21 @@ +========================== +Intersect Policy +========================== + +When you give the ``Fragment Generator`` an interval of ``start`` and ``end`` to pull fragments from, which fragments will it return? + +What if a fragment has 1bp of overlap within the just on the edge of the window? Does it also return that fragment as well? + +These questions are answered by the ``intersect_policy`` argument, which shows up in many of the CLI and API commands. + +``intersect_policy`` can either be ``midpoint`` or ``any``. + +Midpoint +---------------- + +``midpoint``: The midpoint of the fragment determines whether the fragment will be returned or not. If the midpoint falls between ``start`` and ``end``, then it will be returned. Else, it will not. + +Any +------- + +``any``: As long as the fragment overlaps the interval between ``start`` and ``end`` in some capacity, then it will be returned. Else, it will not. \ No newline at end of file diff --git a/docs/_build/html/_sources/source/user_guide/quickstart.rst.txt b/docs/_build/html/_sources/source/user_guide/quickstart.rst.txt new file mode 100644 index 00000000..083554c9 --- /dev/null +++ b/docs/_build/html/_sources/source/user_guide/quickstart.rst.txt @@ -0,0 +1,29 @@ + +Quickstart +========================================= + +------------------------ +Getting Started +------------------------ + +If not to be integrated into a workflow, **FinaleToolkit** is intended to be run directly from a terminal interface. + +You can open the terminal and typing the following command:: + + $ finaletoolkit + +------------------------ +Importing Modules +------------------------ + +The **FinaleToolkit** package itself is divided by its API functions. + +You can load *all* of the functions by using the following command:: + + >>> import finaletoolkit as ft + +If you want to load a *specific* function, you can do so by using the following: + +Assuming we wanted to load the DELFI function:: + + >>> from finaletoolkit.frag import delfi diff --git a/docs/_build/html/_sources/source/user_guide/structure.rst.txt b/docs/_build/html/_sources/source/user_guide/structure.rst.txt new file mode 100644 index 00000000..615ea3dd --- /dev/null +++ b/docs/_build/html/_sources/source/user_guide/structure.rst.txt @@ -0,0 +1,12 @@ + +Structure +========================================= + +While not particularly pertinent to your usage, we include this page to give you a sense of what is going on under the hood of **FinaleToolkit**: + +At the heart of **FinaleToolkit** is the ``Fragment Generator``. This generator is designed to be as flexible as possible. It takes BAM, CRAM, SAM, and Fragment Files (among other arguments) and filters out the reads that are not of interest (e.x. unmapped reads, reads with low mapping quality, etc.). The fragments that make it through this filter are then passed to the relevant function to be processed. + +A rough outline of the structure of **FinaleToolkit** is therefore as follows: + +.. figure:: finaletoolkit_structure.png + :align: center \ No newline at end of file diff --git a/docs/_build/html/_sources/source/user_guide/what.rst.txt b/docs/_build/html/_sources/source/user_guide/what.rst.txt new file mode 100644 index 00000000..c233676f --- /dev/null +++ b/docs/_build/html/_sources/source/user_guide/what.rst.txt @@ -0,0 +1,11 @@ + +Introduction +========================================= + +Circulating cell-free DNA (cfDNA) refers to highly fragmented DNA that circulate in blood plasma. In healthy conditions, cfDNA mainly originates from hematopoietic cells through apoptosis or necrosis. In pathological states, additional cfDNA is released from the genomes of otherwise inaccessible tissues (e.g., from tumors in cancer). + +CfDNA fragmentation patterns have been established as a promising non-invasive biomarker for disease detection and monitoring. It has been shown that fragmentation pattern and cfDNA tissue-of-origin changes are associated with changes in different pathological statuses. + +Computational approaches can extract fragmentation features from cfDNA whole genome sequencing (WGS) data. However, various established cfDNA fragmentation features (ex. Windowed Protection Score (WPS), Motif Diversity Score (MDS), DELFI) have source code which is often absent, poorly documented, ad hoc, and unmaintained. + +**FinaleToolkit** offers a solution to this. It is a fast and comprehensive toolkit that provides a user-friendly interface to extract various cfDNA fragmentation features from fragmentation data. It is designed to be easy to use, well-documented, and maintained. \ No newline at end of file diff --git a/docs/_build/html/_static/basic.css b/docs/_build/html/_static/basic.css index 61572969..2af6139e 100644 --- a/docs/_build/html/_static/basic.css +++ b/docs/_build/html/_static/basic.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -237,6 +237,10 @@ a.headerlink { visibility: hidden; } +a:visited { + color: #551A8B; +} + h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, @@ -670,6 +674,16 @@ dd { margin-left: 30px; } +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + dl > dd:last-child, dl > dd:last-child > :last-child { margin-bottom: 0; @@ -738,6 +752,14 @@ abbr, acronym { cursor: help; } +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + /* -- code displays --------------------------------------------------------- */ pre { diff --git a/docs/_build/html/_static/doctools.js b/docs/_build/html/_static/doctools.js index d06a71d7..4d67807d 100644 --- a/docs/_build/html/_static/doctools.js +++ b/docs/_build/html/_static/doctools.js @@ -4,7 +4,7 @@ * * Base JavaScript utilities for all Sphinx HTML documentation. * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/docs/_build/html/_static/documentation_options.js b/docs/_build/html/_static/documentation_options.js index b57ae3b8..7e4c114f 100644 --- a/docs/_build/html/_static/documentation_options.js +++ b/docs/_build/html/_static/documentation_options.js @@ -1,5 +1,4 @@ -var DOCUMENTATION_OPTIONS = { - URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), +const DOCUMENTATION_OPTIONS = { VERSION: '', LANGUAGE: 'en', COLLAPSE_INDEX: false, diff --git a/docs/_build/html/_static/language_data.js b/docs/_build/html/_static/language_data.js index 250f5665..367b8ed8 100644 --- a/docs/_build/html/_static/language_data.js +++ b/docs/_build/html/_static/language_data.js @@ -5,7 +5,7 @@ * This script contains the language-specific data used by searchtools.js, * namely the list of stopwords, stemmer, scorer and splitter. * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -13,7 +13,7 @@ var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; -/* Non-minified version is copied as a separate JS file, is available */ +/* Non-minified version is copied as a separate JS file, if available */ /** * Porter Stemmer diff --git a/docs/_build/html/_static/searchtools.js b/docs/_build/html/_static/searchtools.js index 97d56a74..92da3f8b 100644 --- a/docs/_build/html/_static/searchtools.js +++ b/docs/_build/html/_static/searchtools.js @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilities for the full-text search. * - * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @@ -57,12 +57,12 @@ const _removeChildren = (element) => { const _escapeRegExp = (string) => string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string -const _displayItem = (item, searchTerms) => { +const _displayItem = (item, searchTerms, highlightTerms) => { const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; - const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT; const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; const [docName, title, anchor, descr, score, _filename] = item; @@ -75,28 +75,35 @@ const _displayItem = (item, searchTerms) => { if (dirname.match(/\/index\/$/)) dirname = dirname.substring(0, dirname.length - 6); else if (dirname === "index/") dirname = ""; - requestUrl = docUrlRoot + dirname; + requestUrl = contentRoot + dirname; linkUrl = requestUrl; } else { // normal html builders - requestUrl = docUrlRoot + docName + docFileSuffix; + requestUrl = contentRoot + docName + docFileSuffix; linkUrl = docName + docLinkSuffix; } let linkEl = listItem.appendChild(document.createElement("a")); linkEl.href = linkUrl + anchor; linkEl.dataset.score = score; linkEl.innerHTML = title; - if (descr) + if (descr) { listItem.appendChild(document.createElement("span")).innerHTML = " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } else if (showSearchSummary) fetch(requestUrl) .then((responseData) => responseData.text()) .then((data) => { if (data) listItem.appendChild( - Search.makeSearchSummary(data, searchTerms) + Search.makeSearchSummary(data, searchTerms, anchor) ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); }); Search.output.appendChild(listItem); }; @@ -109,26 +116,43 @@ const _finishSearch = (resultCount) => { ); else Search.status.innerText = _( - `Search finished, found ${resultCount} page(s) matching the search query.` - ); + "Search finished, found ${resultCount} page(s) matching the search query." + ).replace('${resultCount}', resultCount); }; const _displayNextItem = ( results, resultCount, - searchTerms + searchTerms, + highlightTerms, ) => { // results left, load the summary and display it // this is intended to be dynamic (don't sub resultsCount) if (results.length) { - _displayItem(results.pop(), searchTerms); + _displayItem(results.pop(), searchTerms, highlightTerms); setTimeout( - () => _displayNextItem(results, resultCount, searchTerms), + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), 5 ); } // search finished, update title and status message else _finishSearch(resultCount); }; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; /** * Default splitQuery function. Can be overridden in ``sphinx.search`` with a @@ -152,13 +176,26 @@ const Search = { _queued_query: null, _pulse_status: -1, - htmlToText: (htmlString) => { + htmlToText: (htmlString, anchor) => { const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); - htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + for (const removalQuery of [".headerlinks", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` + ); + } + + // if anchor not specified or not found, fall back to main content const docContent = htmlElement.querySelector('[role="main"]'); - if (docContent !== undefined) return docContent.textContent; + if (docContent) return docContent.textContent; + console.warn( - "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." ); return ""; }, @@ -231,16 +268,7 @@ const Search = { else Search.deferQuery(query); }, - /** - * execute search (requires search index to be loaded) - */ - query: (query) => { - const filenames = Search._index.filenames; - const docNames = Search._index.docnames; - const titles = Search._index.titles; - const allTitles = Search._index.alltitles; - const indexEntries = Search._index.indexentries; - + _parseQuery: (query) => { // stem the search terms and add them to the correct list const stemmer = new Stemmer(); const searchTerms = new Set(); @@ -276,16 +304,32 @@ const Search = { // console.info("required: ", [...searchTerms]); // console.info("excluded: ", [...excludedTerms]); - // array of [docname, title, anchor, descr, score, filename] - let results = []; + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename]. + const normalResults = []; + const nonMainIndexResults = []; + _removeChildren(document.getElementById("search-progress")); - const queryLower = query.toLowerCase(); + const queryLower = query.toLowerCase().trim(); for (const [title, foundTitles] of Object.entries(allTitles)) { - if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { + if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { for (const [file, id] of foundTitles) { let score = Math.round(100 * queryLower.length / title.length) - results.push([ + normalResults.push([ docNames[file], titles[file] !== title ? `${titles[file]} > ${title}` : title, id !== null ? "#" + id : "", @@ -300,46 +344,47 @@ const Search = { // search for explicit entries in index directives for (const [entry, foundEntries] of Object.entries(indexEntries)) { if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { - for (const [file, id] of foundEntries) { - let score = Math.round(100 * queryLower.length / entry.length) - results.push([ + for (const [file, id, isMain] of foundEntries) { + const score = Math.round(100 * queryLower.length / entry.length); + const result = [ docNames[file], titles[file], id ? "#" + id : "", null, score, filenames[file], - ]); + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } } } } // lookup as object objectTerms.forEach((term) => - results.push(...Search.performObjectSearch(term, objectTerms)) + normalResults.push(...Search.performObjectSearch(term, objectTerms)) ); // lookup as search terms in fulltext - results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); // let the scorer override scores with a custom scoring function - if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); - - // now sort the results by score (in opposite order of appearance, since the - // display function below uses pop() to retrieve items) and then - // alphabetically - results.sort((a, b) => { - const leftScore = a[4]; - const rightScore = b[4]; - if (leftScore === rightScore) { - // same score: sort alphabetically - const leftTitle = a[1].toLowerCase(); - const rightTitle = b[1].toLowerCase(); - if (leftTitle === rightTitle) return 0; - return leftTitle > rightTitle ? -1 : 1; // inverted is intentional - } - return leftScore > rightScore ? 1 : -1; - }); + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; // remove duplicate search results // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept @@ -353,14 +398,19 @@ const Search = { return acc; }, []); - results = results.reverse(); + return results.reverse(); + }, + + query: (query) => { + const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); + const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); // for debugging //Search.lastresults = results.slice(); // a copy // console.info("search results:", Search.lastresults); // print the results - _displayNextItem(results, results.length, searchTerms); + _displayNextItem(results, results.length, searchTerms, highlightTerms); }, /** @@ -458,14 +508,18 @@ const Search = { // add support for partial matches if (word.length > 2) { const escapedWord = _escapeRegExp(word); - Object.keys(terms).forEach((term) => { - if (term.match(escapedWord) && !terms[word]) - arr.push({ files: terms[term], score: Scorer.partialTerm }); - }); - Object.keys(titleTerms).forEach((term) => { - if (term.match(escapedWord) && !titleTerms[word]) - arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); - }); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } } // no match but word was a required one @@ -488,9 +542,8 @@ const Search = { // create the mapping files.forEach((file) => { - if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) - fileMap.get(file).push(word); - else fileMap.set(file, [word]); + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); }); }); @@ -541,8 +594,8 @@ const Search = { * search summary for a given text. keywords is a list * of stemmed words. */ - makeSearchSummary: (htmlText, keywords) => { - const text = Search.htmlToText(htmlText); + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); if (text === "") return null; const textLower = text.toLowerCase(); diff --git a/docs/_build/html/_static/sphinx_highlight.js b/docs/_build/html/_static/sphinx_highlight.js index aae669d7..8a96c69a 100644 --- a/docs/_build/html/_static/sphinx_highlight.js +++ b/docs/_build/html/_static/sphinx_highlight.js @@ -29,14 +29,19 @@ const _highlight = (node, addItems, text, className) => { } span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); parent.insertBefore( span, parent.insertBefore( - document.createTextNode(val.substr(pos + text.length)), + rest, node.nextSibling ) ); node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); if (isInSVG) { const rect = document.createElementNS( @@ -140,5 +145,10 @@ const SphinxHighlight = { }, }; -_ready(SphinxHighlight.highlightSearchWords); -_ready(SphinxHighlight.initEscapeListener); +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/docs/_build/html/documentation/api_reference/basicfeatures.html b/docs/_build/html/documentation/api_reference/basicfeatures.html new file mode 100644 index 00000000..c0e81a1b --- /dev/null +++ b/docs/_build/html/documentation/api_reference/basicfeatures.html @@ -0,0 +1,523 @@ + + + + + + + + + + + Basic Features — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Basic Features#

    +
    +
    +finaletoolkit.frag.coverage(input_file: str | TabixFile | AlignmentFile | Path, interval_file: str, output_file: str, scale_factor: float = 1000000.0, intersect_policy: str = 'midpoint', quality_threshold: int = 30, workers: int = 1, verbose: bool | int = False) Iterable[tuple[str, int, int, str, float]]#
    +

    Return estimated fragment coverage over intervals specified in +intervals. Fragments are read from input_file which may be +a SAM, BAM, CRAM, or Frag.gz file. Uses an algorithm where the midpoints of +fragments are calculated and coverage is tabulated from the +midpoints that fall into the specified region. Not suitable for +fragments of size approaching interval size.

    +
    +
    Parameters:
    +
      +
    • input_file (str or pysam.AlignmentFile) – SAM, BAM, CRAM, or Frag.gz file containing paired-end fragment +reads or its path. AlignmentFile must be opened in read mode.

    • +
    • interval_file (str) – BED4 file containing intervals over which to generate coverage +statistics.

    • +
    • output_file (string, optional) – Path for bed file to print coverages to. If output_file = -, +results will be printed to stdout.

    • +
    • scale_factor (int, optional) – Amount to multiply coverages by. Default is 10^6.

    • +
    • intersect_policy (str, optional) – Specifies how to determine whether fragments are in interval. +‘midpoint’ (default) calculates the central coordinate of each fragment +and only selects the fragment if the midpoint is in the +interval. ‘any’ includes fragments with any overlap with the +interval.

    • +
    • quality_threshold (int, optional) – Minimum MAPQ. Default is 30.

    • +
    • workers (int, optional) – Number of subprocesses to spawn. Increases speed at the expense +of memory.

    • +
    • verbose (int or bool, optional)

    • +
    +
    +
    Returns:
    +

    coverages – Fragment coverages over intervals.

    +
    +
    Return type:
    +

    Iterable[tuple[str, int, int, str, float]]

    +
    +
    +
    + +
    +
    +finaletoolkit.frag.frag_length(input_file: str | AlignmentFile | TabixFile, contig: str | None = None, start: int | None = None, stop: int | None = None, intersect_policy: str = 'midpoint', output_file: str | None = None, quality_threshold: int = 30, verbose: bool = False) ndarray#
    +

    Return np.ndarray containing lengths of fragments in input_file +that are above the quality threshold and are proper-paired reads.

    +
    +
    Parameters:
    +
      +
    • input_file (str or pysam.AlignmentFile) – BAM, SAM, or CRAM file containing paired-end fragment reads or +its path. AlignmentFile must be opened in read mode.

    • +
    • contig (string, optional) – Contig or chromosome to get fragments from

    • +
    • start (int, optional) – 0-based left-most coordinate of interval

    • +
    • stop (int, optional) – 1-based right-most coordinate of interval

    • +
    • intersect_policy (str, optional) – Specifies what policy is used to include fragments in the +given interval. Default is “midpoint”. Policies include: +- midpoint: the average of end coordinates of a fragment lies +in the interval. +- any: any part of the fragment is in the interval.

    • +
    • output_file (string, optional)

    • +
    • quality_threshold (int, optional)

    • +
    • verbose (bool, optional)

    • +
    +
    +
    Returns:
    +

    lengthsndarray of fragment lengths from file and contig if +specified.

    +
    +
    Return type:
    +

    numpy.ndarray

    +
    +
    +
    + +
    +
    +finaletoolkit.frag.frag_length_bins(input_file: str | AlignmentFile, contig: str | None = None, start: int | None = None, stop: int | None = None, bin_size: int | None = None, output_file: str | None = None, contig_by_contig: bool = False, histogram: bool = False, intersect_policy: str = 'midpoint', quality_threshold: int = 30, verbose: bool | int = False) tuple[ndarray, ndarray]#
    +

    Takes input_file, computes frag lengths of fragments and returns +two arrays containing bins and counts by size. Optionally prints +data to output as a tab delimited table or histogram.

    +
    +
    Parameters:
    +
      +
    • input_file (str or AlignmentFile)

    • +
    • contig (str, optional)

    • +
    • start (int, optional)

    • +
    • stop (int, optional)

    • +
    • bin_size (int, optional)

    • +
    • output_file (str, optional)

    • +
    • contig_by_contig (bool, optional)

    • +
    • histogram (bool, optional)

    • +
    • intersect_policy (str, optional) – Specifies what policy is used to include fragments in the +given interval. Default is “midpoint”. Policies include: +- midpoint: the average of end coordinates of a fragment lies +in the interval. +- any: any part of the fragment is in the interval.

    • +
    • workers (int, optional)

    • +
    +
    +
    Returns:
    +

      +
    • bins (ndarray)

    • +
    • counts (ndarray)

    • +
    +

    +
    +
    +
    + +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/api_reference/cleavageprofile.html b/docs/_build/html/documentation/api_reference/cleavageprofile.html new file mode 100644 index 00000000..6782f96f --- /dev/null +++ b/docs/_build/html/documentation/api_reference/cleavageprofile.html @@ -0,0 +1,444 @@ + + + + + + + + + + + Cleavage Profile — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Cleavage Profile#

    +
    +
    +finaletoolkit.frag.cleavage_profile(input_file: str, chrom_size: int, contig: str, start: int, stop: int, left: int = 0, right: int = 0, fraction_low: int = 1, fraction_high: int = 10000000, quality_threshold: int = 30, verbose: bool | int = 0) ndarray#
    +

    Cleavage profile calculated over a single interval.

    +
    +
    Parameters:
    +
      +
    • input_file (str) – SAM, BAM, CRAM, or FRAG file with fragment information.

    • +
    • chrom_size (int) – length of contig.

    • +
    • contig (str) – Chromosome or contig

    • +
    • start (int) – 0-based start coordinate

    • +
    • stop (int) – 1-based end coordinate

    • +
    • left (int) – Amount to subtract from start coordinate. Useful if only given +coordinates of CpG.

    • +
    • right (int) – Amount to add to stop coordinate.

    • +
    • fraction_low (int) – Minimum fragment size to include

    • +
    • fraction_high (int) – Maximum fragment size to include

    • +
    • quality_threshold (int) – Minimum MAPQ

    • +
    • verbose (bool or in)

    • +
    +
    +
    Returns:
    +

    cleavage_proportions – Array of cleavage proportions over given interval.

    +
    +
    Return type:
    +

    NDArray

    +
    +
    +
    + +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/api_reference/delfi.html b/docs/_build/html/documentation/api_reference/delfi.html new file mode 100644 index 00000000..c35c4ffd --- /dev/null +++ b/docs/_build/html/documentation/api_reference/delfi.html @@ -0,0 +1,460 @@ + + + + + + + + + + + DELFI — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    DELFI#

    +
    +
    +finaletoolkit.frag.delfi(input_file: str, autosomes: str, bins_file: str, reference_file: str, blacklist_file: str = None, gap_file: Union(str, GenomeGaps) = None, output_file: str = None, gc_correct: bool = True, merge_bins: bool = True, window_size: int = 5000000, subsample_coverage: float = 2, quality_threshold: int = 30, workers: int = 1, preprocessing: bool = True, verbose: int | bool = False) pandas.DataFrame#
    +

    A function that replicates the methodology of Christiano et al +(2019).

    +
    +
    Parameters:
    +
      +
    • input_file (str) – Path string pointing to a bam file containing PE +fragment reads.

    • +
    • autosomes (str) – Path string to a .genome file containing only autosomal +chromosomes

    • +
    • bins_file (str) – Path string to a BED file containing 100kb bins for reference +genome of choice. Cristiano et al uses

    • +
    • reference_file (str) – Path string to .2bit file.

    • +
    • blacklist_file (str) – Path string to BED file containing genome blacklist.

    • +
    • gap_file (str) – Path string to a BED4+ file where each interval is a centromere +or telomere. A bed file can be used only if the fourth field +for each entry corresponding to a telomere or centromere is +labled “telomere” or “centromere, respectively.

    • +
    • output_file (str, optional) – Path to output tsv.

    • +
    • window_size (int) – Size of non-overlapping windows to cover genome. Default is +5 megabases.

    • +
    • subsample_coverage (int, optional) – The depth at which to subsample the input_bam. Default is 2.

    • +
    • workers (int, optional) – Number of worker processes to use. Default is 1.

    • +
    • preprocessing (bool, optional) – Christiano et al (2019)

    • +
    • verbose (int or bool, optional) – Determines how many print statements and loading bars appear in +stdout. Default is False.

    • +
    +
    +
    +
    + +
    +
    +finaletoolkit.frag.delfi_gc_correct(windows: DataFrame, alpha: float = 0.75, it: int = 8, verbose: bool = False)#
    +

    Helper function that takes window data and performs GC adjustment.

    +
    + +
    +
    +finaletoolkit.frag.delfi_merge_bins(hundred_kb_bins: DataFrame, gc_corrected: bool = True, add_chr: bool = False, verbose: bool = False)#
    +
    + +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/api_reference/endmotifs.html b/docs/_build/html/documentation/api_reference/endmotifs.html new file mode 100644 index 00000000..c79b4be3 --- /dev/null +++ b/docs/_build/html/documentation/api_reference/endmotifs.html @@ -0,0 +1,690 @@ + + + + + + + + + + + End-Motifs — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    End-Motifs#

    +
    +
    +class finaletoolkit.frag.EndMotifFreqs(kmer_frequencies: Iterable[tuple[str, float]], k: int, quality_threshold: int = 20)#
    +

    Class that stores frequencies of end-motif k-mer frequencies and +contains methods to manipulate this data.

    +
    +
    Parameters:
    +
      +
    • kmer_frequencies (Iterable) – A Iterable of tuples, each containing a str representing a k-mer +and a float representing its frequency

    • +
    • k (int) – Size of k-mers

    • +
    • quality_threshold (int, optional) – Minimum mapping quality used. Default is 30.

    • +
    +
    +
    +
    +
    +classmethod from_file(file_path: str | Path, quality_threshold: int, sep: str = '\t', header: int = 0) EndMotifFreqs#
    +

    Reads kmer frequency from a two-column tab-delimited file.

    +
    +
    Parameters:
    +
      +
    • file_path (str) – Path string containing path to file.

    • +
    • sep (str, optional) – Delimiter used in file.

    • +
    • header (int, optional) – Number of lines to ignore at the head of the file.

    • +
    +
    +
    Returns:
    +

    kmer_freqs

    +
    +
    Return type:
    +

    EndMotifFreqs

    +
    +
    +
    + +
    +
    +motif_diversity_score() float#
    +

    Calculates a motif diversity score (MDS) using normalized +Shannon entropy as described by Jiang et al (2020). This +function is generalized for any k instead of just 4-mers.

    +
    + +
    +
    +to_tsv(output_file: str | Path, sep: str = '\t')#
    +

    Prints k-mer frequencies to a tsv

    +
    + +
    + +
    +
    +class finaletoolkit.frag.EndMotifsIntervals(intervals: Iterable[tuple[tuple, dict]], k: int, quality_threshold: int = 20)#
    +

    Class that stores frequencies of end-motif k-mers over +user-specified intervals and contains methods to manipulate this +data.

    +
    +
    Parameters:
    +
      +
    • intervals (Iterable) – A collection of tuples, each containing a tuple representing +a genomic interval (chrom, 0-based start, 1-based stop) and a +dict that maps kmers to frequencies in the interval.

    • +
    • k (int) – Size of k-mers

    • +
    • quality_threshold (int, optional) – Minimum mapping quality used. Default is 30.

    • +
    +
    +
    +
    +
    +freq(kmer: str) list[tuple[str, int, int, float]]#
    +

    Returns a list of intervals and associated frquency for given +kmer. Results are in the form (chrom, 0-based start, 1-based +stop, frequency).

    +
    + +
    +
    +classmethod from_file(file_path: str, quality_threshold: int, sep: str = ',') EndMotifFreqs#
    +

    Reads kmer frequency from a tab-delimited file. Expected columns +are contig, start, stop, name, count, *kmers. Because +exporting to file includes an option to turn counts to a fraction, +this doesn’t perfectly correspond to replicating the other file.

    +
    +
    Parameters:
    +
      +
    • file_path (str) – Path string containing path to file.

    • +
    • quality_threshold (int) – MAPQ filter used. Only used for some calculations.

    • +
    • sep (str, optional) – Delimiter used in file.

    • +
    +
    +
    Returns:
    +

    kmer_freqs

    +
    +
    Return type:
    +

    EndMotifFreqs

    +
    +
    +
    + +
    +
    +mds_bed(output_file: str | Path, sep: str = '\t')#
    +

    Writes MDS for each interval to a bed/bedgraph file.

    +
    + +
    +
    +motif_diversity_score() list[tuple[tuple, float]]#
    +

    Calculates a motif diversity score (MDS) for each interval using +normalized Shannon entropy as described by Jiang et al (2020). This +function is generalized for any k instead of just 4-mers.

    +
    + +
    +
    +to_bed(kmer: str, output_file: str | Path, calc_freq: bool = True, sep: str = '\t')#
    +

    Take frequency of specified kmer and writes to BED.

    +
    +
    Parameters:
    +
      +
    • output_file (str) – File to write frequencies to.

    • +
    • calc_freq (bool, optional) – Calculates frequency of motifs if true. Otherwise, writes counts +for each motif. Default is true.

    • +
    • sep (str, optional) – Separator for table. Tab-separated by default.

    • +
    +
    +
    +
    + +
    +
    +to_bedgraph(kmer: str, output_file: str | Path, calc_freq: bool = True, sep: str = '\t')#
    +

    Take frequency of specified kmer and writes to bedgraph.

    +
    +
    Parameters:
    +
      +
    • output_file (str) – File to write frequencies to.

    • +
    • calc_freq (bool, optional) – Calculates frequency of motifs if true. Otherwise, writes counts +for each motif. Default is true.

    • +
    • sep (str, optional) – Separator for table. Tab-separated by default.

    • +
    +
    +
    +
    + +
    +
    +to_tsv(output_file: str | Path, calc_freq: bool = True, sep: str = '\t')#
    +

    Writes all intervals and associated frquencies to file. Columns +are contig, start, stop, name, count, *kmers.

    +
    +
    Parameters:
    +
      +
    • output_file (str) – File to write frequencies to.

    • +
    • calc_freq (bool, optional) – Calculates frequency of motifs if true. Otherwise, writes counts +for each motif. Default is true.

    • +
    • sep (str, optional) – Separator for table. Tab-separated by default.

    • +
    +
    +
    +
    + +
    + +
    +
    +finaletoolkit.frag.region_end_motifs(input_file: str, contig: str, start: int, stop: int, refseq_file: str | Path, k: int = 4, fraction_low: int = 10, fraction_high: int = 600, both_strands: bool = True, output_file: None | str = None, quality_threshold: int = 20, verbose: bool | int = False) dict#
    +

    Function that reads fragments in the specified region from a BAM, +SAM, or tabix indexed file and returns the 5’ k-mer (default is +4-mer) end motif counts as a dictionary. This function +reproduces the methodology of Zhou et al (2023).

    +
    +
    Parameters:
    +
      +
    • input_file (str) – Path of SAM, BAM, CRAM, or Frag.gz containing pair-end reads.

    • +
    • contig (str) – Name of contig or chromosome for region.

    • +
    • start (int) – 0-based start coordinate.

    • +
    • stop (int) – 1-based end coordinate.

    • +
    • refseq_file (str or Path) – 2bit file with reference sequence input_file was aligned to.

    • +
    • k (int, optional) – Length of end motif kmer. Default is 4.

    • +
    • fraction_low (int, optional) – Minimum fragment length.

    • +
    • fraction_high (int, optional) – Maximum fragment length.

    • +
    • both_strands (bool, optional) – Choose whether to use forward 5’ ends only or use 5’ ends for +both ends of PE reads.

    • +
    • output_file (None or str, optional)

    • +
    • quality_threshold (int, optional)

    • +
    • verbose (bool or int, optional)

    • +
    +
    +
    Returns:
    +

    end_motif_freq

    +
    +
    Return type:
    +

    dict

    +
    +
    +
    + +
    +
    +finaletoolkit.frag.end_motifs(input_file: str, refseq_file: str | Path, k: int = 4, fraction_low: int = 10, fraction_high: int = 600, both_strands: bool = False, output_file: None | str = None, quality_threshold: int = 30, workers: int = 1, verbose: bool | int = False) EndMotifFreqs#
    +

    Function that reads fragments from a BAM, SAM, or tabix indexed +file and returns the 5’ k-mer (default is 4-mer) end motif +frequencies as a dictionary. Optionally writes data to a tsv. This +function reproduces the methodology of Zhou et al (2023).

    +
    +
    Parameters:
    +
      +
    • input_file (str) – SAM, BAM, CRAM, or Frag.gz file with paired-end reads.

    • +
    • refseq_file (str or Path) – 2bit file with sequence of reference genome input_file is +aligned to.

    • +
    • k (int, optional) – Length of end motif kmer. Default is 4.

    • +
    • output_file (None or str, optional) – File path to write results to. Either tsv or csv.

    • +
    • quality_threshold (int, optional) – Minimum MAPQ to filter.

    • +
    • workers (int, optional) – Number of worker processes.

    • +
    • verbose (bool or int, optional)

    • +
    +
    +
    Returns:
    +

    end_motif_freq

    +
    +
    Return type:
    +

    EndMotifFreqs

    +
    +
    +
    + +
    +
    +finaletoolkit.frag.interval_end_motifs(input_file: str, refseq_file: str | Path, intervals: str | Iterable[tuple[str, int, int, str]], k: int = 4, fraction_low: int = 10, fraction_high: int = 600, both_strands: bool = True, output_file: None | str = None, quality_threshold: int = 30, workers: int = 1, verbose: bool | int = False) EndMotifsIntervals#
    +

    Function that reads fragments from a BAM, SAM, or tabix indexed +file and user-specified intervals and returns the 5’ k-mer +(default is 4-mer) end motif. Optionally writes data to a tsv.

    +
    +
    Parameters:
    +
      +
    • input_file (str) – Path of SAM, BAM, CRAM, or Frag.gz containing pair-end reads.

    • +
    • refseq_file (str or Path) – Path of 2bit file for reference genome that reads are aligned to.

    • +
    • intervals (str or tuple) – Path of BED file containing intervals or list of tuples +(chrom, start, stop, name).

    • +
    • k (int, optional) – Length of end motif kmer. Default is 4.

    • +
    • output_file (None or str, optional) – File path to write results to. Either tsv or csv.

    • +
    • quality_threshold (int, optional) – Minimum MAPQ to filter.

    • +
    • workers (int, optional) – Number of worker processes.

    • +
    • verbose (bool or int, optional)

    • +
    +
    +
    Returns:
    +

    end_motif_freq

    +
    +
    Return type:
    +

    EndMotifIntervals

    +
    +
    +
    + +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + + + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/api_reference/fragfile.html b/docs/_build/html/documentation/api_reference/fragfile.html new file mode 100644 index 00000000..7bbe2827 --- /dev/null +++ b/docs/_build/html/documentation/api_reference/fragfile.html @@ -0,0 +1,635 @@ + + + + + + + + + + + Frag File Utilities — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Frag File Utilities#

    +
    +
    +finaletoolkit.utils.filter_bam(input_file: str, region_file: str | None = None, output_file: str | None = None, max_length: int | None = None, min_length: int | None = None, quality_threshold: int = 30, workers: int = 1, verbose: bool = False)#
    +

    Accepts the path to a BAM file and creates a bam file where all +reads are read1 in a proper pair, exceed the specified quality +threshold, do not intersect a region in the given blacklist +file, and intersects with a region in the region bed.

    +
    +
    Parameters:
    +
      +
    • input_bam (str) – Path string or AlignmentFile pointing to the BAM file to be +filtered.

    • +
    • region_file (str, option)

    • +
    • output_file (str, optional)

    • +
    • min_length (int, optional)

    • +
    • max_length (int, optional)

    • +
    • quality_threshold (int, optional)

    • +
    • workers (int, optional)

    • +
    • verbose (bool, optional)

    • +
    +
    +
    Returns:
    +

    output_file

    +
    +
    Return type:
    +

    str

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.agg_bw(input_file: str, interval_file: str, output_file: str, median_window_size: int = 0, mean: bool = False, strand_location: int = 5, verbose: bool = False)#
    +

    Takes a BigWig and an interval BED and +aggregates signal along the intervals.

    +

    For aggregating WPS signals, note that the median filter trims the +ends of each interval by half of the window size of the filter +while adjusting data. There are two way this can be approached in +aggregation:

    +

    1. supply an interval file containing smaller intervals. e.g. if +you used 5kb intervals for WPS and used a median filter window +of 1kb, supply a BED file with 4kb windows to this function.

    +

    2. provide the size of the median filter window in +median_window_size along with the original intervals. e.g if +5kb intervals were used for WPS and a 1kb median filter window +was used, supply the 5kb bed file and median filter window size +to this function.

    +

    Do not do both of these at once.

    +
    +
    Parameters:
    +
      +
    • input_file (str)

    • +
    • interval_file (str)

    • +
    • output_file (str)

    • +
    • median_window_size (int, optional) – default is 0

    • +
    • mean (bool) – use mean instead

    • +
    • strand_location (int) – which column (starting at 0) of the interval file contains the +strand. Default is 5.

    • +
    • verbose (int or bool, optional) – default is False

    • +
    +
    +
    Returns:
    +

    agg_scores

    +
    +
    Return type:
    +

    NDArray

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.chrom_sizes_to_list(chrom_sizes_file: str | Path) list[tuple[str][int]]#
    +

    Reads chromosome names and sizes from a CHROMSIZE file into a list.

    +
    +
    Parameters:
    +

    chrom_sizes_file (str or Path) – Tab-delimited file with column for chrom names and column for +chrom sizes.

    +
    +
    Returns:
    +

    chrom names and sizes.

    +
    +
    Return type:
    +

    list of string, int tuples

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.chrom_sizes_to_dict(chrom_sizes_file: str | Path) list[tuple[str][int]]#
    +

    Reads chromosome names and sizes from a CHROMSIZE file into a dict.

    +
    +
    Parameters:
    +

    chrom_sizes_file (str or Path) – Tab-delimited file with column for chrom names and column for +chrom sizes.

    +
    +
    Returns:
    +

    Chrom names are keys and values are int chrom sizes.

    +
    +
    Return type:
    +

    dict

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.frag_generator(input_file: str | pysam.AlignmentFile | pysam.TabixFile | Path, contig: str, quality_threshold: int = 30, start: int = None, stop: int = None, fraction_low: int = 120, fraction_high: int = 180, intersect_policy: str = 'midpoint', verbose: bool = False) Generator[tuple]#
    +

    Reads from BAM, SAM, or BED file and returns tuples containing +contig (chromosome), start, stop (end), mapq, and strand for each fragment. +Optionally may filter for mapq, size, and intersection with a region.

    +
    +
    Parameters:
    +
      +
    • input_file (str or AlignmentFile)

    • +
    • contig (str)

    • +
    • quality_threshold (int, optional)

    • +
    • start (int, optional)

    • +
    • stop (int, optional)

    • +
    • fraction_low (int, optional) – Specifies lowest fragment length included in array. Default is +120, equivalent to long fraction.

    • +
    • fraction_high (int, optional) – Specifies highest fragment length included in array. Default is +120, equivalent to long fraction.

    • +
    • intersect_policy (str, optional) – Specifies what policy is used to include fragments in the +given interval. Default is “midpoint”. Policies include: +- midpoint: the average of end coordinates of a fragment lies +in the interval. +- any: any part of the fragment is in the interval.

    • +
    • verbose (bool, optional)

    • +
    +
    +
    Returns:
    +

    frag_ends – Generator that yields tuples containing the region covered by +each fragment in input_file.

    +
    +
    Return type:
    +

    Generator

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.frag_array(input_file: str | AlignmentFile | TabixFile | Path, contig: str, quality_threshold: int = 30, start: int | None = None, stop: int | None = None, fraction_low: int = 120, fraction_high: int = 180, intersect_policy: str = 'midpoint', verbose: bool = False) ndarray[Any, dtype[_ScalarType_co]]#
    +

    Reads from BAM, SAM, or BED file and returns a three column matrix +with fragment start and stop positions and strand.

    +
    +
    Parameters:
    +
      +
    • input_file (str or AlignmentFile)

    • +
    • contig (str)

    • +
    • quality_threshold (int, optional)

    • +
    • start (int, optional)

    • +
    • stop (int, optional)

    • +
    • fraction_low (int, optional) – Specifies lowest fragment length included in array. Default is +120, equivalent to long fraction.

    • +
    • fraction_high (int, optional) – Specifies highest fragment length included in array. Default is +120, equivalent to long fraction. +intersect_policy : str, optional +Specifies what policy is used to include fragments in the +given interval. Default is “midpoint”. Policies include: +- midpoint: the average of end coordinates of a fragment lies +in the interval. +- any: any part of the fragment is in the interval.

    • +
    • verbose (bool, optional)

    • +
    +
    +
    Returns:
    +

    frag_ends – ‘NDArray’ with shape (n, 3) where column 1 contains fragment +start position and column 2 contains fragment stop position, and +column3 is 1 of on the + strand and is 0 if on the - strand. +If no fragments exist in the specified minimum-maximum interval, +the returned ‘ndarray’ will have a shape of (0, 3)

    +
    +
    Return type:
    +

    NDArray

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.low_quality_read_pairs(read, min_mapq=30)#
    +

    Return True if the sequenced read described in read is not a +properly paired read with a Phred score exceeding min_mapq. Based +on epifluidlab/cofragr +mmary_in_intervals.py

    +

    Equivalent to -F 3852 -f 3

    +
    +
    Parameters:
    +
      +
    • read (pysam.AlignedSegment) – Sequenced read to check for quality, perfect pairing and if it +is mapped.

    • +
    • min_mapq (int, optional) – Minimum Phred score for map quality of read. Defaults to 30.

    • +
    +
    +
    Returns:
    +

    is_low_quality – True if read is low quality, unmapped, not properly paired.

    +
    +
    Return type:
    +

    bool

    +
    +
    +
    + +
    +
    +finaletoolkit.utils.overlaps(contigs_1: ndarray[Any, dtype[_ScalarType_co]], starts_1: ndarray[Any, dtype[_ScalarType_co]], stops_1: ndarray[Any, dtype[_ScalarType_co]], contigs_2: ndarray[Any, dtype[_ScalarType_co]], starts_2: ndarray[Any, dtype[_ScalarType_co]], stops_2: ndarray[Any, dtype[_ScalarType_co]]) ndarray[Any, dtype[_ScalarType_co]]#
    +

    Function that performs vectorized computation of overlaps. Returns +an array of same shape as contig_1 that is true if the intervals +for set 1 each have any overlap with an interval in set 2.

    +
    + +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + + + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/api_reference/genomeutils.html b/docs/_build/html/documentation/api_reference/genomeutils.html new file mode 100644 index 00000000..bfdf655a --- /dev/null +++ b/docs/_build/html/documentation/api_reference/genomeutils.html @@ -0,0 +1,694 @@ + + + + + + + + + + + Genome Utilities — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Genome Utilities#

    +
    +
    +class finaletoolkit.genome.GenomeGaps(gaps_bed: Path | str | None = None)#
    +

    Reads telomere, centromere, and short_arm intervals from a bed file +or generates these intervals from UCSC gap and centromere tracks for +hg19 and hg38.

    +
    +
    +classmethod b37()#
    +

    Creates a GenomeGaps for the Broad Institute GRCh37 reference +genome i.e b37. This reference genome is also based on GRCh37, +but differs from the UCSC hg19 reference in a few ways, +including the absence of the ‘chr’ prefix. We generate this +GenomeGap using an ad hoc method where we take the UCSC hg19 +gap track and drop ‘chr’ from the chromosome names. Because +there are other differences between hg19 and b37, this is not +a perfect solution.

    +
    +
    Returns:
    +

    gaps – GenomeGaps for the b37 reference genome.

    +
    +
    Return type:
    +

    GenomeGaps

    +
    +
    +
    + +
    +
    +get_arm(contig: str, start: int, stop: int) str#
    +

    Returns the chromosome arm the interval is in. If in +the short arm of an acrocentric chromosome or intersects a +centromere, returns an empty string.

    +
    +
    contigstr

    Chromosome of interval.

    +
    +
    startint

    Start of interval.

    +
    +
    stopint

    End of interval.

    +
    +
    +
    +
    Returns:
    +

    arm – Arm that interval is in.

    +
    +
    Return type:
    +

    str

    +
    +
    Raises:
    +

    ValueError – Raised for invalid coordinates

    +
    +
    +
    + +
    +
    +get_contig_gaps(contig: str) ContigGaps#
    +

    Creates a ContigGaps for the specified chromosome

    +
    +
    Parameters:
    +

    contig (str) – Chromosome to make ContigGaps for

    +
    +
    Returns:
    +

    Contains centromere and telomere intervals for chromosome

    +
    +
    Return type:
    +

    ContigGaps

    +
    +
    +
    + +
    +
    +classmethod hg38()#
    +

    Creates a GenomeGaps for the hg38 reference genome. This +sequences uses chromosome names that start with ‘chr’ and is +synonymous with the GRCh38 reference genome. +:returns: gaps – GenomeGaps for the hg38 reference genome. +:rtype: GenomeGaps

    +
    + +
    +
    +in_tcmere(contig: str, start: int, stop: int) bool#
    +

    Checks if specified interval is in a centromere or telomere

    +
    +
    Parameters:
    +
      +
    • contig (str) – Chromosome name

    • +
    • start (int) – Start of interval

    • +
    • stop (int) – End of interval

    • +
    +
    +
    Returns:
    +

    in_telomere_or_centromere – True if in a centromere or telomere

    +
    +
    Return type:
    +

    bool

    +
    +
    +
    + +
    +
    +overlaps_gap(contig: str, start: int, stop: int) bool#
    +

    Checks if specified interval overlaps a gap interval

    +
    +
    Parameters:
    +
      +
    • contig (str) – Chromosome name

    • +
    • start (int) – Start of interval

    • +
    • stop (int) – End of interval

    • +
    +
    +
    Returns:
    +

    in_telomere_or_centromere – True if in a centromere or telomere

    +
    +
    Return type:
    +

    bool

    +
    +
    +
    + +
    +
    +to_bed(output_file: str)#
    +

    Prints gap intervals in GenomeGaps to a BED4 file where the name +is the type of gap interval.

    +
    +
    Parameters:
    +

    output_file (str) – File to write to. Optionally gzipped. If output_file == ‘-‘, +results will be writted to stdout.

    +
    +
    +
    + +
    +
    +classmethod ucsc_hg19()#
    +

    Creates a GenomeGaps for the UCSC hg19 reference genome. This +sequences uses chromosome names that start with ‘chr’ and is +based on a version of the GRCh37 reference genome.

    +
    +
    Returns:
    +

    gaps – GenomeGaps for the UCSC hg19 reference genome.

    +
    +
    Return type:
    +

    GenomeGaps

    +
    +
    +
    + +
    + +
    +
    +class finaletoolkit.genome.ContigGaps(contig: str, centromere: tuple[int, int], telomeres: Iterable[tuple[int, int]], has_short_arm: bool = False)#
    +
    +
    +get_arm(start: int, stop: int)#
    +

    Returns name of chromosome arm the interval is in. Returns +“NOARM” if in a centromere, telomere, or short arm of an +acrocentric chromosome.

    +
    +
    Parameters:
    +
      +
    • start (int) – Start of interval.

    • +
    • stop (int) – End of interval.

    • +
    +
    +
    Returns:
    +

    Name of the chromosome arm.

    +
    +
    Return type:
    +

    str

    +
    +
    Raises:
    +

    ValueError – Raised if invalid coordinates are given.

    +
    +
    +
    + +
    +
    +in_gap(start: int, stop: int) bool#
    +

    Checks if specified interval is in a gap.

    +
    +
    Parameters:
    +
      +
    • start (int) – Start of interval.

    • +
    • stop (int) – End of Interval.

    • +
    +
    +
    Returns:
    +

    True if there is an overlap.

    +
    +
    Return type:
    +

    bool

    +
    +
    +
    + +
    +
    +in_tcmere(start: int, stop: int) bool#
    +

    Checks if specified interval is in a centromere or telomere.

    +
    +
    Parameters:
    +
      +
    • start (int) – Start of interval.

    • +
    • stop (int) – End of Interval.

    • +
    +
    +
    Returns:
    +

    True if there is an overlap.

    +
    +
    Return type:
    +

    bool

    +
    +
    +
    + +
    + +
    +
    +finaletoolkit.genome.ucsc_hg19_gap_bed(output_file: str)#
    +

    Creates BED4 of centromeres, telomeres, and short arms for the UCSC +hg19 reference sequence.

    +
    +
    Parameters:
    +

    output_file (str) – Output path

    +
    +
    +
    + +
    +
    +finaletoolkit.genome.b37_gap_bed(output_file: str)#
    +

    Creates BED4 of centromeres, telomeres, and short arms for the Broad +Institute GRCh37 (b37) reference sequence. Also useful for +files aligned to human_g1k_v37 (1000 Genomes Project).

    +
    +
    Parameters:
    +

    output_file (str) – Output path

    +
    +
    +
    + +
    +
    +finaletoolkit.genome.ucsc_hg38_gap_bed(output_file: str)#
    +

    Creates BED4 of centromeres, telomeres, and short arms for the UCSC +hg38 reference sequence.

    +
    +
    Parameters:
    +

    output_file (str) – Output path

    +
    +
    +
    + +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + + + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/api_reference/index.html b/docs/_build/html/documentation/api_reference/index.html new file mode 100644 index 00000000..735d49e5 --- /dev/null +++ b/docs/_build/html/documentation/api_reference/index.html @@ -0,0 +1,455 @@ + + + + + + + + + + + API — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + + +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/api_reference/wps.html b/docs/_build/html/documentation/api_reference/wps.html new file mode 100644 index 00000000..2f772127 --- /dev/null +++ b/docs/_build/html/documentation/api_reference/wps.html @@ -0,0 +1,515 @@ + + + + + + + + + + + Window Protection Score (WPS) — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Window Protection Score (WPS)#

    +
    +
    +finaletoolkit.frag.wps(input_file: str | AlignmentFile, contig: str, start: int | str, stop: int | str, output_file: str | None = None, window_size: int = 120, fraction_low: int = 120, fraction_high: int = 180, quality_threshold: int = 30, verbose: bool | int = 0) ndarray#
    +

    Return (raw) Windowed Protection Scores as specified in Snyder et al +(2016) over a region [start,stop).

    +
    +
    Parameters:
    +
      +
    • input_file (str or pysam.AlignmentFile) – BAM, SAM or tabix file containing paired-end fragment reads or its +path. AlignmentFile must be opened in read mode.

    • +
    • contig (str)

    • +
    • start (int)

    • +
    • stop (int)

    • +
    • output_file (string, optional)

    • +
    • window_size (int, optional) – Size of window to calculate WPS. Default is k = 120, equivalent +to L-WPS.

    • +
    • fraction_low (int, optional) – Specifies lowest fragment length included in calculation. +Default is 120, equivalent to long fraction.

    • +
    • fraction_high (int, optional) – Specifies highest fragment length included in calculation. +Default is 180, equivalent to long fraction.

    • +
    • quality_threshold (int, optional)

    • +
    • workers (int, optional)

    • +
    • verbose (bool, optional)

    • +
    +
    +
    Returns:
    +

    scores – np struct array of with columns contig, start, and wps.

    +
    +
    Return type:
    +

    numpy.ndarray

    +
    +
    +
    + +
    +
    +finaletoolkit.frag.multi_wps(input_file: AlignmentFile | str, site_bed: str, output_file: None | str = None, window_size: int = 120, interval_size: int = 5000, fraction_low: int = 120, fraction_high: int = 180, quality_threshold: int = 30, workers: int = 1, verbose: bool | int = 0) ndarray#
    +

    Function that aggregates WPS over sites in BED file according to the +method described by Snyder et al (2016).

    +
    +
    Parameters:
    +
      +
    • input_file (str or pysam.AlignmentFile) – BAM, SAM, or tabix file containing paired-end fragment reads or its +path. AlignmentFile must be opened in read mode.

    • +
    • site_bed (str) – Bed file containing intervals to perform WPS on.

    • +
    • output_file (string, optional)

    • +
    • window_size (int, optional) – Size of window to calculate WPS. Default is k = 120, equivalent +to L-WPS.

    • +
    • interval_size (int, optional) – Size of each interval specified in the bed file. Should be the +same for every interbal. Default is 5000.

    • +
    • fraction_low (int, optional) – Specifies lowest fragment length included in calculation. +Default is 120, equivalent to long fraction.

    • +
    • fraction_high (int, optional) – Specifies highest fragment length included in calculation. +Default is 120, equivalent to long fraction.

    • +
    • quality_threshold (int, optional)

    • +
    • workers (int, optional)

    • +
    • verbose (bool, optional)

    • +
    +
    +
    Returns:
    +

    scores – np array of shape (n, 2) where column 1 is the coordinate and +column 2 is the score and n is the number of coordinates in +region [start,stop)

    +
    +
    Return type:
    +

    numpy.ndarray

    +
    +
    +
    + +
    +
    +finaletoolkit.frag.adjust_wps(input_file: str, interval_file: str, output_file: str, genome_file: str, median_window_size: int = 1000, savgol_window_size: int = 21, savgol_poly_deg: int = 2, mean: bool = False, subtract_edges: bool = False, edge_size: int = 500, workers: int = 1, verbose: Union(bool, int) = False)#
    +

    Adjusts raw WPS data in a BigWig by applying a median filter and +Savitsky-Golay filter (Savitsky and Golay, 1964).

    +
    +
    Parameters:
    +
      +
    • input_file (str) – Path string to a BigWig containing raw WPS data.

    • +
    • interval_file (str) – BED format file containing intervals over which WPS was +calculated on.

    • +
    • output_file (str) – BigWig file to write adjusted WPS to.

    • +
    • genome_file (str) – The genome file for the reference genome that WGS was aligned +to. A tab delimited file where column 1 contains the name of +chromosomes and column 2 contains chromosome length.

    • +
    • median_window_size (int, optional) – Size of median filter window. Default is 1000.

    • +
    • savgol_window_size (int, optional) – Size of Savitsky Golay filter window. Default is 21.

    • +
    • savgol_poly_deg (int, optional) – Degree polynomial for Savitsky Golay filter. Default is 2.

    • +
    • mean (bool, optional) – If true, a mean filter is used instead of median. Default is +False.

    • +
    • subtract_edges (bool, optional) – If true, take the median of the first and last 500 bases in a +window and subtract from the whole interval. Default is False.

    • +
    • workers (int, optional) – Number of processes to use. Default is 1.

    • +
    • verbose (bool or int, optional) – Default is False.

    • +
    +
    +
    +
    + +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/cli_reference/index.html b/docs/_build/html/documentation/cli_reference/index.html new file mode 100644 index 00000000..fb24339f --- /dev/null +++ b/docs/_build/html/documentation/cli_reference/index.html @@ -0,0 +1,1161 @@ + + + + + + + + + + + CLI — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    CLI#

    +

    FinaleToolkit is a package and standalone program to extract fragmentation features of cell-free DNA from paired-end sequencing data.

    +

    +
    usage: finaletoolkit [-h] [-v]
    +                     {coverage,frag-length-bins,frag-length-intervals,cleavage-profile,wps,adjust-wps,delfi,delfi-gc-correct,end-motifs,interval-end-motifs,mds,interval-mds,filter-bam,agg-bw,gap-bed}
    +                     ...
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -v, --version
    +

    show program’s version number and exit

    +
    +
    +
    +
    +

    Sub-commands#

    +
    +

    coverage#

    +

    Calculates fragmentation coverage over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

    +
    finaletoolkit coverage [-h] [-o OUTPUT_FILE] [-s SCALE_FACTOR] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file interval_file
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    +
    +
    interval_file
    +

    Path to a BED file containing intervals to calculate coverage over.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -o, --output_file
    +

    A BED file containing coverage values over the intervals specified in interval file.

    +

    Default: “-”

    +
    +
    -s, --scale-factor
    +

    Scale factor for coverage values.

    +

    Default: 1000000.0

    +
    +
    -q, --quality_threshold
    +

    Minimum mapping quality threshold.

    +

    Default: 30

    +
    +
    -w, --workers
    +

    Number of worker processes.

    +

    Default: 1

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +

    Default: False

    +
    +
    +
    +
    +
    +

    frag-length-bins#

    +

    Retrieves fragment lengths grouped in bins given a BAM/SAM/CRAM/Fragment file.

    +
    finaletoolkit frag-length-bins [-h] [-c CONTIG] [-S START] [-p {midpoint,any}] [-E STOP] [--bin-size BIN_SIZE] [-o OUTPUT_FILE] [--contig-by-contig] [--histogram] [-q QUALITY_THRESHOLD] [-v]
    +                               input_file
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -c, --contig
    +

    Specify the contig or chromosome to select fragments from. (Required if using –start or –stop.)

    +
    +
    -S, --start
    +

    Specify the 0-based left-most coordinate of the interval to select fragments from. (Must also specify –contig.)

    +
    +
    -p, --intersect_policy
    +

    Possible choices: midpoint, any

    +

    Specifies what policy is used to include fragments in the given interval. See User Guide for more information.

    +

    Default: “midpoint”

    +
    +
    -E, --stop
    +

    Specify the 1-based right-most coordinate of the interval to select fragments from. (Must also specify –contig.)

    +
    +
    --bin-size
    +

    Specify the size of the bins to group fragment lengths into.

    +
    +
    -o, --output_file
    +

    A .TSV file containing containing fragment lengths binned according to the specified bin size.

    +

    Default: “-”

    +
    +
    --contig-by-contig
    +

    Placeholder, not implemented.

    +

    Default: False

    +
    +
    --histogram
    +

    Enable histogram mode to display histogram in terminal.

    +

    Default: False

    +
    +
    -q, --quality_threshold
    +

    Minimum mapping quality threshold.

    +

    Default: 30

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +

    Default: 0

    +
    +
    +
    +
    +
    +

    frag-length-intervals#

    +

    Retrieves fragment length summary statistics over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

    +
    finaletoolkit frag-length-intervals [-h] [-p {midpoint,any}] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file interval_file
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    +
    +
    interval_file
    +

    Path to a BED file containing intervals to retrieve fragment length summary statistics over.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -p, --intersect_policy
    +

    Possible choices: midpoint, any

    +

    Specifies what policy is used to include fragments in the given interval. See User Guide for more information.

    +

    Default: “midpoint”

    +
    +
    -o, --output-file
    +

    A BED file containing fragment length summary statistics (mean, median, st. dev, min, max) over the intervals specified in the interval file.

    +

    Default: “-”

    +
    +
    -q, --quality-threshold
    +

    Minimum mapping quality threshold.

    +

    Default: 30

    +
    +
    -w, --workers
    +

    Number of worker processes.

    +

    Default: 1

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +

    Default: 0

    +
    +
    +
    +
    +
    +

    cleavage-profile#

    +

    Calculates cleavage proportion over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

    +
    finaletoolkit cleavage-profile [-h] [-o OUTPUT_FILE] [-lo FRACTION_LOW] [-hi FRACTION_HIGH] [-q QUALITY_THRESHOLD] [-l LEFT] [-r RIGHT] [-w WORKERS] [-v] input_file interval_file
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    +
    +
    interval_file
    +

    Path to a BED file containing intervals to calculates cleavage proportion over.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -o, --output_file
    +

    A bigWig file containing the cleavage proportion results over the intervals specified in interval file.

    +

    Default: “-”

    +
    +
    -lo, --fraction_low
    +

    Minimum length for a fragment to be included in cleavage proportion calculation.

    +

    Default: 120

    +
    +
    -hi, --fraction_high
    +

    Maximum length for a fragment to be included in cleavage proportion calculation.

    +

    Default: 180

    +
    +
    -q, --quality-threshold
    +

    Minimum mapping quality threshold.

    +

    Default: 20

    +
    +
    -l, --left
    +

    Number of base pairs to subtract from start coordinate to create interval. Useful when dealing with BED files with only CpG coordinates.

    +

    Default: 0

    +
    +
    -r, --right
    +

    Number of base pairs to add to stop coordinate to create interval. Useful when dealing with BED files with only CpG coordinates.

    +

    Default: 0

    +
    +
    -w, --workers
    +

    Number of worker processes.

    +

    Default: 1

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +

    Default: 0

    +
    +
    +
    +
    +
    +

    wps#

    +

    Calculates Windowed Protection Score (WPS) over intervals defined in a BED file based on alignment data from a BAM/SAM/CRAM/Fragment file.

    +
    finaletoolkit wps [-h] [-o OUTPUT_FILE] [-i INTERVAL_SIZE] [-W WINDOW_SIZE] [-lo FRACTION_LOW] [-hi FRACTION_HIGH] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file site_bed
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    +
    +
    site_bed
    +

    Path to a BED file containing intervals to calculate WPS over.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -o, --output_file
    +

    A bigWig file containing the WPS results over the intervals specified in interval file.

    +

    Default: “-”

    +
    +
    -i, --interval_size
    +

    Size in bp of each interval in the interval file.

    +

    Default: 5000

    +
    +
    -W, --window_size
    +

    Size of the sliding window used to calculate WPS scores.

    +

    Default: 120

    +
    +
    -lo, --fraction_low
    +

    Minimum length for a fragment to be included in WPS calculation.

    +

    Default: 120

    +
    +
    -hi, --fraction_high
    +

    Maximum length for a fragment to be included in WPS calculation.

    +

    Default: 180

    +
    +
    -q, --quality_threshold
    +

    Minimum mapping quality threshold.

    +

    Default: 30

    +
    +
    -w, --workers
    +

    Number of worker processes.

    +

    Default: 1

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +

    Default: 0

    +
    +
    +
    +
    +
    +

    adjust-wps#

    +

    Adjusts raw Windowed Protection Score (WPS) by applying a median filter and Savitsky-Golay filter.

    +
    finaletoolkit adjust-wps [-h] [-o OUTPUT_FILE] [-m MEDIAN_WINDOW_SIZE] [-s SAVGOL_WINDOW_SIZE] [-p SAVGOL_POLY_DEG] [-w WORKERS] [--mean] [--subtract-edges] [-v] input_file interval_file genome_file
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +

    A bigWig file containing the WPS results over the intervals specified in interval file.

    +
    +
    interval_file
    +

    Path to a BED file containing intervals to WPS was calculated over.

    +
    +
    genome_file
    +

    A .chrom.sizes file containing chromosome sizes.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -o, --output-file
    +

    A bigWig file containing the adjusted WPS results over the intervals specified in interval file.

    +

    Default: “-”

    +
    +
    -m, --median-window-size
    +

    Size of the median filter window used to adjust WPS scores.

    +

    Default: 1000

    +
    +
    -s, --savgol-window-size
    +

    Size of the Savitsky-Golay filter window used to adjust WPS scores.

    +

    Default: 21

    +
    +
    -p, --savgol-poly-deg
    +

    Degree polynomial for Savitsky-Golay filter.

    +

    Default: 2

    +
    +
    -w, --workers
    +

    Number of worker processes.

    +

    Default: 1

    +
    +
    --mean
    +

    A mean filter is used instead of median.

    +

    Default: False

    +
    +
    --subtract-edges
    +

    Take the median of the first and last 500 bases in a window and subtract from the whole interval.

    +

    Default: False

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +
    +
    +
    +
    +
    +

    delfi#

    +

    Calculates DELFI featrues over genome, returning information about (GC-corrected) short fragments, long fragments, DELFI ratio, and total fragments. NOTE: Due to some ad hoc implementation details, currently the only accepted reference genome is hg19.

    +
    finaletoolkit delfi [-h] [-b BLACKLIST_FILE] [-g GAP_FILE] [-o OUTPUT_FILE] [-W WINDOW_SIZE] [-gc] [-m] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file autosomes reference_file bins_file
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    +
    +
    autosomes
    +

    Tab-delimited file containing (1) autosome name and (2) integer length of chromosome in base pairs.

    +
    +
    reference_file
    +

    The .2bit file for the associate reference genome sequence used during alignment.

    +
    +
    bins_file
    +

    A BED file containing bins over which to calculate DELFI. To replicate Cristiano et al.’s methodology, use 100kb bins over human autosomes.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -b, --blacklist_file
    +

    BED file containing regions to ignore when calculating DELFI.

    +
    +
    -g, --gap_file
    +

    BED4 format file containing columns for “chrom”, “start”, “stop”, and “type”. The “type” column should denote whether the entry corresponds to a “centromere”, “telomere”, or “short arm”, and entries not falling into these categories are ignored. This information corresponds to the “gap” track for hg19 in the UCSC Genome Browser.

    +
    +
    -o, --output_file
    +

    BED, bed.gz, TSV, or CSV file to write DELFI data to. If “-”, writes to stdout.

    +

    Default: “-”

    +
    +
    -W, --window_size
    +

    Currently unused.

    +

    Default: 5000000

    +
    +
    -gc, --gc_correct
    +

    Indicates whether to apply GC correction.

    +

    Default: False

    +
    +
    -m, --merge_bins
    +

    Indicates whether to merge bins to 5Mb size.

    +

    Default: False

    +
    +
    -q, --quality_threshold
    +

    Minimum mapping quality threshold.

    +

    Default: 30

    +
    +
    -w, --workers
    +

    Number of worker processes.

    +

    Default: 1

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +

    Default: 0

    +
    +
    +
    +
    +
    +

    delfi-gc-correct#

    +

    Performs gc-correction on raw delfi data.

    +
    finaletoolkit delfi-gc-correct [-h] [-o OUTPUT_FILE] [--header-lines HEADER_LINES] [-v] input_file
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +

    BED file containing raw DELFI data. Raw DELFI data should only have columns for “contig”, “start”, “stop”, “arm”, “short”, “long”, “gc”, “num_frags”, “ratio”.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -o, --output-file
    +

    BED to print GC-corrected DELFI fractions. If “-”, will write to stdout.

    +

    Default: “-”

    +
    +
    --header-lines
    +

    Number of header lines in BED.

    +

    Default: 1

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +
    +
    +
    +
    +
    +

    end-motifs#

    +

    Measures frequency of k-mer 5’ end motifs.

    +
    finaletoolkit end-motifs [-h] [-k K] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file refseq_file
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    +
    +
    refseq_file
    +

    The .2bit file for the associate reference genome sequence used during alignment.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -k
    +

    Length of k-mer.

    +

    Default: 4

    +
    +
    -o, --output-file
    +

    TSV to print k-mer frequencies. If “-”, will write to stdout.

    +

    Default: “-”

    +
    +
    -q, --quality-threshold
    +

    Minimum mapping quality threshold.

    +

    Default: 20

    +
    +
    -w, --workers
    +

    Number of worker processes.

    +

    Default: 1

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +

    Default: 0

    +
    +
    +
    +
    +
    +

    interval-end-motifs#

    +

    Measures frequency of k-mer 5’ end motifs in each region specified in a BED file and writes data into a table.

    +
    finaletoolkit interval-end-motifs [-h] [-k K] [-lo FRACTION_LOW] [-hi FRACTION_HIGH] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-w WORKERS] [-v] input_file refseq_file intervals
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +

    Path to a BAM/SAM/CRAM/Fragment file containing fragment data.

    +
    +
    refseq_file
    +

    The .2bit file for the associate reference genome sequence used during alignment.

    +
    +
    intervals
    +

    Path to a BED file containing intervals to retrieve end motif frequencies over.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -k
    +

    Length of k-mer.

    +

    Default: 4

    +
    +
    -lo, --fraction-low
    +

    Minimum length for a fragment to be included in end motif frequency.

    +

    Default: 10

    +
    +
    -hi, --fraction-high
    +

    Maximum length for a fragment to be included in end motif frequency.

    +

    Default: 600

    +
    +
    -o, --output-file
    +

    Path to TSV or CSV file to write end motif frequencies to.

    +

    Default: “-”

    +
    +
    -q, --quality-threshold
    +

    Minimum mapping quality threshold.

    +

    Default: 20

    +
    +
    -w, --workers
    +

    Number of worker processes.

    +

    Default: 1

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +

    Default: 0

    +
    +
    +
    +
    +
    +

    mds#

    +

    Reads k-mer frequencies from a file and calculates a motif diversity score (MDS) using normalized Shannon entropy as described by Jiang et al (2020).

    +
    finaletoolkit mds [-h] [-s SEP] [--header HEADER] [file_path]
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    file_path
    +

    Tab-delimited or similar file containing one column for all k-mers a one column for frequency. Reads from stdin by default.

    +

    Default: “-”

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -s, --sep
    +

    Separator used in tabular file.

    +

    Default: “ “

    +
    +
    --header
    +

    Number of header rows to ignore. Default is 0

    +

    Default: 0

    +
    +
    +
    +
    +
    +

    interval-mds#

    +

    Reads k-mer frequencies from a file and calculates a motif diversity score (MDS) for each interval using normalized Shannon entropy as described by Jiang et al (2020).

    +
    finaletoolkit interval-mds [-h] [-s SEP] [file_path] file_out
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    file_path
    +

    Tab-delimited or similar file containing one column for all k-mers a one column for frequency. Reads from stdin by default.

    +

    Default: “-”

    +
    +
    file_out
    +

    Path to the output BED/BEDGraph file containing MDS for each interval.

    +

    Default: “-”

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -s, --sep
    +

    Separator used in tabular file.

    +

    Default: “ “

    +
    +
    +
    +
    +
    +

    filter-bam#

    +

    Filters a BAM file so that all reads are in mapped pairs, exceed a certain MAPQ, are not flagged for quality, are read1, are not secondary or supplementary alignments, and are on the same reference sequence as the mate.

    +
    finaletoolkit filter-bam [-h] [-r REGION_FILE] [-o OUTPUT_FILE] [-q QUALITY_THRESHOLD] [-hi FRACTION_HIGH] [-lo FRACTION_LOW] [-w WORKERS] [-v] input_file
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +

    Path to BAM file.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -r, --region-file
    +

    Only output alignments overlapping the intervals in this BED file will be included.

    +
    +
    -o, --output-file
    +

    Output BAM file path.

    +

    Default: “-”

    +
    +
    -q, --quality_threshold
    +

    Minimum mapping quality threshold.

    +

    Default: 30

    +
    +
    -hi, --fraction-high
    +

    Maximum length for a fragment to be included in output BAM.

    +
    +
    -lo, --fraction-low
    +

    Minimum length for a fragment to be included in output BAM.

    +
    +
    -w, --workers
    +

    Number of worker processes.

    +

    Default: 1

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +
    +
    +
    +
    +
    +

    agg-bw#

    +

    Aggregates a bigWig signal over constant-length intervals defined in a BED file.

    +
    finaletoolkit agg-bw [-h] [-o OUTPUT_FILE] [-m MEDIAN_WINDOW_SIZE] [-v] input_file interval_file
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    input_file
    +
    +

    A bigWig file containing signals over the intervals specified in interval file.

    +
    +
    +
    interval_file
    +

    Path to a BED file containing intervals over which signals were calculated over.

    +
    +
    +
    +
    +

    Named Arguments#

    +
    +
    -o, --output-file
    +

    A wiggle file containing the aggregate signal over the intervals specified in interval file.

    +

    Default: “-”

    +
    +
    -m, --median-window-size
    +

    Size of the median filter window used to adjust WPS scores. Only modify if aggregating WPS signals.

    +

    Default: 0

    +
    +
    -v, --verbose
    +

    Enable verbose mode to display detailed processing information.

    +
    +
    +
    +
    +
    +

    gap-bed#

    +

    Creates a BED4 file containing centromeres, telomeres, and short-arm intervals, similar to the gaps annotation track for hg19 found on the UCSC Genome Browser (Kent et al 2002). Currently only supports hg19, b37, human_g1k_v37, hg38, and GRCh38

    +
    finaletoolkit gap-bed [-h] {hg19,b37,human_g1k_v37,hg38,GRCh38} output_file
    +
    +
    +
    +

    Positional Arguments#

    +
    +
    reference_genome
    +

    Possible choices: hg19, b37, human_g1k_v37, hg38, GRCh38

    +

    Reference genome to provide gaps for.

    +
    +
    output_file
    +

    Path to write BED file to. If “-” used, writes to stdout.

    +
    +
    +
    +

    Gap is used liberally in this command, and in the case hg38/GRCh38, may refer to regions where there no longer are gaps in the reference sequence.

    +
    +
    +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + + + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/index.html b/docs/_build/html/documentation/index.html new file mode 100644 index 00000000..12d34a1b --- /dev/null +++ b/docs/_build/html/documentation/index.html @@ -0,0 +1,393 @@ + + + + + + + + + + + FinaleToolkit Documentation — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + + + +
    + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + + + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/user_guide/features.html b/docs/_build/html/documentation/user_guide/features.html new file mode 100644 index 00000000..a687cbed --- /dev/null +++ b/docs/_build/html/documentation/user_guide/features.html @@ -0,0 +1,454 @@ + + + + + + + + + + + Features — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Features#

    +

    FinaleToolkit has support for the following cell-free DNA features:

    +
    +

    Fragment Length#

    +

    FinaleToolkit can calculate the fragment length distribution and summary statistics of cell-free DNA fragments.

    +
    +
    +

    Fragment Coverage#

    +

    FinaleToolkit can calculate fragment coverage (the number of reads mapped to a specific region of the genome). This coverage can be normalized by the total number of reads in the sample, or simply the raw value.

    +
    +
    +

    Windowed Protection Score (WPS)#

    +

    FinaleToolkit can calculate the Windowed Protection Score (WPS), which is a metric designed by Snyder et al. 2016.

    +

    It is used to quantify the level of protection or coverage of DNA fragments across a specific genomic region. It’s calculated by assessing the number of DNA fragments that fully span a defined window (typically 120 base pairs) centered around a particular genomic coordinate, and then subtracting the number of fragments with an endpoint falling within the same window. This score is correlated with the location of nucleosomes and other genomic features, including transcriptional start sites (TSS) and DNase I hypersensitive sites (DHSs).

    +
    +
    +

    DELFI#

    +

    FinaleToolkit can calculate DELFI, which is a metric designed by Cristiano et al. 2019.

    +

    DELFI is a metric that was introduced to identify abnormalities in cfDNA from their fragmentation patterns. In the original paper, DELFI was used to categorize patients with cancer and the associated tumor tissues of origin. The associated DELFI score is the ratio between the GC%-corrected short fragment count and the GC%-corrected long fragment count.

    +
    +
    +

    End Motifs#

    +

    FinaleToolkit can calculate the frequency of end-motif k-mers of cell-free DNA fragments. Since end motifs are specific sequences found at the ends of cfDNA fragments resulting from cleavage, they can be used to potentially detect patterns associated with certain conditions or diseases.

    +
    +
    +

    Motif Diversity Score (MDS)#

    +

    FinaleToolkit can calculate the Motif Diversity Score (MDS), which is a metric designed by Jiang et al. 2020.

    +

    The MDS is a metric that quantifies the diversity of cfDNA end motifs. It is the normalized Shannon entropy of the categorical distribution of all possible end-motif k-mers.

    +
    +
    +

    Cleavage Profile#

    +

    FinaleToolkit can calculate the Cleavage Proportion, which is a metric designed by Zhou et al. 2022.

    +

    The cleavage proportion is, by definition, the number of fragment ends that fall within a nucleotide location over the total number of fragment ends that overlap that nucleotide location. According to the authors, this metric shows a relationship to DNA methylation, specifically methylation at CpG sites.

    +
    +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + + + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/user_guide/help.html b/docs/_build/html/documentation/user_guide/help.html new file mode 100644 index 00000000..cf771e1e --- /dev/null +++ b/docs/_build/html/documentation/user_guide/help.html @@ -0,0 +1,411 @@ + + + + + + + + + + + Help — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Help#

    +

    If you think you’ve encountered a bug in FinaleToolkit, please report it on the Github issue tracker . To be useful, bug reports must include the following information:

    +
      +
    • A reproducible code example that demonstrates the problem

    • +
    • The output that you are seeing (ex. the error message)

    • +
    • A clear explanation of why you think something is wrong

    • +
    • The specific version of FinaleToolkit that you are working with.

    • +
    +

    If you’ve encountered an error, searching the specific text of the message before opening a new issue can often help you solve the problem quickly and avoid making a duplicate report.

    +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/user_guide/index.html b/docs/_build/html/documentation/user_guide/index.html new file mode 100644 index 00000000..7a8f1f92 --- /dev/null +++ b/docs/_build/html/documentation/user_guide/index.html @@ -0,0 +1,443 @@ + + + + + + + + + + + User Guide — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + + + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/user_guide/inputdata.html b/docs/_build/html/documentation/user_guide/inputdata.html new file mode 100644 index 00000000..11aa6419 --- /dev/null +++ b/docs/_build/html/documentation/user_guide/inputdata.html @@ -0,0 +1,454 @@ + + + + + + + + + + + Input Data — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Input Data#

    +

    FinaleToolkit is compatible with almost any paired-end sequence data.

    +
    +

    SAM#

    +

    A sequence alignment map (SAM) file is a human-readable file format that stores the results of sequence alignment. It contains information about the alignment of each read to the reference genome, as well as information about the read itself.

    +
    +
    +

    BAM#

    +

    A binary alignment file (BAM) provides the same information as a SAM file, but in a binary format. This can be useful for saving space on disk, but is not human-readable.

    +

    FinaleToolkit requires that BAM files be BAI indexed. Therefore, you should have an associated .bam.bai file in the same directory of your input data.

    +
    +
    +

    CRAM#

    +

    A compressed read alignment map file is a compressed version of a SAM file. It is a binary file that is smaller than a BAM file, but still contains all of the same information.

    +

    FinaleToolkit requires that CRAM files be CRAI indexed. Therefore, you should have an associated .cram.crai file in the same directory of your input data.

    +
    +
    +

    Fragment File#

    +

    A fragment file (.frag.gz) file that is derived from information in a BAM file. A fragment file is a block-gzipped BED3+2 file (similar to a tab-separated value file) that contains the following columns (with one row entry for each fragment): chrom, start, stop, mapq, and strand.

    +

    Here, mapq is the mapping quality of the fragment, and strand is the strand of the fragment. The strand column can be either + or -.

    +

    FinaleToolkit requires that fragment files be Tabix indexed. Therefore, you should have an associated .frag.gz.tbi file in the same directory of your input data.

    +

    For your reference, here is an example fragment file:

    +
    #chrom    start    stop    mapq    strand
    +chr1    10000    10050    60    +
    +chr1    10050    10100    60    -
    +chr1    10100    10150    60    +
    +chr1    10150    10200    60    -
    +chr1    10200    10250    60    +
    +chr1    10250    10300    60    -
    +chr1    10300    10350    60    +
    +chr1    10350    10400    60    -
    +chr1    10400    10450    60    +
    +chr1    10450    10500    60    -
    +
    +
    +

    We encourage you to use our comprehensive database, FinaleDB, to access relevant fragment files. Learn more about FinaleDB here .

    +
    +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/user_guide/installation.html b/docs/_build/html/documentation/user_guide/installation.html new file mode 100644 index 00000000..ba1dfa65 --- /dev/null +++ b/docs/_build/html/documentation/user_guide/installation.html @@ -0,0 +1,438 @@ + + + + + + + + + + + Installation — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Installation#

    +
    +

    Prerequisites#

    +

    The only prerequisite for installing FinaleToolkit is a Python version that is greater than 3.8.

    +
    +
    +

    Installation#

    +

    FinaleToolkit can be installed with with pip.

    +

    Using pip:

    +
    pip install finaletoolkit
    +
    +
    +

    Also when using pip, it’s good practice to use a virtual environment, like a conda environment.

    +
    +
    +

    Errors#

    +

    If any errors arise during the installation, please fill out a detailed issue in the GitHub repository.

    +

    If you are getting an ImportError on Mac when running FinaleToolkit, please run the following command in the terminal:

    +
    $ brew install curl
    +
    +
    +
    +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/user_guide/intersectpolicy.html b/docs/_build/html/documentation/user_guide/intersectpolicy.html new file mode 100644 index 00000000..60a1ee4d --- /dev/null +++ b/docs/_build/html/documentation/user_guide/intersectpolicy.html @@ -0,0 +1,428 @@ + + + + + + + + + + + Intersect Policy — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Intersect Policy#

    +

    When you give the Fragment Generator an interval of start and end to pull fragments from, which fragments will it return?

    +

    What if a fragment has 1bp of overlap within the just on the edge of the window? Does it also return that fragment as well?

    +

    These questions are answered by the intersect_policy argument, which shows up in many of the CLI and API commands.

    +

    intersect_policy can either be midpoint or any.

    +
    +

    Midpoint#

    +

    midpoint: The midpoint of the fragment determines whether the fragment will be returned or not. If the midpoint falls between start and end, then it will be returned. Else, it will not.

    +
    +
    +

    Any#

    +

    any: As long as the fragment overlaps the interval between start and end in some capacity, then it will be returned. Else, it will not.

    +
    +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/user_guide/quickstart.html b/docs/_build/html/documentation/user_guide/quickstart.html new file mode 100644 index 00000000..bb41a2ab --- /dev/null +++ b/docs/_build/html/documentation/user_guide/quickstart.html @@ -0,0 +1,437 @@ + + + + + + + + + + + Quickstart — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Quickstart#

    +
    +

    Getting Started#

    +

    If not to be integrated into a workflow, FinaleToolkit is intended to be run directly from a terminal interface.

    +

    You can open the terminal and typing the following command:

    +
    $ finaletoolkit
    +
    +
    +
    +
    +

    Importing Modules#

    +

    The FinaleToolkit package itself is divided by its API functions.

    +

    You can load all of the functions by using the following command:

    +
    >>> import finaletoolkit as ft
    +
    +
    +

    If you want to load a specific function, you can do so by using the following:

    +

    Assuming we wanted to load the DELFI function:

    +
    >>> from finaletoolkit.frag import delfi
    +
    +
    +
    +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/user_guide/structure.html b/docs/_build/html/documentation/user_guide/structure.html new file mode 100644 index 00000000..b5f77435 --- /dev/null +++ b/docs/_build/html/documentation/user_guide/structure.html @@ -0,0 +1,409 @@ + + + + + + + + + + + Structure — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Structure#

    +

    While not particularly pertinent to your usage, we include this page to give you a sense of what is going on under the hood of FinaleToolkit:

    +

    At the heart of FinaleToolkit is the Fragment Generator. This generator is designed to be as flexible as possible. It takes BAM, CRAM, SAM, and Fragment Files (among other arguments) and filters out the reads that are not of interest (e.x. unmapped reads, reads with low mapping quality, etc.). The fragments that make it through this filter are then passed to the relevant function to be processed.

    +

    A rough outline of the structure of FinaleToolkit is therefore as follows:

    +
    +../../_images/finaletoolkit_structure.png +
    +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/documentation/user_guide/what.html b/docs/_build/html/documentation/user_guide/what.html new file mode 100644 index 00000000..ae1e41ea --- /dev/null +++ b/docs/_build/html/documentation/user_guide/what.html @@ -0,0 +1,407 @@ + + + + + + + + + + + Introduction — FinaleToolkit documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + + +
    +
    +
    +
    +
    + + + + +
    +
    + + + +
    + + + + + + + + + + + + + +
    + +
    + + +
    +
    + +
    +
    + +
    + +
    + + + + +
    + +
    + + +
    +
    + + + + + +
    + +
    +

    Introduction#

    +

    Circulating cell-free DNA (cfDNA) refers to highly fragmented DNA that circulate in blood plasma. In healthy conditions, cfDNA mainly originates from hematopoietic cells through apoptosis or necrosis. In pathological states, additional cfDNA is released from the genomes of otherwise inaccessible tissues (e.g., from tumors in cancer).

    +

    CfDNA fragmentation patterns have been established as a promising non-invasive biomarker for disease detection and monitoring. It has been shown that fragmentation pattern and cfDNA tissue-of-origin changes are associated with changes in different pathological statuses.

    +

    Computational approaches can extract fragmentation features from cfDNA whole genome sequencing (WGS) data. However, various established cfDNA fragmentation features (ex. Windowed Protection Score (WPS), Motif Diversity Score (MDS), DELFI) have source code which is often absent, poorly documented, ad hoc, and unmaintained.

    +

    FinaleToolkit offers a solution to this. It is a fast and comprehensive toolkit that provides a user-friendly interface to extract various cfDNA fragmentation features from fragmentation data. It is designed to be easy to use, well-documented, and maintained.

    +
    + + +
    + + + + + +
    + +
    +
    +
    + +
    + + + +
    + + +
    +
    + +
    + +
    +
    +
    + + + + + +
    + + +
    + + \ No newline at end of file diff --git a/docs/_build/html/genindex.html b/docs/_build/html/genindex.html index 467780fe..36794563 100644 --- a/docs/_build/html/genindex.html +++ b/docs/_build/html/genindex.html @@ -1,9 +1,8 @@ - - + @@ -28,16 +27,16 @@ - + - - - + + + @@ -137,21 +136,21 @@