@@ -494,6 +494,8 @@ def from_transform(
494
494
height : int ,
495
495
x_dim : str = "x" ,
496
496
y_dim : str = "y" ,
497
+ x_coord_name : str = "xc" ,
498
+ y_coord_name : str = "yc" ,
497
499
crs : CRS | Any | None = None ,
498
500
) -> RasterIndex :
499
501
"""Create a RasterIndex from an affine transform and raster dimensions.
@@ -507,10 +509,14 @@ def from_transform(
507
509
Number of pixels in the x direction.
508
510
height : int
509
511
Number of pixels in the y direction.
510
- x_dim : str, default "x"
512
+ x_dim : str, optional
511
513
Name for the x dimension.
512
- y_dim : str, default "y"
514
+ y_dim : str, optional
513
515
Name for the y dimension.
516
+ x_coord_name : str, optional
517
+ Name for the x dimension. For non-rectilinear transforms only.
518
+ y_coord_name : str, optional
519
+ Name for the y dimension. For non-rectilinear transforms only.
514
520
crs : :class:`pyproj.crs.CRS` or any, optional
515
521
The coordinate reference system. Any value accepted by
516
522
:meth:`pyproj.crs.CRS.from_user_input`.
@@ -533,21 +539,35 @@ def from_transform(
533
539
>>> from affine import Affine
534
540
>>> transform = Affine(1.0, 0.0, 0.0, 0.0, -1.0, 100.0)
535
541
>>> index = RasterIndex.from_transform(transform, width=100, height=100)
542
+
543
+ Create a non-rectilinear index:
544
+
545
+ >>> index = RasterIndex.from_transform(
546
+ ... Affine.rotation(45), width=100, height=100, x_coord_name="x1", y_coord_name="x2"
547
+ ... )
536
548
"""
537
549
index : WrappedIndex
538
550
539
551
# pixel centered coordinates
540
552
affine = affine * Affine .translation (0.5 , 0.5 )
541
553
542
554
if affine .is_rectilinear and affine .b == affine .d == 0 :
543
- x_transform = AxisAffineTransform (affine , width , "x" , x_dim , is_xaxis = True )
544
- y_transform = AxisAffineTransform (affine , height , "y" , y_dim , is_xaxis = False )
555
+ x_transform = AxisAffineTransform (affine , width , x_dim , x_dim , is_xaxis = True )
556
+ y_transform = AxisAffineTransform (affine , height , y_dim , y_dim , is_xaxis = False )
545
557
index = (
546
558
AxisAffineTransformIndex (x_transform ),
547
559
AxisAffineTransformIndex (y_transform ),
548
560
)
549
561
else :
550
- xy_transform = AffineTransform (affine , width , height , x_dim = x_dim , y_dim = y_dim )
562
+ xy_transform = AffineTransform (
563
+ affine ,
564
+ width ,
565
+ height ,
566
+ x_dim = x_dim ,
567
+ y_dim = y_dim ,
568
+ x_coord_name = x_coord_name ,
569
+ y_coord_name = y_coord_name ,
570
+ )
551
571
index = CoordinateTransformIndex (xy_transform )
552
572
553
573
return cls (index , crs = crs )
@@ -568,6 +588,18 @@ def create_variables(self, variables: Mapping[Any, Variable] | None = None) -> d
568
588
for index in self ._wrapped_indexes :
569
589
new_variables .update (index .create_variables ())
570
590
591
+ if self .crs is not None :
592
+ xname , yname = self .xy_coord_names
593
+ xattrs , yattrs = self .crs .cs_to_cf ()
594
+ if "axis" in xattrs and "axis" in yattrs :
595
+ # The axis order is defined by the projection
596
+ # So we have to figure which is which.
597
+ # This is an ugly hack that works for common cases.
598
+ if xattrs ["axis" ] == "Y" :
599
+ xattrs , yattrs = yattrs , xattrs
600
+ new_variables [xname ].attrs = xattrs
601
+ new_variables [yname ].attrs = yattrs
602
+
571
603
return new_variables
572
604
573
605
@property
0 commit comments