@@ -204,23 +204,19 @@ def imshow(
204
204
args = locals ()
205
205
apply_default_cascade (args )
206
206
labels = labels .copy ()
207
+ img_is_xarray = False
207
208
# ----- Define x and y, set labels if img is an xarray -------------------
208
209
if xarray_imported and isinstance (img , xarray .DataArray ):
209
- if binary_string :
210
- raise ValueError (
211
- "It is not possible to use binary image strings for xarrays."
212
- "Please pass your data as a numpy array instead using"
213
- "`img.values`"
214
- )
210
+ img_is_xarray = True
215
211
y_label , x_label = img .dims [0 ], img .dims [1 ]
216
212
# np.datetime64 is not handled correctly by go.Heatmap
217
213
for ax in [x_label , y_label ]:
218
214
if np .issubdtype (img .coords [ax ].dtype , np .datetime64 ):
219
215
img .coords [ax ] = img .coords [ax ].astype (str )
220
216
if x is None :
221
- x = img .coords [x_label ]
217
+ x = img .coords [x_label ]. values
222
218
if y is None :
223
- y = img .coords [y_label ]
219
+ y = img .coords [y_label ]. values
224
220
if aspect is None :
225
221
aspect = "auto"
226
222
if labels .get ("x" , None ) is None :
@@ -330,6 +326,42 @@ def imshow(
330
326
_vectorize_zvalue (zmin , mode = "min" ),
331
327
_vectorize_zvalue (zmax , mode = "max" ),
332
328
)
329
+ x0 , y0 , dx , dy = (None ,) * 4
330
+ error_msg_xarray = (
331
+ "Non-numerical coordinates were passed with xarray `img`, but "
332
+ "the Image trace cannot handle it. Please use `binary_string=False` "
333
+ "for 2D data or pass instead the numpy array `img.values` to `px.imshow`."
334
+ )
335
+ if x is not None :
336
+ x = np .asanyarray (x )
337
+ if np .issubdtype (x .dtype , np .number ):
338
+ x0 = x [0 ]
339
+ dx = x [1 ] - x [0 ]
340
+ else :
341
+ error_msg = (
342
+ error_msg_xarray
343
+ if img_is_xarray
344
+ else (
345
+ "Only numerical values are accepted for the `x` parameter "
346
+ "when an Image trace is used."
347
+ )
348
+ )
349
+ raise ValueError (error_msg )
350
+ if y is not None :
351
+ y = np .asanyarray (y )
352
+ if np .issubdtype (y .dtype , np .number ):
353
+ y0 = y [0 ]
354
+ dy = y [1 ] - y [0 ]
355
+ else :
356
+ error_msg = (
357
+ error_msg_xarray
358
+ if img_is_xarray
359
+ else (
360
+ "Only numerical values are accepted for the `y` parameter "
361
+ "when an Image trace is used."
362
+ )
363
+ )
364
+ raise ValueError (error_msg )
333
365
if binary_string :
334
366
if zmin is None and zmax is None : # no rescaling, faster
335
367
img_rescaled = img
@@ -355,13 +387,24 @@ def imshow(
355
387
compression = binary_compression_level ,
356
388
ext = binary_format ,
357
389
)
358
- trace = go .Image (source = img_str )
390
+ trace = go .Image (source = img_str , x0 = x0 , y0 = y0 , dx = dx , dy = dy )
359
391
else :
360
392
colormodel = "rgb" if img .shape [- 1 ] == 3 else "rgba256"
361
- trace = go .Image (z = img , zmin = zmin , zmax = zmax , colormodel = colormodel )
393
+ trace = go .Image (
394
+ z = img ,
395
+ zmin = zmin ,
396
+ zmax = zmax ,
397
+ colormodel = colormodel ,
398
+ x0 = x0 ,
399
+ y0 = y0 ,
400
+ dx = dx ,
401
+ dy = dy ,
402
+ )
362
403
layout = {}
363
- if origin == "lower" :
404
+ if origin == "lower" or ( dy is not None and dy < 0 ) :
364
405
layout ["yaxis" ] = dict (autorange = True )
406
+ if dx is not None and dx < 0 :
407
+ layout ["xaxis" ] = dict (autorange = "reversed" )
365
408
else :
366
409
raise ValueError (
367
410
"px.imshow only accepts 2D single-channel, RGB or RGBA images. "
0 commit comments