OCaml Zarr jsont codecs for v2/v3 and common conventions
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: print conventions, extensions, and unknown attrs in tree

zarr-inspect now shows decoded convention metadata inline:
- proj: code, wkt2, projjson
- spatial: dims, bbox, transform, shape, registration
- multiscales: level count, layout with derivation chains
- unknown keys: truncated JSON values

Root attrs and per-child attrs are both displayed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+137 -46
+137 -46
bin/zarr_inspect.ml
··· 54 54 | Error e -> 55 55 Printf.eprintf "Error encoding %s: %s\n" label e 56 56 57 + let pp_v2_dtype = function 58 + | `Float (_, n) -> Printf.sprintf "float%d" (n*8) 59 + | `Int (_, n) -> Printf.sprintf "int%d" (n*8) 60 + | `Uint (_, n) -> Printf.sprintf "uint%d" (n*8) 61 + | `Bool -> "bool" 62 + | `Complex (_, n) -> Printf.sprintf "complex%d" (n*8) 63 + | `Datetime (_, u) -> Printf.sprintf "datetime[%s]" u 64 + | `Timedelta (_, u) -> Printf.sprintf "timedelta[%s]" u 65 + | `String n -> Printf.sprintf "S%d" n 66 + | `Unicode (_, n) -> Printf.sprintf "U%d" n 67 + | `Raw n -> Printf.sprintf "V%d" n 68 + | `Structured _ -> "structured" 69 + 70 + let pp_v3_dtype = function 71 + | `Bool -> "bool" | `Int8 -> "int8" | `Int16 -> "int16" 72 + | `Int32 -> "int32" | `Int64 -> "int64" 73 + | `Uint8 -> "uint8" | `Uint16 -> "uint16" 74 + | `Uint32 -> "uint32" | `Uint64 -> "uint64" 75 + | `Float16 -> "float16" | `Float32 -> "float32" 76 + | `Float64 -> "float64" 77 + | `Complex64 -> "complex64" | `Complex128 -> "complex128" 78 + | `Raw n -> Printf.sprintf "r%d" n 79 + | `Other o -> Zarr_jsont.Other_ext.name o 80 + 81 + let pp_shape shape = String.concat "x" (List.map string_of_int shape) 82 + 83 + let pp_floats fs = String.concat "," (List.map (Printf.sprintf "%.4g") fs) 84 + 85 + let print_attrs indent (attrs : Zarr_jsont.Attrs.t) = 86 + (* proj *) 87 + (match Zarr_jsont.Attrs.proj attrs with 88 + | Some p -> 89 + let parts = List.filter_map Fun.id [ 90 + Option.map (Printf.sprintf "code=%s") (Zarr_jsont.Conv.Proj.code p); 91 + Option.map (fun _ -> "wkt2=...") (Zarr_jsont.Conv.Proj.wkt2 p); 92 + Option.map (fun _ -> "projjson=...") (Zarr_jsont.Conv.Proj.projjson p); 93 + ] in 94 + if parts <> [] then 95 + Printf.printf "%sproj: %s\n" indent (String.concat " " parts) 96 + | None -> ()); 97 + (* spatial *) 98 + (match Zarr_jsont.Attrs.spatial attrs with 99 + | Some s -> 100 + let dims = String.concat "," (Zarr_jsont.Conv.Spatial.dimensions s) in 101 + Printf.printf "%sspatial: dims=[%s]" indent dims; 102 + (match Zarr_jsont.Conv.Spatial.bbox s with 103 + | Some bbox -> Printf.printf " bbox=[%s]" (pp_floats bbox) 104 + | None -> ()); 105 + (match Zarr_jsont.Conv.Spatial.transform s with 106 + | Some t -> Printf.printf " transform=[%s]" (pp_floats t) 107 + | None -> ()); 108 + (match Zarr_jsont.Conv.Spatial.shape s with 109 + | Some sh -> Printf.printf " shape=[%s]" (pp_shape sh) 110 + | None -> ()); 111 + (match Zarr_jsont.Conv.Spatial.registration s with 112 + | Some `Pixel -> Printf.printf " reg=pixel" 113 + | Some `Node -> Printf.printf " reg=node" 114 + | None -> ()); 115 + Printf.printf "\n" 116 + | None -> ()); 117 + (* multiscales *) 118 + (match Zarr_jsont.Attrs.multiscales attrs with 119 + | Some m -> 120 + let layout = Zarr_jsont.Conv.Multiscales.layout m in 121 + Printf.printf "%smultiscales: %d levels" indent (List.length layout); 122 + (match Zarr_jsont.Conv.Multiscales.resampling_method m with 123 + | Some r -> Printf.printf " resampling=%s" r | None -> ()); 124 + Printf.printf "\n"; 125 + List.iter (fun item -> 126 + let asset = Zarr_jsont.Conv.Multiscales.Layout_item.asset item in 127 + Printf.printf "%s %s" indent asset; 128 + (match Zarr_jsont.Conv.Multiscales.Layout_item.derived_from item with 129 + | Some d -> Printf.printf " <- %s" d | None -> ()); 130 + (match Zarr_jsont.Conv.Multiscales.Layout_item.transform item with 131 + | Some t -> 132 + (match Zarr_jsont.Conv.Multiscales.Transform.scale t with 133 + | Some s -> Printf.printf " scale=[%s]" (pp_floats s) | None -> ()) 134 + | None -> ()); 135 + Printf.printf "\n" 136 + ) layout 137 + | None -> ()); 138 + (* unknown keys *) 139 + (match Zarr_jsont.Attrs.unknown attrs with 140 + | Jsont.Object (mems, _) when mems <> [] -> 141 + List.iter (fun ((k, _), v) -> 142 + let vs = match Jsont_bytesrw.encode_string ~format:Jsont.Minify Jsont.json v with 143 + | Ok s -> 144 + if String.length s > 60 then String.sub s 0 57 ^ "..." 145 + else s 146 + | Error _ -> "?" 147 + in 148 + Printf.printf "%s%s: %s\n" indent k vs 149 + ) mems 150 + | _ -> ()) 151 + 152 + let node_attrs = function 153 + | `V2 n -> Zarr_jsont.V2_node.attrs n 154 + | `V3 n -> Zarr_jsont.V3_node.attrs n 155 + 57 156 let rec print_tree indent children = 58 157 List.iter (fun (name, (result : Zarr_jsont.probe_result)) -> 59 158 let kind = match result.node with 60 159 | `V2 n -> 61 160 (match Zarr_jsont.V2_node.kind n with 62 161 | `Array a -> 63 - let shape = Zarr_jsont.V2.Array_meta.shape a in 64 162 Printf.sprintf "array %s %s" 65 - (match Zarr_jsont.V2.Array_meta.dtype a with 66 - | `Float (_, n) -> Printf.sprintf "float%d" (n*8) 67 - | `Int (_, n) -> Printf.sprintf "int%d" (n*8) 68 - | `Uint (_, n) -> Printf.sprintf "uint%d" (n*8) 69 - | `Bool -> "bool" 70 - | _ -> "?") 71 - (String.concat "x" (List.map string_of_int shape)) 163 + (pp_v2_dtype (Zarr_jsont.V2.Array_meta.dtype a)) 164 + (pp_shape (Zarr_jsont.V2.Array_meta.shape a)) 72 165 | `Group -> "group") 73 166 | `V3 n -> 74 167 (match Zarr_jsont.V3_node.kind n with 75 168 | `Array a -> 76 - let shape = Zarr_jsont.V3.Array_meta.shape a in 77 - let dt = match Zarr_jsont.V3.Array_meta.data_type a with 78 - | `Bool -> "bool" | `Int8 -> "int8" | `Int16 -> "int16" 79 - | `Int32 -> "int32" | `Int64 -> "int64" 80 - | `Uint8 -> "uint8" | `Uint16 -> "uint16" 81 - | `Uint32 -> "uint32" | `Uint64 -> "uint64" 82 - | `Float16 -> "float16" | `Float32 -> "float32" 83 - | `Float64 -> "float64" 84 - | `Complex64 -> "complex64" | `Complex128 -> "complex128" 85 - | `Raw n -> Printf.sprintf "r%d" n 86 - | `Other o -> Zarr_jsont.Other_ext.name o 87 - in 88 - Printf.sprintf "array %s %s" dt 89 - (String.concat "x" (List.map string_of_int shape)) 169 + Printf.sprintf "array %s %s" 170 + (pp_v3_dtype (Zarr_jsont.V3.Array_meta.data_type a)) 171 + (pp_shape (Zarr_jsont.V3.Array_meta.shape a)) 90 172 | `Group -> "group") 91 173 in 92 174 Printf.printf "%s%s [%s]\n" indent name kind; 175 + let attrs = node_attrs result.node in 176 + let sub_indent = indent ^ " " in 177 + (* Also check probe_result.attrs for v2 separate .zattrs *) 178 + let attrs = match result.attrs with 179 + | Some a -> a | None -> attrs 180 + in 181 + print_attrs sub_indent attrs; 93 182 if result.children <> [] then 94 - print_tree (indent ^ " ") result.children 183 + print_tree sub_indent result.children 95 184 ) children 96 185 97 186 let pretty_print_result { Zarr_jsont.node; attrs; children; _ } = 98 - (match node with 99 - | `V2 n -> 100 - (match Zarr_jsont.V2_node.kind n with 101 - | `Array a -> 102 - encode_and_print Zarr_jsont.V2.array_meta_jsont a "v2 .zarray" 103 - | `Group -> 104 - Printf.printf "── v2 .zgroup ──\n"; 105 - Format.printf "{@\n \"zarr_format\": 2@\n}@.") 106 - | `V3 n -> 107 - (match Zarr_jsont.V3_node.kind n with 108 - | `Array _ -> 109 - encode_and_print Zarr_jsont.v3_jsont n "v3 zarr.json (array)" 110 - | `Group -> 111 - encode_and_print Zarr_jsont.v3_jsont n "v3 zarr.json (group)")); 112 - (match attrs with 113 - | Some a -> 114 - (match Jsont.Json.encode Zarr_jsont.attrs_jsont a with 115 - | Ok json -> 116 - Printf.printf "\n── v2 .zattrs ──\n"; 117 - Format.printf "%a@." pp_json json 118 - | Error e -> 119 - Printf.eprintf "Error encoding .zattrs: %s\n" e) 120 - | None -> ()); 187 + let root_kind = match node with 188 + | `V2 n -> 189 + (match Zarr_jsont.V2_node.kind n with 190 + | `Array a -> 191 + encode_and_print Zarr_jsont.V2.array_meta_jsont a "v2 .zarray"; 192 + "v2 array" 193 + | `Group -> 194 + Printf.printf "── v2 .zgroup ──\n"; 195 + "v2 group") 196 + | `V3 n -> 197 + (match Zarr_jsont.V3_node.kind n with 198 + | `Array _ -> 199 + encode_and_print Zarr_jsont.v3_jsont n "v3 zarr.json (array)"; 200 + "v3 array" 201 + | `Group -> 202 + Printf.printf "── v3 group ──\n"; 203 + "v3 group") 204 + in 205 + ignore root_kind; 206 + (* Print root attrs *) 207 + let root_attrs = match attrs with 208 + | Some a -> a 209 + | None -> node_attrs node 210 + in 211 + print_attrs " " root_attrs; 121 212 if children <> [] then begin 122 213 Printf.printf "\n── children ──\n"; 123 214 print_tree " " children