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