1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192openCFStreamtypecount_matrix=intarrayarraytypebackground=floatarraytypet=floatarrayarrayletint_of_char=function|'a'|'A'->0|'c'|'C'->1|'g'|'G'->2|'t'|'T'->3|_->4letflat_background()=Caml.Array.make40.25letbackground_of_sequenceseqpc=letcounts=Caml.Array.make40andn=ref0infori=0toString.lengthseq-1doletk=int_of_charseq.[i]inifk<4then(counts.(k)<-counts.(k)+1;incrn)done;Array.map~f:(func->(floatc+.pc)/.(float!n+.4.*.pc))countsletreverse_complementa=letopenArrayinletn=lengthaininitn~f:(funi->letr=copya.(n-1-i)inswapr03;swapr12;r)letmakematbg=letopenArrayinmapmat~f:(funp->letn=fold~f:(+)~init:0pinletr=mapip~f:(funix->log((floatx+.bg.(i))/.floatn/.bg.(i)))inletn_case=Stream.Infix.(0--^(Array.lengthp))|>Stream.fold~f:(funaccui->accu+.bg.(i)*.r.(i))~init:0.inappendr[|n_case|])lettandem?(orientation=`direct)~spacermat1mat2bg=Array.concat[(ifPoly.(orientation=`everted)thenreverse_complementelseident)(makemat1bg);Array.initspacer~f:(fun_->Caml.Array.make50.);(ifPoly.(orientation=`inverted)thenreverse_complementelseident)(makemat2bg)]letgen_scanfinitmatseqtol=letr=refinitandn=String.lengthseqandm=Array.lengthmatinletseq=Array.initn~f:(funi->int_of_charseq.[i])infori=n-mdownto0doletscore=ref0.inforj=0tom-1doscore:=!score+.Array.(unsafe_get(unsafe_getmatj)(unsafe_getseq(i+j)))done;ifFloat.(!score>tol)thenr:=fi!score!rdone;!rletscan=gen_scan(funposscorel->(pos,score)::l)[]letbest_hitmatseq=let(pos,_)asr=gen_scan(funp1s1((_,s2)asr2)->ifFloat.(s1>s2)then(p1,s1)elser2)(-1,Float.neg_infinity)matseqFloat.neg_infinityinifpos<0thenraise(Invalid_argument"Pwm.best_hit: sequence shorter than the matrix")elserexternalstub_fast_scan:t->intarray->float->(int*float)list="biocaml_pwm_scan"letfast_scanmatseqtol=letn=String.lengthseqinletseq=Array.initn~f:(funi->int_of_charseq.[i])instub_fast_scanmatseqtol