package biocaml
The OCaml Bioinformatics Library
Install
Dune Dependency
Authors
Maintainers
Sources
biocaml-0.11.2.tbz
sha256=fae219e66db06f81f3fd7d9e44717ccf2d6d85701adb12004ab4ae6d3359dd2d
sha512=f6abd60dac2e02777be81ce3b5acdc0db23b3fa06731f5b2d0b32e6ecc9305fe64f407bbd95a3a9488b14d0a7ac7c41c73a7e18c329a8f18febfc8fd50eccbc6
doc/src/biocaml.unix/range.ml.html
Source file range.ml
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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
type t = {lo:int; hi:int} [@@deriving compare, sexp] let make lo hi = if lo <= hi then Ok {lo; hi} else ( error "lower bound larger than upper bound" (lo, hi) [%sexp_of: int * int ] ) let make_unsafe lo hi = {lo; hi} let size v = v.hi - v.lo + 1 let equal u v = compare u v = 0 let member t k = t.lo <= k && k <= t.hi let to_string t = String.concat [ "["; string_of_int t.lo; ", "; string_of_int t.hi; "]" ] let to_list v = List.init (size v) ~f:((+) v.lo) let overlap u v = (min u.hi v.hi) - (max u.lo v.lo) + 1 let gap u v = -(overlap u v) let union u v = if overlap u v < 0 then `Disjoint (u, v) else `Joint {lo = min u.lo v.lo; hi = max u.hi v.hi} let intersect u v = let l = max u.lo v.lo in let h = min u.hi v.hi in if l <= h then Some {lo=l; hi=h} else None let strict_before u v = u.lo < v.lo && u.hi < v.hi let strict_after u v = strict_before v u let before u v = strict_before u v || equal u v let after u v = before v u let compare_positional u v = if equal u v then Some 0 else if strict_before u v then Some (-1) else if strict_after u v then Some 1 else None let subset u v = u.lo >= v.lo && u.hi <= v.hi let superset u v = subset v u let strict_subset u v = subset u v && not (equal u v) let strict_superset u v = strict_subset v u let compare_containment u v = if equal u v then Some 0 else if strict_subset u v then Some (-1) else if strict_superset u v then Some 1 else None let any_overlap tl = let tl = List.sort tl ~compare:(fun u v -> Int.compare u.lo v.lo) in let rec loop tl = match tl with | [] | _::[] -> false | u::v::tl -> v.lo <= u.hi || loop (v::tl) in loop tl let all_positional vl = let compare u v = match compare_containment u v with | Some x -> x | None -> match compare_positional u v with | Some x -> x | None -> assert false in let vl = List.sort ~compare vl in let rec loop vl = match vl with | [] | _::[] -> true | u::v::vl -> (before u v) && loop (v::vl) in loop vl let max_gap_of_positional vl = let compare u v = match compare_containment u v with | Some x -> x | None -> match compare_positional u v with | Some x -> x | None -> assert false in let vl = List.sort ~compare vl in let rec loop ans vl = match vl with | [] | _::[] -> ans | u::v::vl -> if before u v then loop (max ans (gap u v)) (v::vl) else failwith ( sprintf "ranges %s and %s not positionally comparable" (to_string u) (to_string v) ) in match vl with | [] | _::[] -> failwith "given fewer than two ranges" | u::v::vl -> loop (gap u v) (v::vl) let find_min_range ?(init_direction="fwd") v pred i = if i < v.lo || i > v.hi then invalid_arg (sprintf "%d not in range %s" i (to_string v)) ; let rec loop (dir:string) ans = if pred ans then Some ans else if equal ans v then None else match dir with | "fwd" -> let hi' = if ans.hi = v.hi then ans.hi else ans.hi+1 in loop "rev" {ans with hi = hi'} | "rev" -> let lo' = if ans.lo = v.lo then ans.lo else ans.lo-1 in loop "fwd" {ans with lo = lo'} | _ -> invalid_arg ( sprintf "valid directions are \"fwd\" or \"rev\" but given \"%s\"" dir ) in loop init_direction {lo=i; hi=i} let expand_assoc_list tal = let ans = Caml.Hashtbl.create 100 in let insert (t,a) = for i = t.lo to t.hi do let prev = try Caml.Hashtbl.find ans i with Caml.Not_found -> [] in Caml.Hashtbl.replace ans i (a::prev) done in let () = List.iter ~f:insert tal in let ans = Caml.Hashtbl.fold (fun key value ans -> (key,value)::ans) ans [] in List.rev (List.map ~f:(fun (i,al) -> i, List.rev al) ans) let find_regions ?(max_gap=0) pred tal = if any_overlap (List.map ~f:fst tal) then failwith "overlapping ranges not allowed" ; let tal = List.sort tal ~compare:(fun (u,_) (v,_) -> match compare_positional u v with | Some x -> x | None -> assert false ) in (* see below for meaning of [curr] *) let insert (curr : (t * int) option) ans = match curr with | None -> ans | Some (v,gap) -> let x = v.lo in let y = v.hi - gap in if x <= y then {lo=x; hi=y}::ans else failwithf "gap = %d, range = %s" gap (to_string v) () in (* curr = Some (v,gap) means [v] is region built up thus far, * with last [gap] elements failing pred, [0 <= gap <= max_gap]. * curr = None means no region currently being built *) let rec loop (curr : (t * int) option) ans tal = match tal with | [] -> insert curr ans | (t,a)::tal -> match curr with | None -> let curr = if pred a then Some(t,0) else None in loop curr ans tal | Some (curr_v, curr_gap) -> let extra_gap = t.lo - curr_v.hi - 1 in let t,pred,tal = if extra_gap > 0 then {lo=(curr_v.hi + 1); hi=(t.lo - 1)}, false, ((t,a)::tal) else t, pred a, tal in let curr_v = {lo=curr_v.lo; hi=t.hi} in let curr_gap = if pred then 0 else size t + curr_gap in let curr = Some (curr_v, curr_gap) in if curr_gap > max_gap then loop None (insert curr ans) tal else loop curr ans tal in List.rev (loop None [] tal) let rec make_random t = let max = t.hi - t.lo + 1 in let lo = t.lo + Random.int max in let hi = t.lo + Random.int max in if lo <= hi then {lo; hi} else make_random t
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>