Skip to content

Commit 3df381c

Browse files
authored
Merge pull request #1395 from deeptools/pytest_updates
Pytest updates
2 parents 0807d67 + 9eb0c88 commit 3df381c

36 files changed

+775
-573
lines changed

.github/workflows/test.yml

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,30 +48,55 @@ jobs:
4848
with:
4949
python-version: ${{ matrix.python-version }}
5050
cache: 'pip'
51-
- name: pip install
51+
- name: Install Rust
52+
uses: actions-rust-lang/setup-rust-toolchain@v1
53+
- name: build deeptools
5254
run: |
53-
pip install .[actions]
54-
- name: Test deepTools
55+
python -m venv venv
56+
source venv/bin/activate
57+
pip install maturin
58+
maturin develop --release --extras actions
59+
- name: test deeptools
5560
run: |
61+
source venv/bin/activate
5662
pytest -v
57-
- name: Build wheel
63+
- name: build wheel
5864
run: |
65+
source venv/bin/activate
5966
python -m build
60-
- name: Test wheel
67+
- name: test wheel
6168
run: |
69+
source venv/bin/activate
6270
pip install dist/*whl
6371
build-osx:
6472
name: Test on OSX
6573
runs-on: macOS-latest
74+
strategy:
75+
matrix:
76+
python-version: ['3.9','3.10', '3.11', '3.12']
6677
steps:
67-
- uses: actions/checkout@v4
68-
- uses: actions/setup-python@v5
69-
with:
70-
python-version: '3.12'
71-
cache: 'pip'
72-
- name: pip install
73-
run: |
74-
pip install .[actions]
75-
- name: Test deepTools
76-
run: |
77-
pytest -v
78+
- uses: actions/checkout@v4
79+
- uses: actions/setup-python@v5
80+
with:
81+
python-version: ${{ matrix.python-version }}
82+
cache: 'pip'
83+
- name: Install Rust
84+
uses: actions-rust-lang/setup-rust-toolchain@v1
85+
- name: build deeptools
86+
run: |
87+
python -m venv venv
88+
source venv/bin/activate
89+
pip install maturin
90+
maturin develop --release --extras actions
91+
- name: test deeptools
92+
run: |
93+
source venv/bin/activate
94+
pytest -v
95+
- name: build wheel
96+
run: |
97+
source venv/bin/activate
98+
python -m build
99+
- name: test wheel
100+
run: |
101+
source venv/bin/activate
102+
pip install dist/*whl

docs/content/changelog.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,13 @@ Core
3838
- --quiet / -q option no longer exists.
3939
- bed files in computeMatrix no longer support '#' to define groups.
4040
- 'chromosome matching' i.e. chr1 <-> 1, chrMT <-> MT is no longer performed.
41-
41+
- metagene mode erroneously 'nan'ed the before and after values (if they fell outside of the feature). This is fixed now.
42+
- Rounding bahvior in matrix output only two decimals now, unscaled 5 and unscaled 3 prime are now strictly separated from the rest of the scaled region (for value calculation).
43+
4244
* normalization
4345
- Exactscaling is no longer an option, it's always performed.
46+
- SES option in bamCompare mode is no longer available.
47+
- blackList filtering is now performed on a position-based level. Meaning reads that overlap partially with the blacklist can still contribute to the signal.
4448

4549
* alignmentSieve
4650
- options label, smartLabels, genomeChunkLength are removed.

pydeeptools/deeptools/bamCompare.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ def main(args=None):
295295
extendReads=args.extendReads,
296296
blackListFileName=args.blackListFileName,
297297
minMappingQuality=args.minMappingQuality,
298-
ignoreDuplicates=args.ignoreDuplicates,
298+
ignoreDuplicates=False,
299299
center_read=args.centerReads,
300300
zerosToNans=args.skipNonCoveredRegions,
301301
skipZeroOverZero=args.skipZeroOverZero,

pydeeptools/deeptools/bamCompare2.py

Lines changed: 31 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from deeptools import parserCommon
33
from deeptools.hp import r_bamcompare
44
import signal
5+
import sys
56

67
def parseArguments():
78
parentParser = parserCommon.getParentArgParse()
@@ -73,7 +74,7 @@ def getOptionalArgs():
7374
'for sequencing depth differences between the samples. '
7475
'As an alternative, this can be set to None and an option from '
7576
'--normalizeUsing <method> can be used. (Default: %(default)s)',
76-
choices=['readCount', 'SES', 'None'],
77+
choices=['readCount', 'None'],
7778
default='readCount')
7879

7980
optional.add_argument('--sampleLength', '-l',
@@ -126,7 +127,6 @@ def getOptionalArgs():
126127
'values (the first value is used as the numerator '
127128
'pseudocount and the second the denominator pseudocount). (Default: %(default)s)',
128129
default=[1],
129-
type=float,
130130
nargs='+',
131131
action=parserCommon.requiredLength(1, 2),
132132
required=False)
@@ -158,70 +158,8 @@ def process_args(args=None):
158158
if not args.ignoreForNormalization:
159159
args.ignoreForNormalization = []
160160

161-
if not isinstance(args.pseudocount, list):
162-
args.pseudocount = [args.pseudocount]
163-
164-
if len(args.pseudocount) == 1:
165-
args.pseudocount *= 2
166-
167161
return args
168162

169-
# get_scale_factors function is used for scaling in bamCompare
170-
# while get_scale_factor is used for depth normalization
171-
172-
173-
def get_scale_factors(args, statsList, mappedList):
174-
175-
if args.scaleFactors:
176-
scale_factors = list(map(float, args.scaleFactors.split(":")))
177-
elif args.scaleFactorsMethod == 'SES':
178-
scalefactors_dict = estimateScaleFactor(
179-
[args.bamfile1, args.bamfile2],
180-
args.sampleLength, args.numberOfSamples,
181-
1,
182-
mappingStatsList=mappedList,
183-
blackListFileName=args.blackListFileName,
184-
numberOfProcessors=args.numberOfProcessors,
185-
verbose=args.verbose,
186-
chrsToSkip=args.ignoreForNormalization)
187-
188-
scale_factors = scalefactors_dict['size_factors']
189-
190-
if args.verbose:
191-
print("Size factors using SES: {}".format(scale_factors))
192-
print("%s regions of size %s where used " %
193-
(scalefactors_dict['sites_sampled'],
194-
args.sampleLength))
195-
196-
print("ignoring filtering/blacklists, size factors if the number of mapped "
197-
"reads would have been used:")
198-
print(tuple(
199-
float(min(mappedList)) / np.array(mappedList)))
200-
201-
elif args.scaleFactorsMethod == 'readCount':
202-
# change the scaleFactor to 1.0
203-
args.scaleFactor = 1.0
204-
# get num of kept reads for bam file 1
205-
args.bam = args.bamfile1
206-
bam1_mapped, _ = get_num_kept_reads(args, statsList[0])
207-
# get num of kept reads for bam file 2
208-
args.bam = args.bamfile2
209-
bam2_mapped, _ = get_num_kept_reads(args, statsList[1])
210-
211-
mapped_reads = [bam1_mapped, bam2_mapped]
212-
213-
# new scale_factors (relative to min of two bams)
214-
scale_factors = float(min(bam1_mapped, bam2_mapped)) / np.array(mapped_reads)
215-
if args.verbose:
216-
print("Size factors using total number "
217-
"of mapped reads: {}".format(scale_factors))
218-
219-
elif args.scaleFactorsMethod == 'None':
220-
scale_factors = None
221-
222-
return scale_factors
223-
224-
225163
def main(args=None):
226164
"""
227165
The algorithm is composed of two steps.
@@ -274,8 +212,29 @@ def main(args=None):
274212
print("Please only provide one blacklist file.")
275213
sys.exit()
276214
args.blackListFileName = args.blackListFileName[0]
277-
278-
args.pseudocount = 1
215+
if args.scaleFactors:
216+
if len(args.scaleFactors.split(":")) == 2:
217+
args.sf1 = float(args.scaleFactors.split(":")[0])
218+
args.sf2 = float(args.scaleFactors.split(":")[0])
219+
elif len(args.scaleFactors.split(":")) == 1:
220+
args.sf1 = float(args.scaleFactors.split(":")[0])
221+
args.sf2 = float(args.scaleFactors.split(":")[0])
222+
else:
223+
print("Please provide one scale factor, or two by a ':'.")
224+
sys.exit()
225+
else:
226+
args.sf1 = 0.0
227+
args.sf2 = 0.0
228+
if len(args.pseudocount) == 1:
229+
args.pseudocount1 = float(args.pseudocount[0])
230+
args.pseudocount2 = float(args.pseudocount[0])
231+
elif len(args.pseudocount) == 2:
232+
args.pseudocount1 = float(args.pseudocount[0])
233+
args.pseudocount2 = float(args.pseudocount[1])
234+
else:
235+
print(f"Pseudocounts should be either one or two values. Not {args.pseudocount}")
236+
sys.exit()
237+
print(args)
279238
signal.signal(signal.SIGINT, signal.SIG_DFL)
280239
r_bamcompare(
281240
args.bamfile1, # bam file 1
@@ -285,8 +244,11 @@ def main(args=None):
285244
args.normalizeUsing, # normalization method
286245
args.effectiveGenomeSize, # effective genome size
287246
args.scaleFactorsMethod, # scaling method
247+
args.sf1,
248+
args.sf2,
288249
args.operation,
289-
args.pseudocount,
250+
args.pseudocount1,
251+
args.pseudocount2,
290252
args.extendReads,
291253
args.extendReadsLen,
292254
args.centerReads,
@@ -298,6 +260,8 @@ def main(args=None):
298260
args.maxFragmentLength,
299261
args.numberOfProcessors, # threads
300262
args.ignoreForNormalization,
263+
args.skipNonCoveredRegions,
264+
args.skipZeroOverZero,
301265
args.binSize, # bin size
302266
args.region, # regions
303267
args.verbose, # verbose

pydeeptools/deeptools/bamCoverage.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ def main(args=None):
195195
numberOfProcessors=args.numberOfProcessors,
196196
extendReads=args.extendReads,
197197
minMappingQuality=args.minMappingQuality,
198-
ignoreDuplicates=args.ignoreDuplicates,
198+
ignoreDuplicates=False, # ignore duplicates is no longer available.
199199
center_read=args.centerReads,
200200
zerosToNans=args.skipNonCoveredRegions,
201201
samFlag_include=args.samFlagInclude,
@@ -222,7 +222,7 @@ def main(args=None):
222222
numberOfProcessors=args.numberOfProcessors,
223223
extendReads=args.extendReads,
224224
minMappingQuality=args.minMappingQuality,
225-
ignoreDuplicates=args.ignoreDuplicates,
225+
ignoreDuplicates=False, # ignore duplicates is no longer available.
226226
center_read=args.centerReads,
227227
zerosToNans=args.skipNonCoveredRegions,
228228
samFlag_include=args.samFlagInclude,
@@ -242,7 +242,7 @@ def main(args=None):
242242
numberOfProcessors=args.numberOfProcessors,
243243
extendReads=args.extendReads,
244244
minMappingQuality=args.minMappingQuality,
245-
ignoreDuplicates=args.ignoreDuplicates,
245+
ignoreDuplicates=False, # ignore duplicates is no longer available.
246246
center_read=args.centerReads,
247247
zerosToNans=args.skipNonCoveredRegions,
248248
samFlag_include=args.samFlagInclude,

pydeeptools/deeptools/computeMatrix2.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from deeptools import parserCommon
66
from importlib.metadata import version
77
from deeptools.hp import r_computematrix
8+
import signal
89

910
def parse_arguments(args=None):
1011
parser = \
@@ -382,7 +383,7 @@ def main(args=None):
382383
'unscaled 5 prime': args.unscaled5prime,
383384
'unscaled 3 prime': args.unscaled3prime
384385
}
385-
# Assert all regions and scores exist
386+
signal.signal(signal.SIGINT, signal.SIG_DFL)
386387
r_computematrix(
387388
args.command,
388389
args.regionsFileName,

pydeeptools/deeptools/getScaleFactor.py

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,24 +59,24 @@ def getFractionKept_worker(chrom, start, end, bamFile, args, offset):
5959

6060
# get rid of duplicate reads that have same position on each of the
6161
# pairs
62-
if args.ignoreDuplicates:
63-
# Assuming more or less concordant reads, use the fragment bounds, otherwise the start positions
64-
if tLen >= 0:
65-
s = read.pos
66-
e = s + tLen
67-
else:
68-
s = read.pnext
69-
e = s - tLen
70-
if read.reference_id != read.next_reference_id:
71-
e = read.pnext
72-
if lpos is not None and lpos == read.reference_start \
73-
and (s, e, read.next_reference_id, read.is_reverse) in prev_pos:
74-
filtered += 1
75-
continue
76-
if lpos != read.reference_start:
77-
prev_pos.clear()
78-
lpos = read.reference_start
79-
prev_pos.add((s, e, read.next_reference_id, read.is_reverse))
62+
# if args.ignoreDuplicates:
63+
# # Assuming more or less concordant reads, use the fragment bounds, otherwise the start positions
64+
# if tLen >= 0:
65+
# s = read.pos
66+
# e = s + tLen
67+
# else:
68+
# s = read.pnext
69+
# e = s - tLen
70+
# if read.reference_id != read.next_reference_id:
71+
# e = read.pnext
72+
# if lpos is not None and lpos == read.reference_start \
73+
# and (s, e, read.next_reference_id, read.is_reverse) in prev_pos:
74+
# filtered += 1
75+
# continue
76+
# if lpos != read.reference_start:
77+
# prev_pos.clear()
78+
# lpos = read.reference_start
79+
# prev_pos.add((s, e, read.next_reference_id, read.is_reverse))
8080

8181
# If filterRNAstrand is in args, then filter accordingly
8282
# This is very similar to what's used in the get_fragment_from_read function in the filterRnaStrand class
@@ -146,8 +146,7 @@ def fraction_kept(args, stats):
146146
num_needed_to_sample = 0.1 * bam_mapped
147147
else:
148148
num_needed_to_sample = 1000000
149-
if args.exactScaling:
150-
num_needed_to_sample = bam_mapped
149+
num_needed_to_sample = bam_mapped
151150
if num_needed_to_sample == bam_mapped:
152151
distanceBetweenBins = 55000
153152
if args.ignoreForNormalization:

pydeeptools/deeptools/parserCommon.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,13 @@ def read_options():
7979
default=False,
8080
metavar="INT bp")
8181

82-
group.add_argument('--ignoreDuplicates',
83-
help='If set, reads that have the same orientation '
84-
'and start position will be considered only '
85-
'once. If reads are paired, the mate\'s position '
86-
'also has to coincide to ignore a read.',
87-
action='store_true'
88-
)
82+
# group.add_argument('--ignoreDuplicates',
83+
# help='If set, reads that have the same orientation '
84+
# 'and start position will be considered only '
85+
# 'once. If reads are paired, the mate\'s position '
86+
# 'also has to coincide to ignore a read.',
87+
# action='store_true'
88+
# )
8989

9090
group.add_argument('--minMappingQuality',
9191
metavar='INT',

pydeeptools/deeptools/plotCoverage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def main(args=None):
188188
blackListFileName=args.blackListFileName,
189189
extendReads=args.extendReads,
190190
minMappingQuality=args.minMappingQuality,
191-
ignoreDuplicates=args.ignoreDuplicates,
191+
ignoreDuplicates=False, # ignoreDuplicates is no longer supported.
192192
center_read=args.centerReads,
193193
samFlag_include=args.samFlagInclude,
194194
samFlag_exclude=args.samFlagExclude,

0 commit comments

Comments
 (0)