12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758(* keep only the top N scoring molecules in memory *)(* FBR: add .mli file *)(* WARNING: we will have several molecules with equal scores when working
on a huge database *)moduleFMap=BatMap.Make(BatFloat)typet={queue:stringlistFMap.t;(* molecule names sorted by
increasing scores; names for a given
score are in reverse order
of encounter (LIFO) until high_scores_first is called *)count:int;max:int}(* max nb. of molecules to keep *)letcreate_privqueuecountmax:t={queue;count;max}letcreate(n:int):t=create_privFMap.empty0nletinsert_priv(score:float)(name:string)(map:stringlistFMap.t):stringlistFMap.t=try(* score already seen *)letprevious=FMap.findscoremapinletcurrent=name::previousinFMap.addscorecurrentmapwithNot_found->(* new score *)FMap.addscore[name]mapletadd(name:string)(score:float)(acc:t):t=ifacc.count<acc.maxthen(* not enough molecules yet *)letnew_map=insert_privscorenameacc.queueincreate_privnew_map(acc.count+1)acc.maxelse(* enough molecules already *)let(min_score,min_names),rest=FMap.pop_min_bindingacc.queueinifscore>min_scorethenmatchmin_nameswith|[]->assert(false)(* not supposed to happen *)|[_one]->(* forget it and add new *)letnew_map=insert_privscorenamerestincreate_privnew_mapacc.countacc.max|_one::others->(* forget one and add new *)letnew_map=FMap.addmin_scoreothersrestinletnew_map=insert_privscorenamenew_mapincreate_privnew_mapacc.countacc.maxelseacclethigh_scores_first(acc:t):(float*string)list=(* put back scores in decreasing order *)FMap.fold(funscorenamesacc1->(* put back names in encounter order *)List.fold_left(funacc2name->(score,name)::acc2)acc1names)acc.queue[]