|
6 | 6 | @testset "Python zarr implementation" begin
|
7 | 7 |
|
8 | 8 | import Mmap
|
9 |
| -using PyCall |
10 |
| -import PyCall: @py_str |
| 9 | +using PythonCall |
11 | 10 | #If we are on conda, import zarr
|
12 |
| -pyimport_conda("zarr","zarr") |
| 11 | +zarr = pyimport("zarr") |
13 | 12 |
|
14 | 13 | #Create some directories
|
15 | 14 | proot = tempname()
|
@@ -82,113 +81,114 @@ end
|
82 | 81 |
|
83 | 82 | # Test reading in python
|
84 | 83 | for julia_path in (pjulia, pjulia*".zip")
|
85 |
| -py""" |
86 |
| -import zarr |
87 |
| -import numcodecs |
88 |
| -g = zarr.open_group($julia_path) |
89 |
| -gatts = g.attrs |
90 |
| -""" |
| 84 | + g = zarr.open_group(julia_path) |
| 85 | + gatts = pyconvert(Any, g.attrs) |
91 | 86 |
|
92 |
| -#Test group attributes |
93 |
| -@test py"gatts['String attribute']" == "One" |
94 |
| -@test py"gatts['Int attribute']" == 5 |
95 |
| -@test py"gatts['Float attribute']" == 10.5 |
| 87 | + #Test group attributes |
| 88 | + @test gatts["String attribute"] == "One" |
| 89 | + @test gatts["Int attribute"] == 5 |
| 90 | + @test gatts["Float attribute"] == 10.5 |
96 | 91 |
|
97 |
| -dtypesp = ("uint8","uint16","uint32","uint64", |
98 |
| - "int8","int16","int32","int64", |
99 |
| - "float16","float32","float64", |
100 |
| - "complex64", "complex128","bool","S10","U10", "O") |
| 92 | + dtypesp = ("uint8","uint16","uint32","uint64", |
| 93 | + "int8","int16","int32","int64", |
| 94 | + "float16","float32","float64", |
| 95 | + "complex64", "complex128","bool","S10","U10", "O") |
101 | 96 |
|
102 |
| -#Test accessing arrays from python and reading data |
103 |
| -for i=1:length(dtypes), co in compressors |
104 |
| - compstr,comp = co |
105 |
| - t = dtypes[i] |
106 |
| - tp = dtypesp[i] |
107 |
| - arname = string("a",t,compstr) |
108 |
| - py""" |
109 |
| - ar=g[$arname] |
110 |
| - """ |
| 97 | + #Test accessing arrays from python and reading data |
| 98 | + for i=1:length(dtypes), co in compressors |
| 99 | + compstr,comp = co |
| 100 | + t = dtypes[i] |
| 101 | + tp = dtypesp[i] |
| 102 | + arname = string("a",t,compstr) |
| 103 | + ar=g[arname] |
111 | 104 |
|
112 |
| - @test py"ar.attrs['This is a nested attribute']" == Dict("a"=>5) |
113 |
| - @test py"ar.dtype==$tp" |
114 |
| - @test py"ar.shape" == (2,6,10) |
115 |
| - if t<:MaxLengthString |
116 |
| - pyar = py"ar[:,:,:]" |
117 |
| - jar = [get(get(get(pyar,k-1),j-1),i-1) for i in 1:10, j in 1:6, k in 1:2] |
118 |
| - @test jar == testarrays[t] |
119 |
| - else |
120 |
| - @test py"ar[:,:,:]" == permutedims(testarrays[t],(3,2,1)) |
| 105 | + @test pyconvert(Any, ar.attrs["This is a nested attribute"]) == Dict("a"=>5) |
| 106 | + @test pyeq(Bool, ar.dtype, tp) |
| 107 | + @test pyconvert(Tuple, ar.shape) == (2,6,10) |
| 108 | + if t<:MaxLengthString || t<:String |
| 109 | + jar = [ |
| 110 | + if tp == "S10" |
| 111 | + pyconvert(String, ar[k, j, i].decode()) |
| 112 | + else |
| 113 | + pyconvert(String, ar[k, j, i]) |
| 114 | + end |
| 115 | + for i in 0:9, j in 0:5, k in 0:1 |
| 116 | + ] |
| 117 | + @test jar == testarrays[t] |
| 118 | + else |
| 119 | + @test PyArray(ar[pybuiltins.Ellipsis]) == permutedims(testarrays[t],(3,2,1)) |
| 120 | + end |
121 | 121 | end
|
122 |
| -end |
123 | 122 |
|
124 |
| -# Test reading filtered arrays from python |
125 |
| -for (filterstr, filter) in filters |
126 |
| - t = eltype(filter) == Any ? Float64 : eltype(filter) |
127 |
| - arname = string("filter_",filterstr) |
128 |
| - try |
129 |
| - py""" |
130 |
| - ar=g[$arname] |
131 |
| - """ |
132 |
| - catch e |
133 |
| - @error "Error loading group with filter $filterstr" exception=(e,catch_backtrace()) |
134 |
| - @test false # test failed. |
| 123 | + # Test reading filtered arrays from python |
| 124 | + for (filterstr, filter) in filters |
| 125 | + t = eltype(filter) == Any ? Float64 : eltype(filter) |
| 126 | + arname = string("filter_",filterstr) |
| 127 | + local ar |
| 128 | + try |
| 129 | + ar=g[arname] |
| 130 | + catch e |
| 131 | + @error "Error loading group with filter $filterstr" exception=(e,catch_backtrace()) |
| 132 | + @test false # test failed. |
| 133 | + end |
| 134 | + |
| 135 | + @test pyconvert(Any, ar.attrs["Filter test attribute"]) == Dict("b"=>6) |
| 136 | + @test pyconvert(Tuple, ar.shape) == (2,6,10) |
| 137 | + |
| 138 | + # Test zero-dimensional filtered array |
| 139 | + arname = string("filter_zerodim_",filterstr) |
| 140 | + ar_zero=g[arname] |
| 141 | + @test pyconvert(Tuple, ar_zero.shape) == () |
135 | 142 | end
|
136 |
| - |
137 |
| - @test py"ar.attrs['Filter test attribute']" == Dict("b"=>6) |
138 |
| - @test py"ar.shape" == (2,6,10) |
139 |
| - |
140 |
| - # Test zero-dimensional filtered array |
141 |
| - arname = string("filter_zerodim_",filterstr) |
142 |
| - py""" |
143 |
| - ar_zero=g[$arname] |
144 |
| - """ |
145 |
| - @test py"ar_zero.shape" == () |
146 |
| -end |
147 | 143 |
|
148 |
| -for i=1:length(dtypes), co in compressors |
149 |
| - compstr,comp = co |
150 |
| - t = dtypes[i] |
151 |
| - tp = dtypesp[i] |
152 |
| - if t == UInt64 |
153 |
| - continue |
154 |
| - # need to exclude UInt64: |
155 |
| - # need explicit conversion because of https://github.com/JuliaPy/PyCall.jl/issues/744 |
156 |
| - # but explicit conversion uses PyLong_AsLongLongAndOverflow, which converts everything |
157 |
| - # to a signed 64-bit integer, which can error out if the UInt64 is too large. |
158 |
| - # Adding an overload to PyCall for unsigned ints doesn't work with NumPy scalars because |
159 |
| - # they are not subtypes of integer: https://stackoverflow.com/a/58816671 |
160 |
| - end |
| 144 | + for i=1:length(dtypes), co in compressors |
| 145 | + compstr,comp = co |
| 146 | + t = dtypes[i] |
| 147 | + tp = dtypesp[i] |
| 148 | + if t == UInt64 |
| 149 | + continue |
| 150 | + # need to exclude UInt64: |
| 151 | + # need explicit conversion because of https://github.com/JuliaPy/PyCall.jl/issues/744 |
| 152 | + # but explicit conversion uses PyLong_AsLongLongAndOverflow, which converts everything |
| 153 | + # to a signed 64-bit integer, which can error out if the UInt64 is too large. |
| 154 | + # Adding an overload to PyCall for unsigned ints doesn't work with NumPy scalars because |
| 155 | + # they are not subtypes of integer: https://stackoverflow.com/a/58816671 |
| 156 | + end |
161 | 157 |
|
162 |
| - arname = string("azerodim",t,compstr) |
163 |
| - py""" |
164 |
| - ar=g[$arname] |
165 |
| - """ |
| 158 | + arname = string("azerodim",t,compstr) |
| 159 | + ar=g[arname] |
166 | 160 |
|
167 |
| - @test py"ar.dtype==$tp" |
168 |
| - @test py"ar.shape" == () |
169 |
| - @test convert(t, py"ar[()]") == testzerodimarrays[t] |
170 |
| -end |
171 |
| -py""" |
172 |
| -g.store.close() |
173 |
| -""" |
| 161 | + @test pyeq(Bool, ar.dtype, tp) |
| 162 | + @test pyconvert(Tuple, ar.shape) == () |
| 163 | + if t<:MaxLengthString || t<:String |
| 164 | + local x = if tp == "S10" |
| 165 | + pyconvert(String, ar[()].decode()) |
| 166 | + else |
| 167 | + pyconvert(String, ar[()]) |
| 168 | + end |
| 169 | + @test x == testzerodimarrays[t] |
| 170 | + else |
| 171 | + @test pyconvert(Any, ar[()])[] == testzerodimarrays[t] |
| 172 | + end |
| 173 | + end |
| 174 | + g.store.close() |
174 | 175 | end
|
175 | 176 |
|
176 | 177 | ## Now the other way around, we create a zarr array using the python lib and read back into julia
|
177 | 178 | data = rand(Int32,2,6,10)
|
178 |
| -py""" |
179 |
| -import numcodecs |
180 |
| -import numpy as np |
181 |
| -g = zarr.group($ppython) |
| 179 | + |
| 180 | +numpy = pyimport("numpy") |
| 181 | +numcodecs = pyimport("numcodecs") |
| 182 | +g = zarr.group(ppython) |
182 | 183 | g.attrs["groupatt"] = "Hi"
|
183 |
| -z1 = g.create_dataset("a1", shape=(2,6,10),chunks=(1,2,3), dtype='i4') |
184 |
| -z1[:,:,:]=$data |
185 |
| -z1.attrs["test"]={"b": 6} |
186 |
| -z2 = g.create_dataset("a2", shape=(5,),chunks=(5,), dtype='S1', compressor=numcodecs.Zlib()) |
187 |
| -z2[:]=[k for k in 'hallo'] |
188 |
| -z3 = g.create_dataset('a3', shape=(2,), dtype=str) |
189 |
| -z3[:]=np.asarray(['test1', 'test234'], dtype='O') |
190 |
| -zarr.consolidate_metadata($ppython) |
191 |
| -""" |
| 184 | +z1 = g.create_dataset("a1", shape=(2,6,10),chunks=(1,2,3), dtype="i4") |
| 185 | +z1[pybuiltins.Ellipsis] = numpy.array(data) |
| 186 | +z1.attrs["test"] = pydict(Dict("b"=>6)) |
| 187 | +z2 = g.create_dataset("a2", shape=(5,),chunks=(5,), dtype="S1", compressor=numcodecs.Zlib()) |
| 188 | +z2[pybuiltins.Ellipsis] = pylist([k for k in "hallo"]) |
| 189 | +z3 = g.create_dataset("a3", shape=(2,), dtype=pybuiltins.str) |
| 190 | +z3[pybuiltins.Ellipsis]=numpy.asarray(["test1", "test234"], dtype="O") |
| 191 | +zarr.consolidate_metadata(ppython) |
192 | 192 |
|
193 | 193 | #Open in Julia
|
194 | 194 | g = zopen(ppython)
|
@@ -225,21 +225,17 @@ a1[:,1,1] = 1:10
|
225 | 225 |
|
226 | 226 | # Test zip file can be read
|
227 | 227 | ppythonzip = ppython*".zip"
|
228 |
| -py""" |
229 |
| -import numcodecs |
230 |
| -import numpy as np |
231 |
| -store = zarr.ZipStore($ppythonzip, mode="w") |
| 228 | +store = zarr.ZipStore(ppythonzip, mode="w") |
232 | 229 | g = zarr.group(store=store)
|
233 | 230 | g.attrs["groupatt"] = "Hi"
|
234 |
| -z1 = g.create_dataset("a1", shape=(2,6,10),chunks=(1,2,3), dtype='i4') |
235 |
| -z1[:,:,:]=$data |
236 |
| -z1.attrs["test"]={"b": 6} |
237 |
| -z2 = g.create_dataset("a2", shape=(5,),chunks=(5,), dtype='S1', compressor=numcodecs.Zlib()) |
238 |
| -z2[:]=[k for k in 'hallo'] |
239 |
| -z3 = g.create_dataset('a3', shape=(2,), dtype=str) |
240 |
| -z3[:]=np.asarray(['test1', 'test234'], dtype='O') |
| 231 | +z1 = g.create_dataset("a1", shape=(2,6,10),chunks=(1,2,3), dtype="i4") |
| 232 | +z1[pybuiltins.Ellipsis] = numpy.array(data) |
| 233 | +z1.attrs["test"] = pydict(Dict("b"=>6)) |
| 234 | +z2 = g.create_dataset("a2", shape=(5,),chunks=(5,), dtype="S1", compressor=numcodecs.Zlib()) |
| 235 | +z2[pybuiltins.Ellipsis] = pylist([k for k in "hallo"]) |
| 236 | +z3 = g.create_dataset("a3", shape=(2,), dtype=pybuiltins.str) |
| 237 | +z3[pybuiltins.Ellipsis] = numpy.asarray(["test1", "test234"], dtype="O") |
241 | 238 | store.close()
|
242 |
| -""" |
243 | 239 |
|
244 | 240 | g = zopen(Zarr.ZipStore(Mmap.mmap(ppythonzip)))
|
245 | 241 | @test g isa Zarr.ZGroup
|
@@ -282,16 +278,15 @@ for pt in [Week, Day, Hour, Minute, Second,
|
282 | 278 | end
|
283 | 279 |
|
284 | 280 | zarr = pyimport("zarr")
|
285 |
| -np = pyimport("numpy") |
286 |
| - |
| 281 | +numpy = pyimport("numpy") |
287 | 282 | g_julia = zopen(p)
|
288 | 283 | g_python = zarr.open(p)
|
289 | 284 |
|
290 | 285 | for unit in ["Week", "Day", "Hour", "Minute", "Second",
|
291 | 286 | "Millisecond"]
|
292 |
| - @test_py np.datetime64(g_julia[unit][1] |> DateTime |> string) == get(getproperty(g_python,unit),0) |
293 |
| - @test_py np.datetime64(g_julia[unit][10] |> DateTime |> string) == get(getproperty(g_python,unit),9) |
294 |
| - @test_py np.datetime64(g_julia[unit][100] |> DateTime |> string) == get(getproperty(g_python,unit),99) |
| 287 | + for i in [0, 9, 99] |
| 288 | + @test pyeq(Bool, numpy.datetime64(g_julia[unit][i+1] |> DateTime |> string), g_python[unit][i]) |
| 289 | + end |
295 | 290 | end
|
296 | 291 |
|
297 | 292 | end
|
0 commit comments