2 usage: python $ERANGEPATH/findall.py label samplerdsfile regionoutfile
3 [--control controlrdsfile] [--minimum minHits] [--ratio minRatio]
4 [--spacing maxSpacing] [--listPeak] [--shift #bp | learn] [--learnFold num]
5 [--noshift] [--autoshift] [--reportshift] [--nomulti] [--minPlus fraction]
6 [--maxPlus fraction] [--leftPlus fraction] [--minPeak RPM] [--raw]
7 [--revbackground] [--pvalue self|back|none] [--nodirectionality]
8 [--strandfilter plus/minus] [--trimvalue percent] [--notrim]
9 [--cache pages] [--log altlogfile] [--flag aflag] [--append] [--RNA]
11 where values in brackets are optional and label is an arbitrary string.
13 Use -ratio (default 4 fold) to set the minimum fold enrichment
14 over the control, -minimum (default 4) is the minimum number of reads
15 (RPM) within the region, and -spacing (default readlen) to set the maximum
16 distance between reads in the region. -listPeak lists the peak of the
17 region. Peaks mut be higher than -minPeak (default 0.5 RPM).
18 Pvalues are calculated from the sample (change with -pvalue),
19 unless the -revbackground flag and a control RDS file are provided.
21 By default, all numbers and parameters are on a reads per
22 million (RPM) basis. -raw will treat all settings, ratios and reported
23 numbers as raw counts rather than RPM. Use -notrim to turn off region
24 trimming and -trimvalue to control trimming (default 10% of peak signal)
26 The peak finder uses minimal directionality information that can
27 be turned off with -nodirectionality ; the fraction of + strand reads
28 required to be to the left of the peak (default 0.3) can be set with
29 -leftPlus ; -minPlus and -maxPlus change the minimum/maximum fraction
30 of plus reads in a region, which (defaults 0.25 and 0.75, respectively).
32 Use -shift to shift reads either by half the expected
33 fragment length (default 0 bp) or '-shift learn ' to learn the shift
34 based on the first chromosome. If you prefer to learn the shift
35 manually, use -autoshift to calculate a per-region shift value, which
36 can be reported using -reportshift. -strandfilter should only be used
37 when explicitely calling unshifted stranded peaks from non-ChIP-seq
38 data such as directional RNA-seq. regionoutfile is written over by
39 default unless given the -append flag.
52 from commoncode import writeLog, findPeak, getBestShiftForRegion, getConfigParser, getConfigOption, getConfigIntOption, getConfigFloatOption, getConfigBoolOption
57 versionString = "findall: version 3.2"
69 (options, args) = parser.parse_args(argv[1:])
79 findall(factor, hitfile, outfilename, options.minHits, options.minRatio, options.maxSpacing, options.listPeak, options.shift,
80 options.stringency, options.noshift, options.autoshift, options.reportshift,
81 options.minPlusRatio, options.maxPlusRatio, options.leftPlusRatio, options.minPeak,
82 options.normalize, options.logfilename, options.withFlag, options.doDirectionality,
83 options.trimValue, options.doTrim, options.doAppend, options.rnaSettings,
84 options.cachePages, options.ptype, options.mockfile, options.doRevBackground, options.noMulti,
85 options.strandfilter, options.combine5p)
91 parser = optparse.OptionParser(usage=usage)
92 parser.add_option("--control", dest="mockfile")
93 parser.add_option("--minimum", type="float", dest="minHits")
94 parser.add_option("--ratio", type="float", dest="minRatio")
95 parser.add_option("--spacing", type="int", dest="maxSpacing")
96 parser.add_option("--listPeak", action="store_true", dest="listPeak")
97 parser.add_option("--shift", dest="shift")
98 parser.add_option("--learnFold", type="float", dest="stringency")
99 parser.add_option("--noshift", action="store_true", dest="noShift")
100 parser.add_option("--autoshift", action="store_true", dest="autoshift")
101 parser.add_option("--reportshift", action="store_true", dest="reportshift")
102 parser.add_option("--nomulti", action="store_true", dest="noMulti")
103 parser.add_option("--minPlus", type="float", dest="minPlusRatio")
104 parser.add_option("--maxPlus", type="float", dest="maxPlusRatio")
105 parser.add_option("--leftPlus", type="float", dest="leftPlusRatio")
106 parser.add_option("--minPeak", type="float", dest="minPeak")
107 parser.add_option("--raw", action="store_false", dest="normalize")
108 parser.add_option("--revbackground", action="store_true", dest="doRevBackground")
109 parser.add_option("--pvalue", dest="ptype")
110 parser.add_option("--nodirectionality", action="store_false", dest="doDirectionality")
111 parser.add_option("--strandfilter", dest="strandfilter")
112 parser.add_option("--trimvalue", type="float", dest="trimValue")
113 parser.add_option("--notrim", action="store_false", dest="doTrim")
114 parser.add_option("--cache", type="int", dest="cachePages")
115 parser.add_option("--log", dest="logfilename")
116 parser.add_option("--flag", dest="withFlag")
117 parser.add_option("--append", action="store_true", dest="doAppend")
118 parser.add_option("--RNA", action="store_true", dest="rnaSettings")
119 parser.add_option("--combine5p", action="store_true", dest="combine5p")
121 configParser = getConfigParser()
123 minHits = getConfigFloatOption(configParser, section, "minHits", 4.0)
124 minRatio = getConfigFloatOption(configParser, section, "minRatio", 4.0)
125 maxSpacing = getConfigIntOption(configParser, section, "maxSpacing", 50)
126 listPeak = getConfigBoolOption(configParser, section, "listPeak", False)
127 shift = getConfigOption(configParser, section, "shift", None)
128 stringency = getConfigFloatOption(configParser, section, "stringency", 4.0)
129 noshift = getConfigBoolOption(configParser, section, "noshift", False)
130 autoshift = getConfigBoolOption(configParser, section, "autoshift", False)
131 reportshift = getConfigBoolOption(configParser, section, "reportshift", False)
132 minPlusRatio = getConfigFloatOption(configParser, section, "minPlusRatio", 0.25)
133 maxPlusRatio = getConfigFloatOption(configParser, section, "maxPlusRatio", 0.75)
134 leftPlusRatio = getConfigFloatOption(configParser, section, "leftPlusRatio", 0.3)
135 minPeak = getConfigFloatOption(configParser, section, "minPeak", 0.5)
136 normalize = getConfigBoolOption(configParser, section, "normalize", True)
137 logfilename = getConfigOption(configParser, section, "logfilename", "findall.log")
138 withFlag = getConfigOption(configParser, section, "withFlag", "")
139 doDirectionality = getConfigBoolOption(configParser, section, "doDirectionality", True)
140 trimValue = getConfigOption(configParser, section, "trimValue", None)
141 doTrim = getConfigBoolOption(configParser, section, "doTrim", True)
142 doAppend = getConfigBoolOption(configParser, section, "doAppend", False)
143 rnaSettings = getConfigBoolOption(configParser, section, "rnaSettings", False)
144 cachePages = getConfigOption(configParser, section, "cachePages", None)
145 ptype = getConfigOption(configParser, section, "ptype", None)
146 mockfile = getConfigOption(configParser, section, "mockfile", None)
147 doRevBackground = getConfigBoolOption(configParser, section, "doRevBackground", False)
148 noMulti = getConfigBoolOption(configParser, section, "noMulti", False)
149 strandfilter = getConfigOption(configParser, section, "strandfilter", None)
150 combine5p = getConfigBoolOption(configParser, section, "combine5p", False)
152 parser.set_defaults(minHits=minHits, minRatio=minRatio, maxSpacing=maxSpacing, listPeak=listPeak, shift=shift,
153 stringency=stringency, noshift=noshift, autoshift=autoshift, reportshift=reportshift,
154 minPlusRatio=minPlusRatio, maxPlusRatio=maxPlusRatio, leftPlusRatio=leftPlusRatio, minPeak=minPeak,
155 normalize=normalize, logfilename=logfilename, withFlag=withFlag, doDirectionality=doDirectionality,
156 trimValue=trimValue, doTrim=doTrim, doAppend=doAppend, rnaSettings=rnaSettings,
157 cachePages=cachePages, ptype=ptype, mockfile=mockfile, doRevBackground=doRevBackground, noMulti=noMulti,
158 strandfilter=strandfilter, combine5p=combine5p)
163 def findall(factor, hitfile, outfilename, minHits=4.0, minRatio=4.0, maxSpacing=50, listPeak=False, shift=None,
164 stringency=4.0, noshift=False, autoshift=False, reportshift=False,
165 minPlusRatio=0.25, maxPlusRatio=0.75, leftPlusRatio=0.3, minPeak=0.5,
166 normalize=True, logfilename="findall.log", withFlag="", doDirectionality=True,
167 trimValue=None, doTrim=True, doAppend=False, rnaSettings=False,
168 cachePages=None, ptype=None, mockfile=None, doRevBackground=False, noMulti=False,
169 strandfilter=None, combine5p=False):
171 shiftValue = determineShiftValue(autoshift, shift, noshift, rnaSettings)
173 if mockfile is not None:
177 print "Swapping IP and background to calculate FDR"
181 if ptype is not None:
182 ptype = ptype.upper()
188 elif ptype == "SELF":
190 elif ptype == "BACK":
191 if doControl and doRevBackground:
194 print "must have a control dataset and -revbackground for pValue type 'back'"
196 print "could not use pValue type : %s" % ptype
201 print "restrict to flag = %s" % withFlag
205 print "using unique reads only"
209 print "using settings appropriate for RNA: -nodirectionality -notrim -noshift"
211 doDirectionality = False
214 if strandfilter is not None:
215 if strandfilter == "plus":
219 print "only analyzing reads on the plus strand"
220 elif strandfilter == "minus":
224 print "only analyzing reads on the minus strand"
226 stringency = max(stringency, 1.0)
227 writeLog(logfilename, versionString, string.join(sys.argv[1:]))
228 if cachePages is not None:
237 mockRDS = ReadDataset.ReadDataset(mockfile, verbose=True, cache=doCache)
239 if cachePages > mockRDS.getDefaultCacheSize():
240 mockRDS.setDBcache(cachePages)
243 hitRDS = ReadDataset.ReadDataset(hitfile, verbose=True, cache=doCache)
244 readlen = hitRDS.getReadSize()
248 if cachePages > hitRDS.getDefaultCacheSize():
249 hitRDS.setDBcache(cachePages)
251 if trimValue is not None:
252 trimValue = float(trimValue) / 100.
253 trimString = "%2.1f%s" % ((100. * trimValue), "%")
266 outfile = open(outfilename, fileMode)
267 outfile.write("#ERANGE %s\n" % versionString)
269 mockRDSsize = len(mockRDS) / 1000000.
270 controlSampleString = "\t%s (%.1f M reads)" % (mockfile, mockRDSsize)
273 controlSampleString = " none"
275 hitRDSsize = len(hitRDS) / 1000000.
276 outfile.write("#enriched sample:\t%s (%.1f M reads)\n#control sample:%s\n" % (hitfile, hitRDSsize, controlSampleString))
279 outfile.write("#restrict to Flag = %s\n" % withFlag)
281 print "\nenforceDirectionality=%s listPeak=%s nomulti=%s cache=%s " % (doDirectionality, listPeak, noMulti, doCache)
282 print "spacing<%d minimum>%.1f ratio>%.1f minPeak=%.1f\ttrimmed=%s\tstrand=%s" % (maxSpacing, minHits, minRatio, minPeak, trimString, stranded)
283 print "minPlus=%.2f maxPlus=%.2f leftPlus=%.2f shift=%s pvalue=%s" % (minPlusRatio, maxPlusRatio, leftPlusRatio, str(shiftValue), pValueType)
285 outfile.write("#enforceDirectionality=%s listPeak=%s nomulti=%s cache=%s\n" % (doDirectionality, listPeak, noMulti, doCache))
286 outfile.write("#spacing<%d minimum>%.1f ratio>%.1f minPeak=%.1f trimmed=%s strand=%s\n" % (maxSpacing, minHits, minRatio, minPeak, trimString, stranded))
287 outfile.write("#minPlus=%.2f maxPlus=%.2f leftPlus=%.2f shift=%s pvalue=%s\n" % (minPlusRatio, maxPlusRatio, leftPlusRatio, str(shiftValue), pValueType))
289 print "Normalizing to RPM"
294 headerList = ["#regionID\tchrom\tstart\tstop", countLabel, "fold\tmulti%"]
296 headerList.append("plus%\tleftPlus%")
299 headerList.append("peakPos\tpeakHeight")
302 headerList.append("readShift")
305 headerList.append("pValue")
307 headline = string.join(headerList, "\t")
308 print >> outfile, headline
310 statistics = {"index": 0,
317 if minRatio < minPeak:
320 hitChromList = hitRDS.getChromosomes()
322 mockChromList = mockRDS.getChromosomes()
330 mockSampleSize = mockRDSsize
332 hitSampleSize = hitRDSsize
336 for chromosome in hitChromList:
337 if doNotProcessChromosome(chromosome, doControl, mockChromList):
340 print "chromosome %s" % (chromosome)
341 hitDict = hitRDS.getReadsDict(fullChrom=True, chrom=chromosome, flag=withFlag, withWeight=True,
342 doMulti=useMulti, findallOptimize=True, strand=stranded,
344 maxCoord = hitRDS.getMaxCoordinate(chromosome, doMulti=useMulti)
345 if shiftValue == "learn":
346 shiftValue = learnShift(hitDict, hitSampleSize, mockRDS, chromosome, doControl, useMulti, normalize,
347 mockSampleSize, minRatio, maxSpacing, maxCoord, stringency, readlen, minHits,
348 logfilename, outfile, outfilename)
350 regionStats, allRegionWeights, outregions = locateRegions(hitRDS, hitSampleSize, mockRDS, mockSampleSize,
351 chromosome, useMulti, normalize, maxSpacing,
352 doDirectionality, doTrim, minHits, minRatio,
353 readlen, shiftValue, minPeak, minPlusRatio,
354 maxPlusRatio, leftPlusRatio, listPeak, noMulti,
355 doControl, factor, trimValue, outputRegionList=True)
357 statistics["index"] += regionStats["index"]
358 statistics["total"] += regionStats["total"]
359 statistics["failed"] += regionStats["failed"]
360 if not doRevBackground:
362 p, poissonmean = calculatePValue(allRegionWeights)
365 shiftModeValue = writeRegionsToFile(outfile, outregions, doPvalue, p, poissonmean, reportshift, shiftValue)
368 #now do background swapping the two samples around
369 if mockRDS is not None:
370 print "calculating background..."
371 backgroundTrimValue = 1/20.
372 backgroundRegionStats, backgroundRegionWeights = locateRegions(mockRDS, mockSampleSize, hitRDS, hitSampleSize,
373 chromosome, useMulti, normalize, maxSpacing,
374 doDirectionality, doTrim, minHits, minRatio,
375 readlen, shiftValue, minPeak, minPlusRatio,
376 maxPlusRatio, leftPlusRatio, listPeak, noMulti,
377 doControl, factor, backgroundTrimValue)
379 statistics["mIndex"] += backgroundRegionStats["index"]
380 statistics["mTotal"] += backgroundRegionStats["total"]
381 statistics["failed"] += backgroundRegionStats["failed"]
382 print statistics["mIndex"], statistics["mTotal"]
384 if pValueType == "self":
385 p, poissonmean = calculatePValue(allRegionWeights)
387 p, poissonmean = calculatePValue(backgroundRegionWeights)
390 shiftModeValue = writeRegionsToFile(outfile, outregions, doPvalue, p, poissonmean, reportshift, shiftValue)
392 footer = getFooter(statistics, doDirectionality, doRevBackground, shiftValue, reportshift, shiftModeValue)
394 outfile.write(footer)
397 writeLog(logfilename, versionString, "%s%s" % (outfilename, footer.replace("\n#", " | ")))
400 def determineShiftValue(autoshift, shift, noshift, rnaSettings):
405 if shift is not None:
407 shiftValue = int(shift)
411 print "Will try to learn shift"
413 if noshift or rnaSettings:
419 def doNotProcessChromosome(chromosome, doControl, mockChromList):
420 skipChromosome = False
421 if chromosome == "chrM":
422 skipChromosome = True
424 if doControl and (chromosome not in mockChromList):
425 skipChromosome = True
427 return skipChromosome
430 def calculatePValue(dataList):
432 listSize = float(len(dataList))
434 poissonmean = sum(dataList) / listSize
435 except ZeroDivisionError:
438 print "Poisson n=%d, p=%f" % (listSize, poissonmean)
439 p = math.exp(-poissonmean)
441 return p, poissonmean
444 def learnShift(hitDict, hitSampleSize, mockRDS, chrom, doControl, useMulti, normalize, mockSampleSize, minRatio, maxSpacing, maxCoord,
445 stringency, readlen, minHits, logfilename, outfile, outfilename, minSites=30):
447 print "learning shift.... will need at least %d training sites" % minSites
448 previousHit = -1 * maxSpacing
455 for read in hitDict[chrom]:
457 sense = read["sense"]
458 weight = read["weight"]
459 if abs(pos - previousHit) > maxSpacing or pos == maxCoord:
462 sumAll /= hitSampleSize
464 regionStart = hitList[0]
465 regionStop = hitList[-1]
466 regionLength = regionStop - regionStart
467 # we're going to require stringent settings
468 if sumAll >= stringency * minHits and numStarts > stringency * minRatio and regionLength > stringency * readlen:
469 foldRatio = getFoldRatio(mockRDS, chrom, regionStart, regionStop, doControl, useMulti, normalize, mockSampleSize, sumAll, minRatio)
471 if foldRatio >= minRatio:
472 localshift = getBestShiftForRegion(readList, regionStart, regionLength, useWeight=True)
474 shiftDict[localshift] += 1
476 shiftDict[localshift] = 1
485 if pos not in hitList:
489 totalWeight += weight
490 readList.append({"start": pos, "sense": sense, "weight": weight})
495 learningSettings = ["#learn: stringency=%.2f min_signal=%2.f min_ratio=%.2f min_region_size=%d" % (stringency, stringency * minHits,
496 stringency * minRatio, stringency * readlen),
497 "#number of training examples: %d" % count]
498 outline = string.join(learningSettings, "\n")
500 writeLog(logfilename, versionString, "%s%s" % (outfilename, outline))
502 outline = "#too few training examples to pick a shiftValue - defaulting to 0\n#consider picking a lower minimum or threshold"
503 print >> outfile, outline
504 writeLog(logfilename, versionString, "%s%s" % (outfilename, outline))
507 for shift in sorted(shiftDict):
508 if shiftDict[shift] > bestCount:
510 bestCount = shiftDict[shift]
512 shiftValue = bestShift
515 outline = "#picked shiftValue to be %d" % shiftValue
517 print >> outfile, outline
518 writeLog(logfilename, versionString, "%s%s" % (outfilename, outline))
523 def getFoldRatio(rds, chrom, start, stop, doControl, useMulti, normalize, sampleSize, sumAll, minRatio):
524 if doControl and rds is not None:
525 foldRatio = getFoldRatioFromRDS(rds, chrom, start, stop, useMulti, normalize, sampleSize, sumAll)
532 def getFoldRatioFromRDS(rds, chrom, start, stop, useMulti, normalize, sampleSize, sumAll):
533 numMock = 1. + rds.getCounts(chrom, start, stop, uniqs=True, multi=useMulti, splices=False, reportCombined=True)
535 numMock /= sampleSize
537 foldRatio = sumAll / numMock
542 def locateRegions(rds, rdsSampleSize, referenceRDS, referenceSampleSize, chrom, useMulti,
543 normalizeToRPM, maxSpacing, doDirectionality, doTrim, minHits, minRatio, readlen,
544 shiftValue, minPeak, minPlusRatio, maxPlusRatio, leftPlusRatio, listPeak,
545 noMulti, doControl, factor, trimValue, outputRegionList=False):
548 totalRegionWeight = 0
550 previousHit = - 1 * maxSpacing
551 currentHitList = [-1]
552 currentTotalWeight = 0
553 currentUniqReadCount = 0
558 hitDict = rds.getReadsDict(fullChrom=True, chrom=chrom, withWeight=True, doMulti=useMulti, findallOptimize=True)
559 maxCoord = rds.getMaxCoordinate(chrom, doMulti=useMulti)
560 for read in hitDict[chrom]:
562 sense = read["sense"]
563 weight = read["weight"]
564 if abs(pos - previousHit) > maxSpacing or pos == maxCoord:
565 sumAll = currentTotalWeight
567 sumAll /= rdsSampleSize
569 regionStart = currentHitList[0]
570 regionStop = currentHitList[-1]
571 regionWeights.append(int(sumAll))
572 if sumAll >= minHits and numStarts > minRatio and (regionStop - regionStart) > readlen:
574 foldRatio = getFoldRatio(referenceRDS, chrom, regionStart, regionStop, doControl, useMulti, normalizeToRPM, referenceSampleSize, sumAll, minRatio)
575 if foldRatio >= minRatio:
576 # first pass, with absolute numbers
577 peak = findPeak(currentReadList, regionStart, regionStop - regionStart, readlen, doWeight=True, leftPlus=doDirectionality, shift=shiftValue)
579 bestPos = peak.topPos[0]
580 numHits = peak.numHits
581 peakScore = peak.smoothArray[bestPos]
582 numPlus = peak.numPlus
584 numLeft = peak.numLeftPlus
586 peakScore /= rdsSampleSize
589 minSignalThresh = trimValue * peakScore
591 stop = regionStop - regionStart - 1
593 while not startFound:
594 if peak.smoothArray[start] >= minSignalThresh or start == bestPos:
601 if peak.smoothArray[stop] >= minSignalThresh or stop == bestPos:
606 regionStop = regionStart + stop
608 trimPeak = findPeak(currentReadList, regionStart, regionStop - regionStart, readlen, doWeight=True, leftPlus=doDirectionality, shift=shift)
610 sumAll = trimPeak.numHits
611 numPlus = trimPeak.numPlus
612 numLeft = trimPeak.numLeftPlus
614 sumAll /= rdsSampleSize
616 foldRatio = getFoldRatio(referenceRDS, chrom, regionStart, regionStop, doControl, useMulti, normalizeToRPM, referenceSampleSize, sumAll, minRatio)
618 sumMulti = rds.getCounts(chrom, regionStart, regionStop, uniqs=False, multi=useMulti, splices=False, reportCombined=True)
619 # just in case it changed, use latest data
621 bestPos = trimPeak.topPos[0]
622 peakScore = trimPeak.smoothArray[bestPos]
627 peakScore /= rdsSampleSize
629 elif outputRegionList:
630 sumMulti = currentTotalWeight - currentUniqReadCount
634 sumMulti /= rdsSampleSize
637 multiP = 100. * (sumMulti / sumAll)
644 # check that we still pass threshold
645 if sumAll >= minHits and foldRatio >= minRatio and (regionStop - regionStart) > readlen:
646 plusRatio = float(numPlus)/numHits
647 if peakScore >= minPeak and minPlusRatio <= plusRatio <= maxPlusRatio:
651 peakDescription = "\t%d\t%.1f" % (regionStart + bestPos, peakScore)
654 if leftPlusRatio < numLeft / numPlus:
657 plusP = plusRatio * 100.
658 leftP = 100. * numLeft / numPlus
659 # we have a region that passes all criteria
660 region = Region.DirectionalRegion(regionStart, regionStop + readlen - 1,
661 factor, index, chrom, sumAll,
662 foldRatio, multiP, plusP, leftP,
663 peakDescription, shift)
664 outregions.append(region)
666 totalRegionWeight += sumAll
670 # we have a region, but didn't check for directionality
672 totalRegionWeight += sumAll
674 region = Region.Region(regionStart, regionStop + readlen - 1, factor, index, chrom,
675 sumAll, foldRatio, multiP, peakDescription, shift)
676 outregions.append(region)
679 currentTotalWeight = 0
680 currentUniqReadCount = 0
684 if pos not in currentHitList:
687 currentHitList.append(pos)
688 currentTotalWeight += weight
690 currentUniqReadCount += 1
692 currentReadList.append({"start": pos, "sense": sense, "weight": weight})
695 statistics = {"index": index,
696 "total": totalRegionWeight,
697 "failed": failedCounter
701 return statistics, regionWeights, outregions
703 return statistics, regionWeights
706 def writeRegionsToFile(outfile, outregions, doPvalue, pValue, poissonmean, reportshift, shiftValue):
709 for region in outregions:
710 # iterative poisson from http://stackoverflow.com/questions/280797?sort=newest
712 outputList = [region.printRegionWithShift()]
713 if shiftValue == "auto":
715 shiftDict[region.shift] += 1
717 shiftDict[region.shift] = 1
719 outputList = [region.printRegion()]
721 # iterative poisson from http://stackoverflow.com/questions/280797?sort=newest
723 sumAll = int(region.numReads)
724 for i in xrange(sumAll):
725 pValue *= poissonmean
728 outputList.append("%1.2g" % pValue)
730 outline = string.join(outputList, "\t")
732 print >> outfile, outline
735 for shift in sorted(shiftDict):
736 if shiftDict[shift] > bestCount:
738 bestCount = shiftDict[shift]
743 def getFooter(stats, doDirectionality, doRevBackground, shiftValue, reportshift, shiftModeValue):
744 footerList = ["#stats:\t%.1f RPM in %d regions" % (stats["total"], stats["index"])]
746 footerList.append("#\t\t%d additional regions failed directionality filter" % stats["failed"])
750 percent = min(100. * (float(stats["mIndex"])/stats["index"]), 100)
751 except (ValueError, ZeroDivisionError):
754 footerList.append("#%d regions (%.1f RPM) found in background (FDR = %.2f percent)" % (stats["mIndex"], stats["mTotal"], percent))
756 if shiftValue == "auto" and reportshift:
757 footerList.append("#mode of shift values: %d" % shiftModeValue)
759 footer = string.join(footerList, "\n")
763 if __name__ == "__main__":