Skip to content

Commit 9fea409

Browse files
Pass Automated Testing Suitezoj613
Pass Automated Testing Suite
authored andcommitted
Implement basic functionality.
This commit implements basic functionality. - Supported codecs include Sharding Indexed, Gzip, Crc32c, Transpose and Bytes. - Supported stores include MemoryStore and FilesystemStore. - Supported data types include Float32, Float64, Complex32 and Complex64. This limitation is simply a result of Owl limited array write functionality as reported here: owlbarn/owl#671 - All the core Zarr V3 specification details have been implemented.
1 parent 187d044 commit 9fea409

29 files changed

+2667
-2
lines changed

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
BSD 3-Clause License
22

3-
Copyright (c) 2024, zoj613
3+
Copyright (c) 2024, Zolisa Bleki
44

55
Redistribution and use in source and binary forms, with or without
66
modification, are permitted provided that the following conditions are met:

README.md

+111-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,112 @@
11
# zarr-ml
2-
An Ocaml implementation of the Zarr version 3 specification.
2+
An implementation of the Zarr version 3 specification.
3+
4+
5+
## Example
6+
```ocaml
7+
open Zarr
8+
open Zarr.Codecs
9+
open Zarr.Storage
10+
open Zarr.Metadata
11+
open Zarr.Extensions
12+
module Ndarray = Owl.Dense.Ndarray.Generic
13+
14+
let store =
15+
Result.get_ok @@
16+
FilesystemStore.open_or_create ~file_perm:0o777 "testdata.zarr";;
17+
18+
let group_node =
19+
Result.get_ok @@ Node.of_path "/some/group";;
20+
21+
FilesystemStore.create_group store group_node;;
22+
23+
let array_node =
24+
Result.get_ok @@ Node.(group_node / "name");;
25+
26+
let shard_config = {
27+
chunk_shape = [|5; 5; 10|];
28+
codecs = Chain.create [] (Bytes Little) [Gzip L5];
29+
index_codecs = Chain.create [] (Bytes Big) [Crc32c];
30+
index_location = Start
31+
};;
32+
let codec_chain =
33+
Chain.create [Transpose [|0; 1; 2|]] (ShardingIndexed shard_config) [];;
34+
35+
FilesystemStore.create_array
36+
~codecs:codec_chain
37+
~shape:[|100; 100; 50|]
38+
~chunks:[|15; 15; 20|]
39+
(FillValue.Float Float.neg_infinity)
40+
Datatype.Float32
41+
array_node
42+
store;;
43+
44+
FilesystemStore.find_all_nodes store |> List.map Node.to_path;;
45+
(* - : string list = ["/"; "/some"; "/some/group/name"; "/some/group"] *)
46+
47+
let slice = Owl_types.[|R [0; 20]; I 10; R []|];;
48+
let x =
49+
Result.get_ok @@
50+
FilesystemStore.get_array array_node slice Bigarray.Float32 store;;
51+
(*
52+
C0 C1 C2 C3 C4 C45 C46 C47 C48 C49
53+
R[0,0] -INF -INF -INF -INF -INF ... -INF -INF -INF -INF -INF
54+
R[1,0] -INF -INF -INF -INF -INF ... -INF -INF -INF -INF -INF
55+
R[2,0] -INF -INF -INF -INF -INF ... -INF -INF -INF -INF -INF
56+
R[3,0] -INF -INF -INF -INF -INF ... -INF -INF -INF -INF -INF
57+
R[4,0] -INF -INF -INF -INF -INF ... -INF -INF -INF -INF -INF
58+
... ... ... ... ... ... ... ... ... ... ...
59+
R[16,0] -INF -INF -INF -INF -INF ... -INF -INF -INF -INF -INF
60+
R[17,0] -INF -INF -INF -INF -INF ... -INF -INF -INF -INF -INF
61+
R[18,0] -INF -INF -INF -INF -INF ... -INF -INF -INF -INF -INF
62+
R[19,0] -INF -INF -INF -INF -INF ... -INF -INF -INF -INF -INF
63+
R[20,0] -INF -INF -INF -INF -INF ... -INF -INF -INF -INF -INF *)
64+
65+
(* Do some computation on the array slice *)
66+
let x' = Ndarray.map (fun _ -> Owl_stats_dist.uniform_rvs 0. 100.) x;;
67+
FilesystemStore.set_array array_node slice x' store;;
68+
69+
FilesystemStore.get_array
70+
array_node
71+
Owl_types.[|R [0; 73]; L [10; 16]; R[0; 5]|]
72+
Bigarray.Float32
73+
store;;
74+
(*
75+
C0 C1 C2 C3 C4 C5
76+
R[0,0] 68.0272 44.914 85.2431 39.0772 26.582 16.577
77+
R[0,1] -INF -INF -INF -INF -INF -INF
78+
R[1,0] 88.418 77.0368 43.4968 45.1263 8.95641 76.9155
79+
R[1,1] -INF -INF -INF -INF -INF -INF
80+
R[2,0] 98.4036 77.8744 67.6689 56.8803 37.0718 97.042
81+
... ... ... ... ... ...
82+
R[71,1] -INF -INF -INF -INF -INF -INF
83+
R[72,0] -INF -INF -INF -INF -INF -INF
84+
R[72,1] -INF -INF -INF -INF -INF -INF
85+
R[73,0] -INF -INF -INF -INF -INF -INF
86+
R[73,1] -INF -INF -INF -INF -INF -INF *)
87+
88+
FilesystemStore.reshape store array_node [|25; 32; 10|];;
89+
FilesystemStore.get_array
90+
array_node
91+
Owl_types.[|R []; I 10; R[0; 5]|]
92+
Bigarray.Float32
93+
store;;
94+
(*
95+
C0 C1 C2 C3 C4 C5
96+
R[0,0] 68.0272 44.914 85.2431 39.0772 26.582 16.577
97+
R[1,0] 88.418 77.0368 43.4968 45.1263 8.95641 76.9155
98+
R[2,0] 98.4036 77.8744 67.6689 56.8803 37.0718 97.042
99+
R[3,0] 22.8653 20.1767 88.9549 22.1052 9.86822 10.8826
100+
R[4,0] 55.6043 93.8599 60.3723 40.543 46.8199 97.282
101+
... ... ... ... ... ...
102+
R[20,0] 61.2473 78.8035 52.3056 59.5631 78.2462 52.4205
103+
R[21,0] -INF -INF -INF -INF -INF -INF
104+
R[22,0] -INF -INF -INF -INF -INF -INF
105+
R[23,0] -INF -INF -INF -INF -INF -INF
106+
R[24,0] -INF -INF -INF -INF -INF -INF *)
107+
108+
FilesystemStore.array_metadata array_node store
109+
|> Result.get_ok
110+
|> ArrayMetadata.shape;;
111+
(* - : int array = [|25; 32; 10|] *)
112+
```

