33import pytest
44
55import iris
6+
7+ iris .FUTURE .save_split_attrs = True
68from iris .coords import AuxCoord , DimCoord
79from iris .cube import Cube
810
911NX , N_STRLEN = 3 , 64
1012TEST_STRINGS = ["Münster" , "London" , "Amsterdam" ]
1113TEST_COORD_VALS = ["bun" , "éclair" , "sandwich" ]
1214
15+ # VARS_COORDS_SHARE_STRING_DIM = True
16+ VARS_COORDS_SHARE_STRING_DIM = False
17+ if VARS_COORDS_SHARE_STRING_DIM :
18+ TEST_COORD_VALS [- 1 ] = "Xsandwich" # makes the max coord strlen same as data one
19+
1320
1421def convert_strings_to_chararray (string_array_1d , maxlen , encoding = "utf-8" ):
1522 bbytes = [text .encode (encoding ) for text in string_array_1d ]
@@ -19,18 +26,33 @@ def convert_strings_to_chararray(string_array_1d, maxlen, encoding="utf-8"):
1926 return chararray
2027
2128
22- # def convert_chararray_to_strings(char_array_2d, maxlen: int | None =0, encoding="utf-8"):
23- # strings = [bytes.decode(encoding) for bytes in char_array_2d]
24- # if not maxlen:
25- # maxlen = max(len(string) for string in strings)
26- # dtype_str = f"S{maxlen}"
27- # string_array = np.array(strings, dtype=dtype_str)
28- # return string_array
29+ def convert_bytesarray_to_strings (
30+ byte_array , encoding = "utf-8" , string_length : int | None = None
31+ ):
32+ """Convert bytes to strings.
33+
34+ N.B. for now at least, we assume the string dim is **always the last one**.
35+ """
36+ bytes_shape = byte_array .shape
37+ var_shape = bytes_shape [:- 1 ]
38+ if string_length is None :
39+ string_length = bytes_shape [- 1 ]
40+ string_dtype = f"U{ string_length } "
41+ result = np .empty (var_shape , dtype = string_dtype )
42+ for ndindex in np .ndindex (var_shape ):
43+ element_bytes = byte_array [ndindex ]
44+ bytes = b"" .join ([b if b else b"\0 " for b in element_bytes ])
45+ string = bytes .decode (encoding )
46+ result [ndindex ] = string
47+ return result
2948
3049
3150INCLUDE_COORD = True
3251# INCLUDE_COORD = False
3352
53+ INCLUDE_NUMERIC_AUXCOORD = True
54+ # INCLUDE_NUMERIC_AUXCOORD = False
55+
3456
3557def make_testfile (filepath , chararray , coordarray , encoding_str = None ):
3658 with nc .Dataset (filepath , "w" ) as ds :
@@ -51,6 +73,13 @@ def make_testfile(filepath, chararray, coordarray, encoding_str=None):
5173 v_co [:] = coordarray
5274 if encoding_str is not None :
5375 v_co ._Encoding = encoding_str
76+ if INCLUDE_NUMERIC_AUXCOORD :
77+ v_num = ds .createVariable (
78+ "v_num" ,
79+ float ,
80+ dimensions = ("x" ,),
81+ )
82+ v_num [:] = np .arange (NX )
5483 v = ds .createVariable (
5584 "v" ,
5685 "S1" ,
@@ -63,7 +92,10 @@ def make_testfile(filepath, chararray, coordarray, encoding_str=None):
6392 if encoding_str is not None :
6493 v ._Encoding = encoding_str
6594 if INCLUDE_COORD :
66- v .coordinates = "v_co"
95+ coords_str = "v_co"
96+ if INCLUDE_NUMERIC_AUXCOORD :
97+ coords_str += " v_num"
98+ v .coordinates = coords_str
6799
68100
69101def make_testcube (
@@ -111,8 +143,10 @@ def show_result(filepath):
111143 )
112144 print ("-data-" )
113145 print (repr (cube .data ))
146+ print ("-numeric auxcoord data-" )
147+ print (repr (cube .coord ("x" ).points ))
114148 if INCLUDE_COORD :
115- print ("-coord data-" )
149+ print ("-string auxcoord data-" )
116150 try :
117151 print (repr (cube .coord ("v_co" ).points ))
118152 except Exception as err2 :
@@ -160,3 +194,19 @@ def test_save_encodings(encoding):
160194 filepath = f"tmp_save_{ str (encoding )} .nc"
161195 iris .save (cube , filepath )
162196 show_result (filepath )
197+
198+
199+ # @pytest.mark.parametrize("ndim", [1, 2])
200+ # def test_convert_bytes_to_strings(ndim: int):
201+ # if ndim == 1:
202+ # source = convert_strings_to_chararray(TEST_STRINGS, 16)
203+ # elif ndim == 2:
204+ # source = np.stack([
205+ # convert_strings_to_chararray(TEST_STRINGS, 16),
206+ # convert_strings_to_chararray(TEST_COORD_VALS, 16),
207+ # ])
208+ # else:
209+ # raise ValueError(f"Unexpected param ndim={ndim}.")
210+ # # convert the strings to bytes
211+ # result = convert_bytesarray_to_strings(source)
212+ # print(result)
0 commit comments