REDItools3 3.1a0__tar.gz → 3.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of REDItools3 might be problematic. Click here for more details.

Files changed (26) hide show
  1. {reditools3-3.1a0 → reditools3-3.3}/PKG-INFO +4 -4
  2. {reditools3-3.1a0 → reditools3-3.3}/REDItools3.egg-info/PKG-INFO +4 -4
  3. {reditools3-3.1a0 → reditools3-3.3}/pyproject.toml +4 -4
  4. {reditools3-3.1a0 → reditools3-3.3}/reditools/analyze.py +45 -60
  5. {reditools3-3.1a0 → reditools3-3.3}/reditools/file_utils.py +21 -42
  6. {reditools3-3.1a0 → reditools3-3.3}/reditools/homopolymerics.py +6 -1
  7. {reditools3-3.1a0 → reditools3-3.3}/reditools/index.py +7 -2
  8. {reditools3-3.1a0 → reditools3-3.3}/reditools/reditools.py +14 -1
  9. {reditools3-3.1a0 → reditools3-3.3}/reditools/rtchecks.py +28 -3
  10. {reditools3-3.1a0 → reditools3-3.3}/LICENSE +0 -0
  11. {reditools3-3.1a0 → reditools3-3.3}/README.md +0 -0
  12. {reditools3-3.1a0 → reditools3-3.3}/REDItools3.egg-info/SOURCES.txt +0 -0
  13. {reditools3-3.1a0 → reditools3-3.3}/REDItools3.egg-info/dependency_links.txt +0 -0
  14. {reditools3-3.1a0 → reditools3-3.3}/REDItools3.egg-info/requires.txt +0 -0
  15. {reditools3-3.1a0 → reditools3-3.3}/REDItools3.egg-info/top_level.txt +0 -0
  16. {reditools3-3.1a0 → reditools3-3.3}/reditools/__init__.py +0 -0
  17. {reditools3-3.1a0 → reditools3-3.3}/reditools/__main__.py +0 -0
  18. {reditools3-3.1a0 → reditools3-3.3}/reditools/alignment_file.py +0 -0
  19. {reditools3-3.1a0 → reditools3-3.3}/reditools/alignment_manager.py +0 -0
  20. {reditools3-3.1a0 → reditools3-3.3}/reditools/compiled_position.py +0 -0
  21. {reditools3-3.1a0 → reditools3-3.3}/reditools/compiled_reads.py +0 -0
  22. {reditools3-3.1a0 → reditools3-3.3}/reditools/fasta_file.py +0 -0
  23. {reditools3-3.1a0 → reditools3-3.3}/reditools/logger.py +0 -0
  24. {reditools3-3.1a0 → reditools3-3.3}/reditools/region.py +0 -0
  25. {reditools3-3.1a0 → reditools3-3.3}/reditools/utils.py +0 -0
  26. {reditools3-3.1a0 → reditools3-3.3}/setup.cfg +0 -0
@@ -1,19 +1,19 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: REDItools3
3
- Version: 3.1a0
3
+ Version: 3.3
4
4
  Author: Ernesto Picardi
5
5
  Author-email: Adam Handen <adam.handen@gmail.com>
6
6
  Project-URL: homepage, https://github.com/BioinfoUNIBA/REDItools3
7
7
  Project-URL: repository, https://github.com/BioinfoUNIBA/REDItools3
8
8
  Project-URL: issues, https://github.com/BioinfoUNIBA/REDItools3/issues
9
9
  Keywords: bioinformatics,RNA,RNA-editing
10
- Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Development Status :: 5 - Production/Stable
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: Intended Audience :: Science/Research
13
13
  Classifier: License :: OSI Approved :: GNU General Public License (GPL)
14
14
  Classifier: Operating System :: MacOS :: MacOS X
15
15
  Classifier: Operating System :: Unix
16
- Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.7
17
17
  Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
18
18
  Requires-Python: >=3.7
19
19
  Description-Content-Type: text/markdown
@@ -1,19 +1,19 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: REDItools3
3
- Version: 3.1a0
3
+ Version: 3.3
4
4
  Author: Ernesto Picardi
5
5
  Author-email: Adam Handen <adam.handen@gmail.com>
