@@ -210,6 +210,8 @@ template doAssert(condition: bool, message: string) = # FIXME is this already in
210210 stderr.writeLine (" ERROR: " , message)
211211 quit (1 )
212212
213+
214+ # COVERAGE FUNCTIONS #
213215proc newCov (f = 0 , r = 0 ): coverage_t =
214216 coverage_t (forward: f, reverse: r)
215217
@@ -228,12 +230,24 @@ proc dec(c: var coverage_t, reverse=false) =
228230proc tot (c: coverage_t): int =
229231 c.forward + c.reverse
230232
233+ proc max (c1: coverage_t, c2: coverage_t): coverage_t =
234+ newCov (max (c1.forward, c2.forward), max (c1.reverse, c2.reverse))
235+ proc min (c1: coverage_t, c2: coverage_t): coverage_t =
236+ newCov (min (c1.forward, c2.forward), min (c1.reverse, c2.reverse))
237+ proc `+` (c1: coverage_t, c2: coverage_t): coverage_t =
238+ newCov (c1.forward + c2.forward, c1.reverse + c2.reverse)
239+
240+ proc `/` (c: coverage_t, by: float ): tuple [forward: float , reverse: float ] =
241+ (float (c.forward)/ by, float (c.reverse)/ by)
242+ proc `*` (c: coverage_t, by: int ): coverage_t =
243+ newCov (c.forward* by, c.reverse* by)
244+
245+
231246proc topStop (q: HeapQueue ): int64 =
232247 if not q[0 ].isNil:
233248 return q[0 ].stop
234249 return - 1
235250
236-
237251proc topReverse (q: HeapQueue ): bool =
238252 if not q[0 ].isNil:
239253 return q[0 ].reverse
@@ -391,6 +405,24 @@ type
391405 chrom2str: TableRef [chrom_t, string ]
392406 chrom2len: TableRef [chrom_t, pos_t]
393407
408+ proc output_wig_span (span: genomic_interval_t[coverage_t], opts: output_option_t) =
409+ let span_length = opts.span_length # FIXME the actual span can be less than span_length!
410+ let value_str =
411+ if opts.strand:
412+ case opts.span_func:
413+ of sf_max, sf_min: $ span.label.forward & " \t " & $ span.label.reverse
414+ of sf_mean:
415+ let mean = span.label/ float (span_length)
416+ $ mean.forward & " \t " & $ mean.reverse
417+ else :
418+ let tot = span.label.forward + span.label.reverse
419+ case opts.span_func:
420+ of sf_max, sf_min: $ tot
421+ of sf_mean: $ (float (tot)/ float (span_length))
422+ echo $ span.start & " \t " & value_str
423+
424+
425+
394426proc write_output (o: var output_t, i: genomic_interval_t[coverage_t]) =
395427 if o.current_span.chrom != i.chrom or i.start < i.stop: # skip empty intervals
396428 case o.opts.output_format:
@@ -412,16 +444,13 @@ proc write_output(o: var output_t, i: genomic_interval_t[coverage_t]) =
412444 if len (o.quantization_index2label) > 0 :
413445 stderr.writeLine (" wig output does not support quantized coverage" )
414446 raise
415- if o.opts.strand:
416- stderr.writeLine (" wig output does not support stranded coverage" )
417- raise
447+ # if o.opts.strand:
448+ # stderr.writeLine("wig output does not support stranded coverage")
449+ # raise
418450 let span_length = o.opts.span_length
419451 if o.current_span.chrom != i.chrom: # start new contig
420452 if o.current_span.chrom != - 1 and o.current_span.start < o.chrom2len[o.current_span.chrom]: # output last possibly incomplete span from previous chrom
421- let span_value = case o.opts.span_func:
422- of sf_max, sf_min: $ o.current_span.label.forward
423- of sf_mean: $ (float (o.current_span.label.forward)/ float (span_length)) # FIXME the actual span is less than span_length!
424- echo $ o.current_span.start & " \t " & span_value
453+ output_wig_span (o.current_span, o.opts)
425454 if i.chrom == - 1 :
426455 return
427456
@@ -434,22 +463,18 @@ proc write_output(o: var output_t, i: genomic_interval_t[coverage_t]) =
434463 while o.current_span.start <= i.stop:
435464 let inter = intersection_first (o.current_span, i)
436465 if not is_empty (inter): # update the current span value
437- o.current_span.label.forward = case o.opts.span_func:
438- of sf_max: max (o.current_span.label.forward , i.label.forward )
439- of sf_min: min (o.current_span.label.forward , i.label.forward )
440- of sf_mean: o.current_span.label.forward + i.label.forward * int (len (inter))
466+ o.current_span.label = case o.opts.span_func:
467+ of sf_max: max (o.current_span.label, i.label)
468+ of sf_min: min (o.current_span.label, i.label)
469+ of sf_mean: o.current_span.label + i.label* int (len (inter))
441470 if inter.stop == o.current_span.stop: # span is concluded
442- # output span
443- let span_value = case o.opts.span_func:
444- of sf_max, sf_min: $ o.current_span.label.forward
445- of sf_mean: $ (float (o.current_span.label.forward)/ float (span_length))
446- echo $ o.current_span.start & " \t " & span_value
471+ output_wig_span (o.current_span, o.opts)
447472 # next span
448473 o.current_span.start += span_length
449474 o.current_span.stop = o.current_span.start + span_length
450- o.current_span.label.forward = case o.opts.span_func
451- of sf_max, sf_mean: 0
452- of sf_min: high (int )
475+ o.current_span.label = case o.opts.span_func
476+ of sf_max, sf_mean: newCov ( 0 , 0 )
477+ of sf_min: newCov ( high (int ), high ( int ) )
453478 else : # span extends beyond the interval, we are done
454479 break
455480
0 commit comments