qmcchem/ocaml/Block.ml

294 lines
7.0 KiB
OCaml
Raw Permalink Normal View History

2017-10-10 09:39:58 +02:00
open Qptypes
2015-12-19 02:35:13 +01:00
2022-01-06 17:43:31 +01:00
type t =
2015-12-19 02:35:13 +01:00
{ property : Property.t ;
value : Sample.t ;
weight : Weight.t ;
compute_node : Compute_node.t ;
2019-07-14 18:50:44 +02:00
pid : int ;
2015-12-19 02:35:13 +01:00
block_id : Block_id.t ;
}
let re =
Str.regexp "[ |#|\n]+"
2022-01-06 17:43:31 +01:00
let of_string s =
2015-12-19 02:35:13 +01:00
try
let lst =
Str.split re s
|> List.rev
in
match lst with
| b :: pid :: c:: p :: w :: v :: [] -> Some
{ property = Property.of_string p ;
2019-07-14 18:50:44 +02:00
value = Sample.of_float (float_of_string v) ;
2022-01-06 17:43:31 +01:00
weight = Weight.of_float (float_of_string w) ;
2015-12-19 02:35:13 +01:00
compute_node = Compute_node.of_string c;
2019-07-14 18:50:44 +02:00
pid = int_of_string pid;
block_id = Block_id.of_int (int_of_string b) ;
2015-12-19 02:35:13 +01:00
}
2022-01-06 17:43:31 +01:00
| b :: pid :: c:: p :: w :: v ->
let v =
2015-12-19 02:35:13 +01:00
List.rev v
2022-01-06 17:43:31 +01:00
|> Array.of_list
2019-07-14 18:50:44 +02:00
|> Array.map float_of_string
2015-12-19 02:35:13 +01:00
in
2022-01-06 17:43:31 +01:00
let dim =
2015-12-19 02:35:13 +01:00
Array.length v
in
Some
{ property = Property.of_string p ;
value = Sample.of_float_array ~dim v ;
2022-01-06 17:43:31 +01:00
weight = Weight.of_float (float_of_string w) ;
2015-12-19 02:35:13 +01:00
compute_node = Compute_node.of_string c;
2019-07-14 18:50:44 +02:00
pid = int_of_string pid;
block_id = Block_id.of_int (int_of_string b) ;
2015-12-19 02:35:13 +01:00
}
| _ -> None
with
| _ -> None
2022-01-06 17:43:31 +01:00
2022-01-11 22:12:02 +01:00
let to_short_string b =
Printf.sprintf "%s # %s %d %d"
(Property.to_string b.property)
(Compute_node.to_string b.compute_node)
b.pid
(Block_id.to_int b.block_id)
let to_string b =
Printf.sprintf "%s %s # %s %s %s %d"
(Sample.to_string b.value )
(Weight.to_float b.weight |> string_of_float)
(Property.to_string b.property)
(Compute_node.to_string b.compute_node)
(string_of_int b.pid)
(Block_id.to_int b.block_id)
2022-01-06 17:43:31 +01:00
let zero =
bytes_of_int 0
let to_bytes b =
(* [ Length of b
[ Length of value ;
2022-01-11 13:41:13 +01:00
Value ;
2022-01-06 17:43:31 +01:00
Length of weight ;
Weight ;
... ] ] *)
let l =
2022-01-11 13:41:13 +01:00
[ Property.to_bytes b.property ;
Sample.to_bytes b.value ;
Weight.to_bytes b.weight ;
bytes_of_int b.pid ;
Block_id.to_bytes b.block_id ;
Compute_node.to_bytes b.compute_node ]
2022-01-06 17:43:31 +01:00
|> List.map (fun x -> [ bytes_of_int (Bytes.length x) ; x ] )
|> List.concat
in
let result =
Bytes.concat Bytes.empty (zero :: l)
in
2022-01-12 12:48:08 +01:00
Bytes.set_int64_ne result 0 (Int64.of_int ((Bytes.length result) - 8));
2022-01-11 13:41:13 +01:00
result
2022-01-12 12:48:08 +01:00
let read_bytes b idx =
2022-01-11 13:41:13 +01:00
(* Reads m, the first 8 bytes as an int64 containing the number of bytes to read.
Then, read the next m bytes and return a tuple containing the decoded data and the rest.
*)
2022-01-12 12:48:08 +01:00
let l = (Bytes.length b) - idx in
2022-01-11 22:12:02 +01:00
if l < 8 then
2022-01-12 12:48:08 +01:00
None
2022-01-11 13:41:13 +01:00
else
2022-01-11 22:12:02 +01:00
let m =
2022-01-12 12:48:08 +01:00
Bytes.get_int64_ne b idx
2022-01-11 22:12:02 +01:00
|> Int64.to_int
in
2022-01-12 14:43:29 +01:00
try
Some (Bytes.sub b (idx+8) m, idx+8+m)
with Invalid_argument _ -> None
2022-01-11 13:41:13 +01:00
2022-01-12 19:05:15 +01:00
let of_bytes ?(idx=0) b =
2022-01-12 12:48:08 +01:00
let get_x s idx =
match read_bytes s idx with
| Some ( data, i1) -> data, i1
| _ -> raise Exit
in
let result =
try
let property, idx = get_x b idx in
let value , idx = get_x b idx in
let weight , idx = get_x b idx in
let pid , idx = get_x b idx in
let block_id, idx = get_x b idx in
let compute_node, i5 = get_x b idx in
Some
{ property = Property.of_bytes property;
value = Sample.of_bytes value;
weight = Weight.of_bytes weight;
pid = int_of_bytes pid;
block_id = Block_id.of_bytes block_id;
compute_node = Compute_node.of_bytes compute_node;
}
with Exit -> None
in
2022-01-06 17:43:31 +01:00
result
2022-01-11 22:12:02 +01:00
let of_string_or_bytes s =
2022-01-11 14:47:04 +01:00
if Qmcchem_config.binary_io then
2022-01-11 22:12:02 +01:00
Bytes.of_string s
|> of_bytes
2022-01-11 14:47:04 +01:00
else
2022-01-11 22:12:02 +01:00
of_string s
2015-12-19 02:35:13 +01:00
let dir_name = lazy(
2022-01-06 17:43:31 +01:00
let ezfio_filename =
2015-12-19 02:35:13 +01:00
Lazy.force Qputils.ezfio_filename
in
let md5 =
2018-03-14 17:02:52 +01:00
QmcMd5.hash ()
2015-12-19 02:35:13 +01:00
in
2019-07-31 15:07:04 +02:00
let d = Filename.concat ezfio_filename "blocks" in
if not ( Sys.file_exists d ) then
Unix.mkdir d 0o755;
2022-01-06 17:43:31 +01:00
List.fold_right Filename.concat
[ ezfio_filename ; "blocks" ; md5 ; Filename.dir_sep ] ""
2015-12-19 02:35:13 +01:00
)
(* Fetch raw data from the EZFIO file *)
let _raw_data =
ref None
let update_raw_data ?(locked=true) () =
(* Create array of files to read *)
2022-01-06 17:43:31 +01:00
let dir_name =
2015-12-19 02:35:13 +01:00
Lazy.force dir_name
in
2022-01-06 17:43:31 +01:00
let files =
let result =
2019-07-23 17:27:02 +02:00
if Sys.file_exists dir_name && Sys.is_directory dir_name then
2015-12-19 02:35:13 +01:00
begin
Sys.readdir dir_name
2019-07-14 18:50:44 +02:00
|> Array.map (fun x -> dir_name^x)
2015-12-19 02:35:13 +01:00
|> Array.to_list
end
2019-07-14 18:50:44 +02:00
else []
2015-12-19 02:35:13 +01:00
in
if locked then
result
else
2019-07-14 18:50:44 +02:00
List.filter (fun x ->
try
2022-01-06 17:43:31 +01:00
let _ =
2019-07-14 18:50:44 +02:00
Str.search_backward (Str.regexp "locked") x ((String.length x) - 1)
in false
with
| Not_found -> true
) result
2015-12-19 02:35:13 +01:00
in
2022-01-11 22:12:02 +01:00
if Qmcchem_config.binary_io then
begin
let result =
2022-01-12 12:48:08 +01:00
let rec aux buf idx accu =
2022-01-11 22:12:02 +01:00
(* Read one block *)
2022-01-12 12:48:08 +01:00
match read_bytes buf idx with
| None -> List.rev accu
| Some (item, new_idx) ->
match of_bytes item with
| None -> List.rev accu
| Some item -> (aux [@tailcall]) buf new_idx (item::accu)
2022-01-11 22:12:02 +01:00
in
List.concat_map (fun filename ->
let ic = open_in filename in
let length = in_channel_length ic in
let result =
2022-01-12 12:48:08 +01:00
if length > 0 then
2022-01-11 22:12:02 +01:00
let buf = Bytes.create length in
really_input ic buf 0 length;
2022-01-12 12:48:08 +01:00
aux buf 0 []
2022-01-11 22:12:02 +01:00
else []
in
close_in ic;
result ) files
2020-04-16 00:42:51 +02:00
in
2022-01-11 22:12:02 +01:00
result
end
else
begin
2022-01-12 12:48:08 +01:00
let rec transform new_list = function
| [] -> new_list
| head :: tail ->
let head = String.trim head in
let item = of_string head in
match item with
| None -> transform new_list tail
| Some x -> transform (x::new_list) tail
in
2022-01-11 22:12:02 +01:00
let result =
let rec aux ic accu =
let l =
try
Some (input_line ic)
with
| End_of_file -> None
in
match l with
| None -> List.rev accu
| Some l -> (aux [@tailcall]) ic (l::accu)
in
List.concat_map (fun filename ->
let ic = open_in filename in
let result = aux ic [] in
close_in ic;
result ) files
|> transform []
in
result
end
let to_string_or_bytes b =
if Qmcchem_config.binary_io then
to_bytes b
|> Bytes.to_string
else
to_string b
2015-12-19 02:35:13 +01:00
2022-01-06 17:43:31 +01:00
let raw_data ?(locked=true) () =
2015-12-19 02:35:13 +01:00
match !_raw_data with
| Some x -> x
| None ->
2022-01-06 17:43:31 +01:00
let result =
2015-12-19 02:35:13 +01:00
update_raw_data ~locked ()
in
_raw_data := Some result;
result
let properties = lazy (
2019-07-19 11:46:29 +02:00
let h = Hashtbl.create 63 in
2022-01-06 17:43:31 +01:00
List.iter (fun x ->
2019-07-23 17:34:58 +02:00
Hashtbl.replace h (Property.to_string x.property) x.property)
2019-07-19 11:46:29 +02:00
(raw_data ());
Hashtbl.fold (fun k v a -> v :: a) h []
2015-12-19 02:35:13 +01:00
)