1+ import datetime
2+
13import numpy as np
24import zarr
5+ from zarr .errors import ArrayNotFoundError
6+ from zarr .errors import ContainsArrayError
7+ from zarr .errors import ContainsGroupError
8+ from zarr .errors import PathNotFoundError
39
410
511def create_zarr_patch_structure (
@@ -11,34 +17,129 @@ def create_zarr_patch_structure(
1117 sensing_times ,
1218 constellation ,
1319 bands ,
20+ overwrite ,
1421):
1522 if not sensing_times .size == 0 :
1623 patch_size_pixels = patch_size // min (b ["gsd" ] for _ , b in bands .items ())
1724
1825 patch_constellation_path = f"{ storage_path } /{ tile_id } /{ constellation } "
19- zarr .open (fs_mapper (patch_constellation_path ), mode = "a" )
26+ zarr .open (
27+ fs_mapper (patch_constellation_path ),
28+ mode = "a" ,
29+ ) # make sure the path exists
2030
2131 patch_path = f"{ patch_constellation_path } /data"
22- zarr .open_array (
23- fs_mapper (patch_path ),
24- "w" ,
25- shape = (
26- len (sensing_times ),
27- len (bands ),
28- int (patch_size_pixels ),
29- int (patch_size_pixels ),
30- ),
31- chunks = (1 , 1 , int (chunk_size ), int (chunk_size )),
32- dtype = np .uint16 ,
33- )
34-
35- # Create timestamps array
36- timestamps_path = f"{ patch_constellation_path } /timestamps"
37- z_dates = zarr .open_array (
38- fs_mapper (f"{ timestamps_path } " ),
39- mode = "w" ,
40- shape = (len (sensing_times )),
41- chunks = (len (sensing_times )),
42- dtype = "<U27" ,
43- )
44- z_dates [:] = sensing_times
32+
33+ if overwrite :
34+ zarr .open_array (
35+ fs_mapper (patch_path ),
36+ "w" ,
37+ shape = (
38+ len (sensing_times ),
39+ len (bands ),
40+ int (patch_size_pixels ),
41+ int (patch_size_pixels ),
42+ ),
43+ chunks = (1 , 1 , int (chunk_size ), int (chunk_size )),
44+ dtype = np .uint16 ,
45+ )
46+
47+ # Create timestamps array
48+ timestamps_path = f"{ patch_constellation_path } /timestamps"
49+ z_dates = zarr .open_array (
50+ fs_mapper (f"{ timestamps_path } " ),
51+ mode = "w" ,
52+ shape = (len (sensing_times )),
53+ chunks = (len (sensing_times )),
54+ dtype = "<U27" ,
55+ )
56+ z_dates [:] = sensing_times
57+
58+ else :
59+
60+ # read current timestamps
61+ timestamps_path = f"{ patch_constellation_path } /timestamps"
62+
63+ try :
64+ existing_timestamps = zarr .open_array (fs_mapper (timestamps_path ), "r" )[
65+ :
66+ ]
67+ existing_timestamps = np .array (
68+ [
69+ np .datetime64 (datetime .datetime .fromisoformat (el ))
70+ for el in existing_timestamps
71+ ],
72+ )
73+
74+ new_timesteps = np .array (sensing_times )[
75+ ~ np .isin (sensing_times , existing_timestamps )
76+ ]
77+
78+ if new_timesteps .shape [0 ] > 0 :
79+ assert max (existing_timestamps ) <= min (
80+ new_timesteps ,
81+ ), "Sat-Extractor can only append more recent data or overwrite existing data. "
82+
83+ # get union of sensing times
84+ timestamps_union = np .union1d (existing_timestamps , sensing_times )
85+
86+ except (PathNotFoundError , ContainsGroupError , ArrayNotFoundError ):
87+ timestamps_union = sensing_times
88+ except Exception as e :
89+ raise e
90+
91+ # write sensing times fresh
92+ z_dates = zarr .open_array (
93+ fs_mapper (f"{ timestamps_path } " ),
94+ mode = "w" ,
95+ shape = (len (timestamps_union )),
96+ chunks = (len (timestamps_union )),
97+ dtype = "<U27" ,
98+ )
99+ z_dates [:] = timestamps_union
100+
101+ # resize any existing array based thereon
102+
103+ # data
104+ try :
105+ # if it doesn't exist, create it.
106+ z_data = zarr .open_array (
107+ fs_mapper (patch_path ),
108+ "w-" ,
109+ shape = (
110+ len (timestamps_union ),
111+ len (bands ),
112+ int (patch_size_pixels ),
113+ int (patch_size_pixels ),
114+ ),
115+ chunks = (1 , 1 , int (chunk_size ), int (chunk_size )),
116+ dtype = np .uint16 ,
117+ )
118+ except ContainsArrayError :
119+ z_data = zarr .open_array (fs_mapper (patch_path ), "r+" )
120+
121+ data_shape = z_data .shape
122+ z_data .resize (len (timestamps_union ), * data_shape [1 :])
123+
124+ except Exception as e :
125+ raise e
126+
127+ # masks
128+ mask_root_path = f"{ patch_constellation_path } /mask"
129+ z_mask_dir = zarr .open_group (
130+ fs_mapper (mask_root_path ),
131+ "a" ,
132+ )
133+
134+ for mask_key in z_mask_dir .keys ():
135+
136+ mask_path = f"{ mask_root_path } /{ mask_key } "
137+
138+ z_mask = zarr .open_array (
139+ fs_mapper (mask_path ),
140+ "r+" ,
141+ )
142+
143+ mask_shape = z_mask .shape
144+
145+ z_mask .resize (len (timestamps_union ), * mask_shape [1 :])
0 commit comments