2
2
Simple odc-stats plugin example, with excessive
3
3
documentation. Creates temporal median NDVI
4
4
from DEA Landsat Collection 3
5
-
5
+
6
6
"""
7
7
8
8
import xarray as xr
14
14
enum_to_bool
15
15
)
16
16
17
+
17
18
class StatsNDVI (StatsPluginInterface ):
18
19
"""
19
- Define a class for summarising time
20
+ Define a class for summarising time
20
21
series of NDVI using the median.
21
22
"""
23
+
22
24
NAME = "ndvi_median"
23
25
SHORT_NAME = NAME
24
26
VERSION = "1.0"
@@ -33,21 +35,24 @@ def __init__(
33
35
group_by : str = "solar_day" ,
34
36
** kwargs ,
35
37
):
36
-
38
+
37
39
self .input_bands = input_bands
38
40
self .output_bands = output_bands
39
41
self .mask_band = mask_band
40
42
self .contiguity_band = contiguity_band
41
43
self .group_by = group_by
42
44
45
+ < << << << HEAD
43
46
# These params get passed to the upstream
44
47
# base class StatsPluginInterface
48
+ == == == =
49
+ ## These params get passed to the upstream
50
+ # base StatsPluginInterface class
51
+ >> >> >> > refs / remotes / origin / plugin_documentation
45
52
super ().__init__ (
46
- input_bands = tuple (input_bands )+ (mask_band ,)+ (contiguity_band ,),
47
- ** kwargs
53
+ input_bands = tuple (input_bands ) + (mask_band ,) + (contiguity_band ,), ** kwargs
48
54
)
49
55
50
-
51
56
@property
52
57
def measurements (self ) -> Tuple [str , ...]:
53
58
"""
@@ -56,7 +61,7 @@ def measurements(self) -> Tuple[str, ...]:
56
61
but equally we could define the outputs ames within this function.
57
62
For example, by adding a suffix to the input bands.
58
63
"""
59
-
64
+
60
65
return (self .output_bands ,)
61
66
62
67
def native_transform (self , xx ):
@@ -67,22 +72,27 @@ def native_transform(self, xx):
67
72
step of data and is usually used for things like
68
73
masking clouds, nodata, and contiguity masking.
69
74
"""
70
- #grab the QA band from the Landsat data
75
+ # grab the QA band from the Landsat data
71
76
mask = xx [self .mask_band ]
72
77
73
78
# create boolean arrays from the mask for cloud
74
79
# and cloud shadows, and nodata
75
80
bad = enum_to_bool (mask , ("nodata" ,))
76
81
non_contiguent = xx .get (self .contiguity_band , 1 ) == 0
77
82
bad = bad | non_contiguent
78
-
83
+
79
84
cloud_mask = enum_to_bool (mask , ("cloud" , "shadow" ))
80
- bad = cloud_mask | bad
85
+ bad = cloud_mask | bad
81
86
82
87
# drop masking bands
83
88
xx = xx .drop_vars ([self .mask_band ] + [self .contiguity_band ])
89
+ < << << << HEAD
84
90
85
91
# Mask the bad data (clouds etc)
92
+ == == == =
93
+
94
+ ## Mask the bad data (clouds etc)
95
+ >> >> >> > refs / remotes / origin / plugin_documentation
86
96
xx = erase_bad (xx , bad )
87
97
88
98
return xx
@@ -93,14 +103,24 @@ def reduce(self, xx: xr.Dataset) -> xr.Dataset:
93
103
"""
94
104
# convert to float by and convert nodata to NaN
95
105
xx = mask_invalid_data (xx )
96
-
97
- ndvi = (xx ['nbart_nir' ] - xx ['nbart_red' ]) / (xx ['nbart_nir' ] + xx ['nbart_red' ])
98
106
107
+ < << << << HEAD
99
108
# calculate temporal median NDVI. Note that we use
100
109
# 'spec' and not 'time', this is an odc-stats thing
101
110
ndvi = ndvi .median ('spec' ).rename (self .output_bands )
102
111
112
+ == == == =
113
+ ndvi = (xx ["nbart_nir" ] - xx ["nbart_red" ]) / (xx ["nbart_nir" ] + xx ["nbart_red" ])
114
+
115
+ # calculate temporal median NDVI.
116
+ # !!!!!!!!!!!!!!!!!!!!!!!!!!!!
117
+ # Note that we use 'spec' and not 'time', this is an odc-stats thing
118
+ # !!!!!!!!!!!!!!!!!!!!!!!!!!!!
119
+ ndvi = ndvi .median ("spec" ).rename (self .output_bands )
120
+
121
+ >> >> >> > refs / remotes / origin / plugin_documentation
103
122
return ndvi .to_dataset ()
104
123
124
+
105
125
# now lets 'register' the function with odc-stats
106
126
register ("ndvi-median" , StatsNDVI )
0 commit comments