6
6
  Project-URL: homepage, https://github.com/BioinfoUNIBA/REDItools3
7
7
  Project-URL: repository, https://github.com/BioinfoUNIBA/REDItools3
8
8
  Project-URL: issues, https://github.com/BioinfoUNIBA/REDItools3/issues
9
9
  Keywords: bioinformatics,RNA,RNA-editing
10
- Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Development Status :: 5 - Production/Stable
11
11
  Classifier: Intended Audience :: Developers
12
12
  Classifier: Intended Audience :: Science/Research
13
13
  Classifier: License :: OSI Approved :: GNU General Public License (GPL)
14
14
  Classifier: Operating System :: MacOS :: MacOS X
15
15
  Classifier: Operating System :: Unix
16
- Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.7
17
17
  Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
18
18
  Requires-Python: >=3.7
19
19
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "REDItools3"
7
- version = "v3.1-alpha"
7
+ version = "v3.3"
8
8
  authors = [
9
9
  { name="Adam Handen", email="adam.handen@gmail.com" },
10
10
  { name="Ernesto Picardi" },
@@ -12,18 +12,18 @@ authors = [
12
12
  readme = "README.md"
13
13
  dependencies = [
14
14
  "pysam>=0.22.0",
15
- "sortedcontainers>=2.4.0"
15
+ "sortedcontainers>=2.4.0",
16
16
  ]
17
17
  keywords = ["bioinformatics", "RNA", "RNA-editing"]
18
18
  requires-python = ">=3.7"
19
19
  classifiers = [
20
- "Development Status :: 3 - Alpha",
20
+ "Development Status :: 5 - Production/Stable",
21
21
  "Intended Audience :: Developers",
22
22
  "Intended Audience :: Science/Research",
23
23
  "License :: OSI Approved :: GNU General Public License (GPL)",
24
24
  "Operating System :: MacOS :: MacOS X",
25
25
  "Operating System :: Unix",
26
- "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.7",
27
27
  "Topic :: Scientific/Engineering :: Bio-Informatics",
28
28
  ]
29
29
 
@@ -79,25 +79,18 @@ def setup_rtools(options): # noqa:WPS213,WPS231
79
79
  rtools.log_level = Logger.info_level
80
80
 
81
81
  if options.load_omopolymeric_file:
82
- regions = file_utils.load_omopolymeric_regions(
83
- options.load_omopolymeric_file,
84
- )
82
+ regions = file_utils.read_bed_file(options.load_omopolymeric_file)
85
83
  rtools.exclude(regions)
86
84
 
87
- if options.create_omopolymeric_file:
88
- rtools.create_omopolymeric_positions(
89
- options.create_omopolymeric_file,
90
- options.omopolymeric_span,
91
- )
92
-
93
85
  if options.splicing_file:
94
- rtools.load_splicing_file(
86
+ rtools.splice_positions = file_utils.load_splicing_file(
95
87
  options.splicing_file,
96
88
  options.splicing_span,
97
89
  )
98
90
 
99
91
  if options.bed_file:
100
- rtools.load_target_positions(options.bed_file)
92
+ regions = file_utils.read_bed_file(options.bed_file)
93
+ rtools.target_positions = regions
101
94
  if options.exclude_regions:
102
95
  for fname in options.exclude_regions:
103
96
  regions = file_utils.read_bed_file(fname)
@@ -109,10 +102,11 @@ def setup_rtools(options): # noqa:WPS213,WPS231
109
102
  rtools.max_base_position = options.max_base_position
110
103
  rtools.min_base_quality = options.min_base_quality
111
104
 
112
- rtools.min_column_length = options.min_column_length
105
+ rtools.min_column_length = options.min_read_depth
113
106
  rtools.min_edits = options.min_edits
114
107
  rtools.min_edits_per_nucleotide = options.min_edits_per_nucleotide
115
108
  rtools.strand = options.strand
109
+ rtools.max_alts = options.max_editing_nucleotides
116
110
 
117
111
  rtools.strand_confidence_threshold = options.strand_confidence_threshold
118
112
 
@@ -215,7 +209,7 @@ def run(options, in_queue, out_queue):
215
209
  except Exception as exc:
216
210
  if options.debug:
217
211
  traceback.print_exception(*sys.exc_info())
218
- sys.stderr.write(f'[ERROR] {exc}\n')
212
+ sys.stderr.write(f'[ERROR] ({type(exc)}) {exc}\n')
219
213
 
220
214
 
221
215
  def parse_options(): # noqa:WPS213
@@ -225,21 +219,26 @@ def parse_options(): # noqa:WPS213
225
219
  Returns:
226
220
  namespace: commandline args
227
221
  """
228
- parser = argparse.ArgumentParser(description='REDItools 2.0')
222
+ parser = argparse.ArgumentParser(
223
+ prog="reditools analyze",
224
+ description='REDItools3',
225
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
226
+ )
229
227
  parser.add_argument(
230
228
  'file',
231
229
  nargs='+',
232
- help='The bam file to be analyzed',
230
+ help='The bam file(s) to be analyzed.',
233
231
  )
234
232
  parser.add_argument(
235
233
  '-r',
236
234
  '--reference',
237
- help='The reference FASTA file',
235
+ help='Reference FASTA file.',
238
236
  )
239
237
  parser.add_argument(
240
238
  '-o',
241
239
  '--output-file',
242
- help='The output statistics file',
240
+ help='Path to write output to.',
241
+ default='/dev/stdout',
243
242
  )
244
243
  parser.add_argument(
245
244
  '-s',
@@ -248,96 +247,85 @@ def parse_options(): # noqa:WPS213
248
247
  type=int,
249
248
  default=0,
250
249
  help='Strand: this can be 0 (unstranded),' +
251
- '1 (secondstrand oriented) or ' +
252
- '2 (firststrand oriented)',
250
+ '1 (second strand oriented) or ' +
251
+ '2 (first strand oriented).',
253
252
  )
254
253
  parser.add_argument(
255
254
  '-a',
256
255
  '--append-file',
257
256
  action='store_true',
258
- help='Appends results to file (and creates if not existing)',
257
+ help='Appends results to file (and creates if not existing).',
259
258
  )
260
259
  parser.add_argument(
261
260
  '-g',
262
261
  '--region',
263
- help='The self.region of the bam file to be analyzed',
262
+ help='Only analyzes the specified region.',
264
263
  )
265
264
  parser.add_argument(
266
265
  '-m',
267
266
  '--load-omopolymeric-file',
268
- help='The file containing the omopolymeric positions',
269
- )
270
- parser.add_argument(
271
- '-c',
272
- '--create-omopolymeric-file',
273
- default=False,
274
- help='Path to write omopolymeric positions to',
275
- action='store_true',
267
+ help='BED file of omopolymeric positions.',
276
268
  )
277
269
  parser.add_argument(
278
270
  '-os',
279
271
  '--omopolymeric-span',
280
272
  type=int,
281
273
  default=5,
282
- help='The omopolymeric span',
274
+ help='The omopolymeric span.',
283
275
  )
284
276
  parser.add_argument(
285
277
  '-sf',
286
278
  '--splicing-file',
287
- help='The file containing the splicing sites positions',
279
+ help='The file containing splicing site positions.',
288
280
  )
289
281
  parser.add_argument(
290
282
  '-ss',
291
283
  '--splicing-span',
292
284
  type=int,
293
285
  default=4,
294
- help='The splicing span',
286
+ help='The splicing span.',
295
287
  )
296
288
  parser.add_argument(
297
289
  '-mrl',
298
290
  '--min-read-length',
299
291
  type=int,
300
292
  default=30, # noqa:WPS432
301
- help='Reads whose length is below this value will be discarded.',
293
+ help='Reads with length below -mrl will be discarded.',
302
294
  )
303
295
  parser.add_argument(
304
296
  '-q',
305
297
  '--min-read-quality',
306
298
  type=int,
307
299
  default=20, # noqa:WPS432
308
- help='Reads with mapping quality below this value will be discarded.',
300
+ help='Reads with mapping quality below -q will be discarded.',
309
301
  )
310
302
  parser.add_argument(
311
303
  '-bq',
312
304
  '--min-base-quality',
313
305
  type=int,
314
306
  default=30, # noqa:WPS432
315
- help='Base quality below this value will not be included in ' +
316
- 'the analysis.',
307
+ help='Base quality below -bq will bed discarded.',
317
308
  )
318
309
  parser.add_argument(
319
310
  '-mbp',
320
311
  '--min-base-position',
321
312
  type=int,
322
313
  default=0,
323
- help='Bases which reside in a previous position (in the read)' +
324
- 'will not be included in the analysis.',
314
+ help='Ignores the first -mbp bases in each read.',
325
315
  )
326
316
  parser.add_argument(
327
317
  '-Mbp',
328
318
  '--max-base-position',
329
319
  type=int,
330
320
  default=0,
331
- help='Bases which reside in a further position (in the read)' +
332
- 'will not be included in the analysis.',
321
+ help='Ignores the last -Mpb bases in each read.',
333
322
  )
334
323
  parser.add_argument(
335
324
  '-l',
336
- '--min-column-length',
325
+ '--min-read-depth',
337
326
  type=int,
338
327
  default=1,
339
- help='Positions whose columns have length below this value will' +
340
- 'not be included in the analysis.',
328
+ help='Only report on positions with at least -l read depth',
341
329
  )
342
330
  parser.add_argument(
343
331
  '-e',
@@ -351,8 +339,7 @@ def parse_options(): # noqa:WPS213
351
339
  '--min-edits-per-nucleotide',
352
340
  type=int,
353
341
  default=0,
354
- help='Positions whose columns have bases with less than' +
355
- 'min-edits-per-base edits will not be included in the analysis.',
342
+ help='Positions with fewer than -men edits will not be discarded.',
356
343
  )
357
344
  parser.add_argument(
358
345
  '-me',
@@ -360,16 +347,14 @@ def parse_options(): # noqa:WPS213
360
347
  type=int,
361
348
  default=0, # noqa:WPS432
362
349
  help='The minimum number of editing events (per position). ' +
363
- 'Positions whose columns have bases with less than ' +
364
- '"min-edits-per-base edits" will not be included in the ' +
365
- 'analysis.',
350
+ 'Positions with fewer than -me edits will be discarded.',
366
351
  )
367
352
  parser.add_argument(
368
353
  '-Men',
369
354
  '--max-editing-nucleotides',
370
355
  type=int,
371
- default=100, # noqa:WPS432
372
- help='The maximum number of editing nucleotides, from 0 to 4 ' +
356
+ default=4, # noqa:WPS432
357
+ help='The maximum number of editing nucleotides, from 0 to 3 ' +
373
358
  '(per position). Positions whose columns have more than ' +
374
359
  '"max-editing-nucleotides" will not be included in the analysis.',
375
360
  )
@@ -378,8 +363,8 @@ def parse_options(): # noqa:WPS213
378
363
  '--strand-confidence-threshold',
379
364
  type=float,
380
365
  default=0.7, # noqa:WPS432
381
- help='Only report the strandedness if at least this proportion of ' +
382
- 'reads are of a given strand',
366
+ help='Only report the strandedness if at least -T proportion of ' +
367
+ 'reads are of a given strand.',
383
368
  )
384
369
  parser.add_argument(
385
370
  '-C',
@@ -393,25 +378,25 @@ def parse_options(): # noqa:WPS213
393
378
  '-V',
394
379
  '--verbose',
395
380
  default=False,
396
- help='Verbose information in stderr',
381
+ help='Run in verbose mode.',
397
382
  action='store_true',
398
383
  )
399
384
  parser.add_argument(
400
385
  '-N',
401
386
  '--dna',
402
387
  default=False,
403
- help='Run REDItools 2.0 on DNA-Seq data',
388
+ help='Run REDItools on DNA-Seq data.',
404
389
  action='store_true',
405
390
  )
406
391
  parser.add_argument(
407
392
  '-B',
408
393
  '--bed_file',
409
- help='Path of BED file containing target self.regions',
394
+ help='Only analyze regions in the provided BED file.',
410
395
  )
411
396
  parser.add_argument(
412
397
  '-t',
413
398
  '--threads',
414
- help='Number of threads to run',
399
+ help='Number of threads for parallel processing.',
415
400
  type=int,
416
401
  default=1,
417
402
  )
@@ -419,7 +404,7 @@ def parse_options(): # noqa:WPS213
419
404
  '-w',
420
405
  '--window',
421
406
  help='How many bp should be processed by each thread at a time. ' +
422
- 'Defaults to full contig.',
407
+ 'Zero uses the full contig.',
423
408
  type=int,
424
409
  default=0,
425
410
  )
@@ -427,18 +412,18 @@ def parse_options(): # noqa:WPS213
427
412
  '-k',
428
413
  '--exclude_regions',
429
414
  nargs='+',
430
- help='Path of BED file containing regions to exclude from analysis',
415
+ help='Skip regions in the provided BED file(s).',
431
416
  )
432
417
  parser.add_argument(
433
418
  '-E',
434
419
  '--exclude_reads',
435
- help='Path to a text file listing read names to exclude from analysis',
420
+ help='Text file listing read names to exclude from analysis.',
436
421
  )
437
422
  parser.add_argument(
438
423
  '-d',
439
424
  '--debug',
440
425
  default=False,
441
- help='REDItools is run in DEBUG mode.',
426
+ help='Run in debug mode.',
442
427
  action='store_true',
443
428
  )
444
429
 
@@ -2,11 +2,8 @@
2
2
 
3
3
  import csv
4
4
  import os
5
- from collections import defaultdict
6
5
  from gzip import open as gzip_open
7
6
 
8
- from sortedcontainers import SortedSet
9
-
10
7
  from reditools.region import Region
11
8
 
12
9
 
@@ -68,54 +65,36 @@ def concat(output, *fnames, clean_up=True, encoding='utf-8'):
68
65
  os.remove(fname)
69
66
 
70
67
 
71
- def load_poly_regions(fname):
72
- """
73
- Read omopolymeric positions from a file.
74
-
75
- Parameters:
76
- fname (str): File path
77
-
78
- Returns:
79
- (dict): Contigs and regions
80
- """
81
- poly_regions = defaultdict(set)
82
- with read_bed_file(fname) as reader:
83
- for row in reader:
84
- poly_regions[row[0]] = Region(
85
- contig=row[0],
86
- start=row[1],
87
- stop=row[2],
88
- )
89
- return poly_regions
90
-
91
-
92
- def load_splicing_file(splicing_file, span):
68
+ def load_splicing_file(splicing_file, splicing_span):
93
69
  """
94
70
  Read splicing positions from a file.
95
71
 
96
72
  Parameters:
97
73
  splicing_file (str): File path
98
- span(int): Width of splice sites
74
+ splicing_span(int): Width of splice sites
99
75
 
100
- Returns:
101
- (dict): Contig and positions
76
+ Yeilds:
77
+ Splicing file contents as Regions.
102
78
  """
103
- splice_positions = defaultdict(SortedSet)
104
79
  strand_map = {'-': 'D', '+': 'A'}
105
80
 
106
- with open_stream(splicing_file, 'r') as stream:
107
- for line in stream:
108
- fields = line.strip().split()
109
-
110
- chrom = fields[0]
111
- strand = fields[4]
112
- splice = fields[3]
113
- span = int(fields[1])
114
-
115
- coe = -1 if strand_map.get(strand, None) == splice else 1
116
- new_positions = [1 + span + coe * fctr for fctr in range(span)]
117
- splice_positions[chrom] |= new_positions
118
- return splice_positions
81
+ stream = open_stream(splicing_file)
82
+ reader = csv.reader(
83
+ filter(lambda row: row[0] != '#', stream),
84
+ delimiter=' ',
85
+ )
86
+ for row in reader:
87
+ contig = row[0]
88
+ span = int(row[1])
89
+ splice = row[3]
90
+ strand = row[4]
91
+
92
+ coe = -1 if strand_map.get(strand, None) == splice else 1
93
+ start = 1 + span
94
+ stop = start + splicing_span * coe
95
+ if start > stop:
96
+ start, stop = stop, start
97
+ yield Region(contig=contig, start=start, stop=stop)
119
98
 
120
99
 
121
100
  def load_text_file(file_name):
@@ -42,7 +42,11 @@ def parse_options():
42
42
  Returns:
43
43
  namespace
44
44
  """
45
- parser = argparse.ArgumentParser(description='REDItools 2.0')
45
+ parser = argparse.ArgumentParser(
46
+ prog="reditools find-repeats",
47
+ description='REDItools3',
48
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
49
+ )
46
50
  parser.add_argument(
47
51
  'file',
48
52
  help='The fasta file to be analyzed',
@@ -57,6 +61,7 @@ def parse_options():
57
61
  parser.add_argument(
58
62
  '-o',
59
63
  '--output',
64
+ default='/dev/stdout',
60
65
  help='Destination to write results. Default is to use STDOUT. ' +
61
66
  'If the filename ends in .gz, the contents will be gzipped.',
62
67
  )
@@ -180,7 +180,11 @@ def parse_options(): # noqa:WPS213
180
180
  Returns:
181
181
  namespace: commandline args
182
182
  """
183
- parser = argparse.ArgumentParser(description='REDItools 2.0')
183
+ parser = argparse.ArgumentParser(
184
+ prog="reditools index",
185
+ description='REDItools3',
186
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
187
+ )
184
188
  parser.add_argument(
185
189
  'file',
186
190
  nargs='+',
@@ -189,6 +193,7 @@ def parse_options(): # noqa:WPS213
189
193
  parser.add_argument(
190
194
  '-o',
191
195
  '--output-file',
196
+ default='/dev/stdout',
192
197
  help='The output statistics file',
193
198
  )
194
199
  parser.add_argument(
@@ -239,7 +244,7 @@ def main():
239
244
  indexer.add_target_from_bed(trg_fname)
240
245
 
241
246
  if options.output_file:
242
- stream = open_stream(options.output_fipe, 'w')
247
+ stream = open_stream(options.output_file, 'w')
243
248
  else:
244
249
  stream = sys.stdout
245
250
 
@@ -127,7 +127,6 @@ class REDItools(object):
127
127
  self._target_positions = False
128
128
  self._exclude_positions = {}
129
129
  self._splice_positions = []
130
-
131
130
  self._specific_edits = None
132
131
 
133
132
  self.reference = None
@@ -294,6 +293,20 @@ class REDItools(object):
294
293
  """
295
294
  return self._exclude_positions
296
295
 
296
+ @property
297
+ def max_alts(self):
298
+ """Maximum number of alternative bases for a position."""
299
+ return self._max_alts
300
+
301
+ @max_alts.setter
302
+ def max_alts(self, max_alts):
303
+ self._max_alts = max_alts
304
+ function = self._rtqc.check_max_alts
305
+ if max_alts < 3:
306
+ self._rtqc.add(function)
307
+ else:
308
+ self._rtqc.discard(function)
309
+
297
310
  def exclude(self, regions):
298
311
  """
299
312
  Explicitly skip specified genomic regions.
@@ -149,12 +149,14 @@ class RTChecks(object):
149
149
  Returns:
150
150
  (bool): True if there are sufficient edits
151
151
  """
152
- for num_edits in bases.get_min_edits():
153
- if 0 < num_edits < rtools.min_edits_per_nucleotide:
152
+ for base in "ATCG":
153
+ if base == bases.ref:
154
+ continue
155
+ if bases[base] < rtools.min_edits_per_nucleotide:
154
156
  rtools.log(
155
157
  Logger.debug_level,
156
158
  'DISCARDING COLUMN edits={} < {}',
157
- num_edits,
159
+ bases[base],
158
160
  rtools.min_edits_per_nucleotide,
159
161
  )
160
162
  return False
@@ -272,3 +274,26 @@ class RTChecks(object):
272
274
  )
273
275
  return False
274
276
  return True
277
+
278
+ def check_max_alts(self, bases, rtools):
279
+ """
280
+ Check that there are no more than a max number of alts.
281
+
282
+ Parameters:
283
+ bases (CompiledPosition): Base position under analysis
284
+ rtools (REDItools): Object running the analysis
285
+
286
+ Returns:
287
+ (bool): True if there are n or fewer alts
288
+ """
289
+
290
+ alts = bases.get_variants()
291
+ if len(alts) > rtools.max_alts:
292
+ rtools.log(
293
+ Logger.debug_level,
294
+ 'DISCARD COLUMN alts={} > {}',
295
+ len(alts),
296
+ rtools.max_alts,
297
+ )
298
+ return False
299
+ return True
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes