1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
open Core
module Xls = struct
type entry = {
seqid : string ;
pos_start : int ;
pos_end : int ;
length : int ;
summit : int ;
tags : int ;
pvalue : float ;
fold : float ;
fdr : float option ;
}
type item = [
| `Comment of string
| `Record of entry
| `Header
]
let =
"chr\tstart\tend\tlength\tsummit\ttags\t-10*log10(pvalue)\tfold_enrichment"
let parse line =
let fail () =
failwithf "Macs.Xls.parse failed: %s" (line : Line.t :> string) ()
in
match (line : Line.t :> string) with
| "" -> `Comment ""
| line when String.is_prefix line ~prefix:header_prefix ->
`Header
| line ->
if Char.equal line.[0] '#' then `Comment (String.slice line 1 0)
else (
match String.split ~on:'\t' line with
| seqid :: pos_start :: pos_end :: length ::
summit :: tags :: pvalue :: fold :: maybe_fdr ->
let fdr = match maybe_fdr with
| [] -> None
| [ fdr ] -> Some (Float.of_string fdr)
| _ -> fail ()
in
`Record {
seqid ;
pos_start = Int.of_string pos_start ;
pos_end = Int.of_string pos_end ;
length = Int.of_string length ;
summit = Int.of_string summit ;
tags = Int.of_string tags ;
pvalue = Float.of_string pvalue ;
fold = Float.of_string fold ;
fdr
}
| _ -> fail ()
)
let unparse = function
| `Comment "" -> ""
| `Comment c -> sprintf "#%s\n" c
| `Header -> header_prefix ^ "\n"
| `Record r ->
sprintf "%s\n" (
String.concat ~sep:"\t" (
r.seqid :: sprintf "%d" r.pos_start :: sprintf "%d" r.pos_end ::
sprintf "%d" r.length :: sprintf "%d" r.summit ::
sprintf "%d" r.tags :: sprintf "%g" r.pvalue ::
sprintf "%g" r.fold ::
Option.value_map r.fdr ~default:[] ~f:(fun x -> [ sprintf "%g" x ])
)
)
| _ -> assert false
end