array_write_read/
array_write_read.rs

1#![allow(missing_docs)]
2
3use rayon::iter::{IntoParallelIterator, ParallelIterator};
4use zarrs::storage::{
5    storage_adapter::usage_log::UsageLogStorageAdapter, ReadableWritableListableStorage,
6};
7
8fn array_write_read() -> Result<(), Box<dyn std::error::Error>> {
9    use std::sync::Arc;
10    use zarrs::{
11        array::{DataType, ZARR_NAN_F32},
12        array_subset::ArraySubset,
13        node::Node,
14        storage::store,
15    };
16
17    // Create a store
18    // let path = tempfile::TempDir::new()?;
19    // let mut store: ReadableWritableListableStorage =
20    //     Arc::new(zarrs::filesystem::FilesystemStore::new(path.path())?);
21    // let mut store: ReadableWritableListableStorage = Arc::new(
22    //     zarrs::filesystem::FilesystemStore::new("zarrs/tests/data/array_write_read.zarr")?,
23    // );
24    let mut store: ReadableWritableListableStorage = Arc::new(store::MemoryStore::new());
25    if let Some(arg1) = std::env::args().collect::<Vec<_>>().get(1) {
26        if arg1 == "--usage-log" {
27            let log_writer = Arc::new(std::sync::Mutex::new(
28                // std::io::BufWriter::new(
29                std::io::stdout(),
30                //    )
31            ));
32            store = Arc::new(UsageLogStorageAdapter::new(store, log_writer, || {
33                chrono::Utc::now().format("[%T%.3f] ").to_string()
34            }));
35        }
36    }
37
38    // Create the root group
39    zarrs::group::GroupBuilder::new()
40        .build(store.clone(), "/")?
41        .store_metadata()?;
42
43    // Create a group with attributes
44    let group_path = "/group";
45    let mut group = zarrs::group::GroupBuilder::new().build(store.clone(), group_path)?;
46    group
47        .attributes_mut()
48        .insert("foo".into(), serde_json::Value::String("bar".into()));
49    group.store_metadata()?;
50
51    println!(
52        "The group metadata is:\n{}\n",
53        group.metadata().to_string_pretty()
54    );
55
56    // Create an array
57    let array_path = "/group/array";
58    let array = zarrs::array::ArrayBuilder::new(
59        vec![8, 8], // array shape
60        vec![4, 4], // regular chunk shape
61        DataType::Float32,
62        ZARR_NAN_F32,
63    )
64    // .bytes_to_bytes_codecs(vec![]) // uncompressed
65    .dimension_names(["y", "x"].into())
66    // .storage_transformers(vec![].into())
67    .build(store.clone(), array_path)?;
68
69    // Write array metadata to store
70    array.store_metadata()?;
71
72    println!(
73        "The array metadata is:\n{}\n",
74        array.metadata().to_string_pretty()
75    );
76
77    // Write some chunks
78    (0..2).into_par_iter().try_for_each(|i| {
79        let chunk_indices: Vec<u64> = vec![0, i];
80        let chunk_subset = array.chunk_grid().subset(&chunk_indices)?.ok_or_else(|| {
81            zarrs::array::ArrayError::InvalidChunkGridIndicesError(chunk_indices.to_vec())
82        })?;
83        array.store_chunk_elements(
84            &chunk_indices,
85            &vec![i as f32 * 0.1; chunk_subset.num_elements() as usize],
86        )
87    })?;
88
89    let subset_all = array.subset_all();
90    let data_all = array.retrieve_array_subset_ndarray::<f32>(&subset_all)?;
91    println!("store_chunk [0, 0] and [0, 1]:\n{data_all:+4.1}\n");
92
93    // Store multiple chunks
94    array.store_chunks_elements::<f32>(
95        &ArraySubset::new_with_ranges(&[1..2, 0..2]),
96        &[
97            //
98            1.0, 1.0, 1.0, 1.0, 1.1, 1.1, 1.1, 1.1, 1.0, 1.0, 1.0, 1.0, 1.1, 1.1, 1.1, 1.1,
99            //
100            1.0, 1.0, 1.0, 1.0, 1.1, 1.1, 1.1, 1.1, 1.0, 1.0, 1.0, 1.0, 1.1, 1.1, 1.1, 1.1,
101        ],
102    )?;
103    let data_all = array.retrieve_array_subset_ndarray::<f32>(&subset_all)?;
104    println!("store_chunks [1..2, 0..2]:\n{data_all:+4.1}\n");
105
106    // Write a subset spanning multiple chunks, including updating chunks already written
107    array.store_array_subset_elements::<f32>(
108        &ArraySubset::new_with_ranges(&[3..6, 3..6]),
109        &[-3.3, -3.4, -3.5, -4.3, -4.4, -4.5, -5.3, -5.4, -5.5],
110    )?;
111    let data_all = array.retrieve_array_subset_ndarray::<f32>(&subset_all)?;
112    println!("store_array_subset [3..6, 3..6]:\n{data_all:+4.1}\n");
113
114    // Store array subset
115    array.store_array_subset_elements::<f32>(
116        &ArraySubset::new_with_ranges(&[0..8, 6..7]),
117        &[-0.6, -1.6, -2.6, -3.6, -4.6, -5.6, -6.6, -7.6],
118    )?;
119    let data_all = array.retrieve_array_subset_ndarray::<f32>(&subset_all)?;
120    println!("store_array_subset [0..8, 6..7]:\n{data_all:+4.1}\n");
121
122    // Store chunk subset
123    array.store_chunk_subset_elements::<f32>(
124        // chunk indices
125        &[1, 1],
126        // subset within chunk
127        &ArraySubset::new_with_ranges(&[3..4, 0..4]),
128        &[-7.4, -7.5, -7.6, -7.7],
129    )?;
130    let data_all = array.retrieve_array_subset_ndarray::<f32>(&subset_all)?;
131    println!("store_chunk_subset [3..4, 0..4] of chunk [1, 1]:\n{data_all:+4.1}\n");
132
133    // Erase a chunk
134    array.erase_chunk(&[0, 0])?;
135    let data_all = array.retrieve_array_subset_ndarray::<f32>(&subset_all)?;
136    println!("erase_chunk [0, 0]:\n{data_all:+4.1}\n");
137
138    // Read a chunk
139    let chunk_indices = vec![0, 1];
140    let data_chunk = array.retrieve_chunk_ndarray::<f32>(&chunk_indices)?;
141    println!("retrieve_chunk [0, 1]:\n{data_chunk:+4.1}\n");
142
143    // Read chunks
144    let chunks = ArraySubset::new_with_ranges(&[0..2, 1..2]);
145    let data_chunks = array.retrieve_chunks_ndarray::<f32>(&chunks)?;
146    println!("retrieve_chunks [0..2, 1..2]:\n{data_chunks:+4.1}\n");
147
148    // Retrieve an array subset
149    let subset = ArraySubset::new_with_ranges(&[2..6, 3..5]); // the center 4x2 region
150    let data_subset = array.retrieve_array_subset_ndarray::<f32>(&subset)?;
151    println!("retrieve_array_subset [2..6, 3..5]:\n{data_subset:+4.1}\n");
152
153    // Show the hierarchy
154    let node = Node::open(&store, "/").unwrap();
155    let tree = node.hierarchy_tree();
156    println!("hierarchy_tree:\n{}", tree);
157
158    Ok(())
159}
160
161fn main() {
162    if let Err(err) = array_write_read() {
163        println!("{:?}", err);
164    }
165}