123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226openCoreletgcs=letc=ref0andn=ref0inletcount=function'c'|'g'|'C'|'G'->incrc|'n'|'N'->incrn|_->()inString.iter~f:counts;float!c/.float(String.lengths-!n)letincrdeltagcnw=w:=!w+delta;function'c'|'C'|'g'|'G'->gc:=!gc+delta|'n'|'N'->n:=!n+delta|_->()letlocal_gcks=letn=String.lengthsinifk>nthenraise(Invalid_argument"Dna_sequence.local_gc");letgc=ref0andunk=ref0andw=ref0andi=ref0infori=0tok/2doincr1gcunkws.[i]done;letrecstream()=if!i>=nthenSeq.Nilelseletw=(Stdlib.min(n-1)(!i+k/2))-(Stdlib.max0(!i-k/2))+1inletr=ifw=!unkthen0.5else(float!gc)/.(float(w-!unk))inif!i+k/2+1<nthenincr1gcunk(ref0)s.[!i+k/2+1];if!i-k/2>=0thenincr(-1)gcunk(ref0)s.[!i-k/2];Stdlib.incri;Seq.Cons(r,stream)instreammoduletypeParser=sigtypettypescore(** filter arguments:
- position
- GC content around this position
- optimal score of a match finishing at this position
- start position of the optimal match finishing at this position *)type'amatch_filter=int->float->int->int->'aoptiontypestatistics={nb_gc_levels:int;values:scorearrayarray;(* gc levels -> sorted score values *)}(** [statistics nbl parser] computes statistics for [nbl] number of GC levels *)valstatistics:generator:(int->float->string)->int->t->statisticsvalcdf_of_statistics:statistics->float->float->floatvalaverage_cdf_of_statistics:statistics->float->floatvalbound_of_fpr:statistics->float->floatvalbound_for_gc_and_fpr:statistics->gc:float->fpr:float->float(** returns (start, end), raw score, gc content, normalized score *)(* val fpr_filter : statistics -> float -> ((int * int) * int * float * float) match_filter *)(** returns location, raw score, gc content, normalized score *)(* val loc_fpr_filter : statistics -> float -> GLoc.t -> (GLoc.t * int * float * float) match_filter *)(*
val normalize : statistics -> string -> int array -> float array
val fdr_scan : fdr:float -> t -> statistics -> string -> (int * int * float) list
val use_location : Location.t -> (int * int * float) list -> (Location.t * float) list *)endmoduleParser_of_char(P:Wfa.Profilewithtypesymbol=Wfa.Nucleotide.tandtypescore=float)=structmoduleM=Wfa.Make(Float)(Wfa.Nucleotide)(P)typet=M.automatontype'amatch_filter=int->float->int->int->'aoption(* let int_of_char = function
* | 'a' | 'A' -> 0
* | 'c' | 'C' -> 1
* | 'g' | 'G' -> 2
* | 't' | 'T' -> 3
* | 'n' | 'N' -> 4
* | _ -> raise (Invalid_argument "Dnaseq.int_of_char") *)letchar=letopenWfa.Nucleotideinfunction|'a'|'A'->Somea|'c'|'C'->Somec|'g'|'G'->Someg|'t'|'T'->Somet|'n'|'N'->None|_->raise(Invalid_argument"Dnaseq.char")typestatistics={nb_gc_levels:int;values:floatarrayarray;(* gc levels -> score values *)}(* let gc_round n f =
* let n = float n in
* Float.(iround_exn ~dir:`Down ((f * n + 0.5) / n)) *)letgc_levelsn=Array.init(n+1)~f:(funi->floati/.(floatn))letgc_levelnf=letn=floatninFloat.(iround_exn~dir:`Down(f*n+.0.5))(* FIXME: this keeps the neg_inf scores in the beginning,
the first values with position = -1 should be removed *)letarrange_score_valuesscores=Array.sort~compare:Poly.comparescores;scoresletseq_size=1000000letstatistics~generatornb_levelsaut=letseqz=Array.map~f:(generatorseq_size)(gc_levelsnb_levels)in{nb_gc_levels=nb_levels;values=Array.mapseqz~f:(funs->M.scancharauts|>Seq.map(fun(_,s,_)->s)|>Stdlib.Array.of_seq|>arrange_score_values);}letrecrank_auxtxab=ifa>bthenraiseStdlib.Not_foundelseifa=bthenaelse(leti=(a+b)/2+1inifFloat.(t.(i)<=x)thenrank_auxtxibelserank_auxtxa(i-1))letranktx=rank_auxtx0(Array.lengtht-1)letcdfax=float(rankax+1)/.(float(Array.lengtha))letcdf_of_statisticsstatsgcscore=cdfstats.values.(gc_levelstats.nb_gc_levelsgc)scoreletaverage_cdf_of_statisticsstats=letcdfz=Array.initstats.nb_gc_levels~f:(funi->cdfstats.values.(i))inletn=floatstats.nb_gc_levelsinfunscore->(Array.fold~f:(funaccuf->accu+.fscore)~init:0.cdfz)/.nletbound_of_fprstatsfpr=letk=int_of_float(floatseq_size*.(1.-.fpr))inArray.fold~f:(funaccuvalues->Float.minaccuvalues.(k))~init:Float.max_valuestats.valuesletbound_for_gc_and_fprstats~gc~fpr=letk=int_of_float(floatseq_size*.(1.-.fpr))instats.values.(gc_levelstats.nb_gc_levelsgc).(k)(* let gen_fpr_filter localize stats fpr =
* let bound = bound_of_fpr stats fpr
* and cdf = cdf_of_statistics stats
* and tpr_bound = 1. -. fpr in
* fun ed gc score st ->
* if score < bound then None
* else (
* let nscore = cdf gc score in
* if nscore < tpr_bound then None
* else Some (
* localize st ed,
* score, gc, nscore
* )
* ) *)(* let loc_fpr_filter stats fpr loc =
* gen_fpr_filter
* (fun st ed -> GLoc.{ chr = loc.chr ; lo = loc.lo + st ; hi = loc.hi + ed })
* stats fpr
*
* let fpr_filter = gen_fpr_filter (fun i j -> i,j) *)(*
let normalize stats dna score =
let cdf = cdf_of_statistics stats in
let gc = local_gc (min 30 (String.length dna)) dna in
Array.mapi (fun i x -> cdf gc.(i) x) score
let ( += ) l e = l := e :: !l
let fdr_scan ~fdr aut stats dna =
let score, position = scan aut dna in
let score = normalize stats dna score
and r = ref [] in
for i = Array.length score - 1 downto 0 do
if score.(i) >= fdr
then r += (position.(i), i - position.(i) + 1, score.(i))
done ;
List.sort ~cmp:compare !r
open Location
let use_location loc hits =
List.map (fun (s,l,f) -> move loc (loc.st + s) (loc.st + s + l - 1), f) hits
*)end(* module Test = struct
* let balmer_hexamer = `sequence [
* `base (1.04, -1.8,-0.01,-1.78) ;
* `base (-2.47,-3.34,1.27,-1.87) ;
* `base (-1.7,-3.05,0.94,0.16) ;
* `base (-2.88,-1.3,-0.69,1.22) ;
* `base (-3.17,1.09,-0.85,-1.38) ;
* `base (1.35,-3.34,-1.36,-2.07) ;
* ]
*
* let balmer_dr125 = `sequence [
* balmer_hexamer ;
* `disjunction [ `gap (5,5) ; `gap (2,2) ; `gap (1,1) ] ;
* balmer_hexamer
* ]
* module Parser = Parser_of_char(Motif.Profile)
* let aut = Motif.PSSM.automaton balmer_dr125
* end *)