Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

""" Extend XArray with the ``.stems`` XArray accessor [1]_ 

 

 

 

References 

---------- 

.. [1] http://xarray.pydata.org/en/stable/internals.html#extending-xarray 

 

""" 

import logging 

 

import xarray as xr 

 

from .gis import convert, conventions, coords, projections 

 

logger = logging.getLogger(__name__) 

 

 

class _STEMSAccessor(object): 

""" Base class for xarray.DataArray and xarray.Dataset accessors 

""" 

 

def __init__(self, xarray_obj): 

self._obj = xarray_obj 

self._grid_mapping = 'crs' 

 

def georeference(self, crs, transform, grid_mapping='crs'): 

""" Apply georeferencing to XArray data 

 

Parameters 

---------- 

crs : rasterio.crs.CRS 

Rasterio CRS 

transform : affine.Affine 

Affine transform of the data 

grid_mapping : str, optional 

Name to use for grid mapping variable 

 

Returns 

------- 

xarray.Dataset or xarray.DataArray 

Georeferenced data 

""" 

self._grid_mapping = grid_mapping 

obj = conventions.georeference(self._obj, crs, transform, 

grid_mapping=grid_mapping, 

inplace=False) 

return obj 

 

def is_georeferenced(self): 

""" Check if data is georeferenced 

 

Returns 

------- 

bool 

True if XArray data is georeferenced 

""" 

return conventions.is_georeferenced(self._obj) 

 

@property 

def coord_x(self): 

""" np.ndarray: X coordinates 

""" 

x, _ = projections.cf_xy_coord_names(self.crs) 

return self._obj.coords[x] 

 

@property 

def coord_y(self): 

""" np.ndarray: Y coordinates 

""" 

_, y = projections.cf_xy_coord_names(self.crs) 

return self._obj.coords[y] 

 

@property 

def crs(self): 

""" rasterio.crs.CRS: Coordinate reference system 

""" 

# TODO: parse based on CF information, not just GDAL 

var_gm = self.grid_mapping 

return convert.to_crs(var_gm.attrs['spatial_ref']) 

 

@property 

def transform(self): 

""" affine.Affine: Affine transform 

""" 

# TODO: assume unique -> yes if 2D, otherwise no 

x, y = projections.cf_xy_coord_names(self.crs) 

 

if 'x' in self._obj.dims and 'y' in self._obj.dims: 

assume_unique = True 

else: 

logger.debug('Could not find y/x coordinates as dimensions. ' 

'Assuming coordinates are NOT unique') 

assume_unique = False 

 

xform = coords.coords_to_transform(self.coord_y, self.coord_x, 

assume_unique=assume_unique) 

return xform 

 

@property 

def bounds(self): 

""" BoundingBox: Bounding box of data 

""" 

assume_unique = True 

bounds = coords.coords_to_bounds(self.coord_y, self.coord_x, 

assume_unique=assume_unique) 

return bounds 

 

@property 

def bbox(self): 

""" Polygon: Bounding box polygon 

""" 

return convert.to_bbox(self.bounds) 

 

@property 

def grid_mapping(self): 

""" xarray.DataArray: Georeferencing variable 

""" 

try: 

var_grid_mapping = conventions.get_grid_mapping( 

self._obj, grid_mapping=self._grid_mapping 

) 

except KeyError as ke: 

raise KeyError('XArray data object is not georeferenced') 

else: 

return var_grid_mapping 

 

 

@xr.register_dataarray_accessor('stems') 

class DataArrayAccessor(_STEMSAccessor): 

""" XArray.DataArray accessor for STEMS project 

""" 

pass 

 

 

@xr.register_dataset_accessor('stems') 

class DatasetAccessor(_STEMSAccessor): 

""" XArray.Dataset accessor for STEMS project 

""" 

pass