123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154(* TODO: get bins number 37450 to read metadata *)openBaseopenStdiotypechunk={chunk_beg:Int64.t;chunk_end:Int64.t;}typebin={bin:int;n_chunk:int;chunks:chunkarray;}typeinterval=IoffsetofInt64.t[@@unboxed]typereference_sequence={n_bin:int;bins:binarray;n_intv:int;intervals:intervalarray;}typet={n_ref:int;reference_sequences:reference_sequencearray;n_no_coor:Int64.toption;}exceptionParser_errorofstringletfailmsg=raise(Parser_errormsg)letfailffmt=Printf.ksprintffailfmtletinput_bytet=Option.value_exn(In_channel.input_bytet)letinput_s32ic=letb1=input_byteicinletb2=input_byteicinletb3=input_byteicinletb4=input_byteicinletopenInt32inshift_left(of_int_exnb4)24|>bit_or(shift_left(of_int_exnb3)16)|>bit_or(shift_left(of_int_exnb2)8)|>bit_or(of_int_exnb1)letinput_u64ic=letb1=input_byteicinletb2=input_byteicinletb3=input_byteicinletb4=input_byteicinletb5=input_byteicinletb6=input_byteicinletb7=input_byteicinletb8=input_byteicinletopenInt64in(shift_left(of_int_exnb8)56)|>bit_or(shift_left(of_int_exnb7)48)|>bit_or(shift_left(of_int_exnb6)40)|>bit_or(shift_left(of_int_exnb5)32)|>bit_or(shift_left(of_int_exnb4)24)|>bit_or(shift_left(of_int_exnb3)16)|>bit_or(shift_left(of_int_exnb2)8)|>bit_or(of_int_exnb1)letinput_s32_as_intcontextic=matchBase.Int32.to_int(input_s32ic)with|Somei->i|None->failf"Met too big an integer while parsing a %s"contextletread_magic_stringic=letbuf=Bytes.create4inIn_channel.really_input_exnic~buf~pos:0~len:4;ifBytes.(buf<>of_string"BAI\001")thenfail"Incorrect magic string"letread_chunkic=letchunk_beg=input_u64icinletchunk_end=input_u64icin{chunk_beg;chunk_end}letread_binic=letbin=input_s32_as_int"bin"icinletn_chunk=input_s32_as_int"n_chunk"icinletchunks=Array.initn_chunk~f:(fun_->read_chunkic)in{bin;n_chunk;chunks}letread_intervalic=Ioffset(input_u64ic)letread_reference_sequenceic=letn_bin=input_s32_as_int"n_bin"icinletbins=Array.initn_bin~f:(fun_->read_binic)inletn_intv=input_s32_as_int"n_intv"icinletintervals=Array.initn_intv~f:(fun_->read_intervalic)in{n_bin;bins;n_intv;intervals}letread_reference_sequencesicn=Array.initn~f:(fun_->read_reference_sequenceic)letreadic=tryread_magic_stringic;letn_ref=input_s32_as_int"n_ref"icinletreference_sequences=read_reference_sequencesicn_refinletn_no_coor=trySome(input_u64ic)withEnd_of_file->NoneinOk{n_ref;reference_sequences;n_no_coor}withParser_errormsg->Error(`Msgmsg)let%test"read"=matchIn_channel.with_file"../data/ex1.bam.bai"~f:readwith|Okr->r.n_ref=2|Error_->falseletreg2binlohi=lethi=hi-1inlettesti=lolsri=hilsriinletcalci=((1lsl(29-i))-1)/7+(lolsri)iniftest14thencalc14elseiftest17thencalc17elseiftest20thencalc20elseiftest23thencalc23elseiftest26thencalc26elsezerolet%test_=reg2bin40007800=4681let%test_=reg2bin14000001420000=595letrecint_foldlohi~init~f=iflo>hitheninitelseint_fold(lo+1)hi~init:(finitlo)~fletreg2binslohi~init~f=lethi=hi-1inletinit=finit0inletfabacc=int_fold(a+lolsrb)(a+hilsrb)~init:acc~fininit|>f126|>f923|>f7320|>f58517|>f468114letreg2binlistlohi=reg2binslohi~init:[]~f:(funacci->i::acc)|>List.revlet%test_=Poly.(reg2binlist14000001420000=[0;1;9;74;595;4766;4767])let%test_=Poly.(reg2binlist9400000094010000=[0;2;20;162;1302;10418])