dune-project

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
(lang dune 3.15)
2+
3+
(name zarr)
4+
5+
(generate_opam_files true)
6+
7+
(source
8+
(github zoj613/zarr-ml))
9+
10+
(authors "Author Name")
11+
12+
(maintainers "Maintainer Name")
13+
14+
(license BSD-3-Clause)
15+
16+
(documentation https://url/to/documentation)
17+
18+
(package
19+
(name zarr)
20+
(synopsis "A short synopsis")
21+
(description "A longer description")
22+
(depends
23+
dune
24+
(ocaml (>= 4.14.2))
25+
yojson
26+
ppx_derviving_yojson
27+
ezgzip
28+
checkseum
29+
stdint
30+
owl)
31+
(tags
32+
(topics "to describe" your project)))
33+
34+
; See the complete stanza docs at https://dune.readthedocs.io/en/stable/dune-files.html#dune-project

lib/codecs/array_to_array.ml

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
module Ndarray = Owl.Dense.Ndarray.Generic
2+
3+
type dimension_order = int array
4+
5+
type array_to_array =
6+
| Transpose of dimension_order
7+
8+
type error =
9+
[ `Invalid_transpose_order of dimension_order * string ]
10+
11+
(* https://zarr-specs.readthedocs.io/en/latest/v3/codecs/transpose/v1.0.html *)
12+
module TransposeCodec = struct
13+
type config = {order : int array} [@@deriving yojson]
14+
type transpose = config Util.ext_point [@@deriving yojson]
15+
16+
let compute_encoded_size input_size = input_size
17+
18+
let encode o x =
19+
try Ok (Ndarray.transpose ~axis:o x) with
20+
| Failure s -> Error (`Invalid_transpose_order (o, s))
21+
22+
let decode o x =
23+
let inv_order = Array.(make (length o) 0) in
24+
Array.iteri (fun i x -> inv_order.(x) <- i) o;
25+
try Ok (Ndarray.transpose ~axis:inv_order x) with
26+
| Failure s -> Error (`Invalid_transpose_order (o, s))
27+
28+
let to_yojson order =
29+
transpose_to_yojson
30+
{name = "transpose"; configuration = {order}}
31+
32+
let parse_order o =
33+
let o' = Array.copy o in
34+
Array.fast_sort Int.compare o';
35+
if o' <> Array.init (Array.length o') Fun.id then
36+
Error (`Invalid_transpose_order (o, ""))
37+
else
38+
Result.ok @@ Transpose o
39+
40+
let of_yojson x =
41+
let open Util.Result_syntax in
42+
transpose_of_yojson x >>= fun trans ->
43+
parse_order trans.configuration.order
44+
>>? fun (`Invalid_transpose_order _) -> "Invalid transpose order"
45+
end
46+
47+
module ArrayToArray = struct
48+
let compute_encoded_size input_size = function
49+
| Transpose _ -> TransposeCodec.compute_encoded_size input_size
50+
51+
let encode t x =
52+
match t with
53+
| Transpose order -> TransposeCodec.encode order x
54+
55+
let decode t x =
56+
match t with
57+
| Transpose order -> TransposeCodec.decode order x
58+
59+
let to_yojson = function
60+
| Transpose order -> TransposeCodec.to_yojson order
61+
62+
let of_yojson x =
63+
match Util.get_name x with
64+
| "transpose" -> TransposeCodec.of_yojson x
65+
| s -> Error ("array->array codec not supported: " ^ s)
66+
end

lib/codecs/array_to_array.mli

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module Ndarray = Owl.Dense.Ndarray.Generic
2+
3+
type dimension_order = int array
4+
5+
type array_to_array =
6+
| Transpose of dimension_order
7+
8+
type error =
9+
[ `Invalid_transpose_order of dimension_order * string ]
10+
11+
module ArrayToArray : sig
12+
val compute_encoded_size : int -> array_to_array -> int
13+
val encode
14+
: array_to_array ->
15+
('a, 'b) Ndarray.t ->
16+
(('a, 'b) Ndarray.t, [> error]) result
17+
val decode
18+
: array_to_array ->
19+
('a, 'b) Ndarray.t ->
20+
(('a, 'b) Ndarray.t, [> error]) result
21+
val of_yojson : Yojson.Safe.t -> (array_to_array, string) result
22+
val to_yojson : array_to_array -> Yojson.Safe.t
23+
end

0 commit comments

Comments
 (0)