ECOv003-L2T-STARS 1.0.0__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. ECOv003_L2T_STARS/BRDF/BRDF.py +57 -0
  2. ECOv003_L2T_STARS/BRDF/SZA.py +65 -0
  3. ECOv003_L2T_STARS/BRDF/__init__.py +1 -0
  4. ECOv003_L2T_STARS/BRDF/statistical_radiative_transport.txt +90 -0
  5. ECOv003_L2T_STARS/BRDF/version.txt +1 -0
  6. ECOv003_L2T_STARS/ECOv003_DL.py +527 -0
  7. ECOv003_L2T_STARS/ECOv003_DL.xml +47 -0
  8. ECOv003_L2T_STARS/ECOv003_L2T_STARS.py +162 -0
  9. ECOv003_L2T_STARS/ECOv003_L2T_STARS.xml +47 -0
  10. ECOv003_L2T_STARS/L2TSTARSConfig.py +188 -0
  11. ECOv003_L2T_STARS/L2T_STARS.py +489 -0
  12. ECOv003_L2T_STARS/LPDAAC/LPDAACDataPool.py +444 -0
  13. ECOv003_L2T_STARS/LPDAAC/__init__.py +9 -0
  14. ECOv003_L2T_STARS/LPDAAC/version.txt +1 -0
  15. ECOv003_L2T_STARS/Manifest.toml +2332 -0
  16. ECOv003_L2T_STARS/Project.toml +14 -0
  17. ECOv003_L2T_STARS/VIIRS/VIIRSDataPool.py +294 -0
  18. ECOv003_L2T_STARS/VIIRS/VIIRSDownloader.py +26 -0
  19. ECOv003_L2T_STARS/VIIRS/VIIRS_CMR_LOGIN.py +36 -0
  20. ECOv003_L2T_STARS/VIIRS/VNP09GA.py +1277 -0
  21. ECOv003_L2T_STARS/VIIRS/VNP43IA4.py +288 -0
  22. ECOv003_L2T_STARS/VIIRS/VNP43MA3.py +323 -0
  23. ECOv003_L2T_STARS/VIIRS/__init__.py +9 -0
  24. ECOv003_L2T_STARS/VIIRS/version.txt +1 -0
  25. ECOv003_L2T_STARS/VNP43NRT/VNP43NRT.py +863 -0
  26. ECOv003_L2T_STARS/VNP43NRT/__init__.py +1 -0
  27. ECOv003_L2T_STARS/VNP43NRT/process_VNP43NRT.jl +169 -0
  28. ECOv003_L2T_STARS/VNP43NRT/version.txt +1 -0
  29. ECOv003_L2T_STARS/VNP43NRT_jl/Manifest.toml +995 -0
  30. ECOv003_L2T_STARS/VNP43NRT_jl/Project.toml +15 -0
  31. ECOv003_L2T_STARS/VNP43NRT_jl/__init__.py +0 -0
  32. ECOv003_L2T_STARS/VNP43NRT_jl/instantiate.jl +25 -0
  33. ECOv003_L2T_STARS/VNP43NRT_jl/instantiate.py +13 -0
  34. ECOv003_L2T_STARS/VNP43NRT_jl/src/VNP43NRT.jl +411 -0
  35. ECOv003_L2T_STARS/VNP43NRT_jl/src/__init__.py +0 -0
  36. ECOv003_L2T_STARS/__init__.py +3 -0
  37. ECOv003_L2T_STARS/calibrate_fine_to_coarse.py +60 -0
  38. ECOv003_L2T_STARS/constants.py +38 -0
  39. ECOv003_L2T_STARS/daterange/__init__.py +1 -0
  40. ECOv003_L2T_STARS/daterange/daterange.py +35 -0
  41. ECOv003_L2T_STARS/generate_L2T_STARS_runconfig.py +249 -0
  42. ECOv003_L2T_STARS/generate_NDVI_coarse_directory.py +21 -0
  43. ECOv003_L2T_STARS/generate_NDVI_coarse_image.py +30 -0
  44. ECOv003_L2T_STARS/generate_NDVI_fine_directory.py +14 -0
  45. ECOv003_L2T_STARS/generate_NDVI_fine_image.py +28 -0
  46. ECOv003_L2T_STARS/generate_STARS_inputs.py +231 -0
  47. ECOv003_L2T_STARS/generate_albedo_coarse_directory.py +18 -0
  48. ECOv003_L2T_STARS/generate_albedo_coarse_image.py +30 -0
  49. ECOv003_L2T_STARS/generate_albedo_fine_directory.py +17 -0
  50. ECOv003_L2T_STARS/generate_albedo_fine_image.py +30 -0
  51. ECOv003_L2T_STARS/generate_filename.py +37 -0
  52. ECOv003_L2T_STARS/generate_input_staging_directory.py +23 -0
  53. ECOv003_L2T_STARS/generate_model_state_tile_date_directory.py +28 -0
  54. ECOv003_L2T_STARS/generate_output_directory.py +28 -0
  55. ECOv003_L2T_STARS/install_STARS_jl.py +43 -0
  56. ECOv003_L2T_STARS/instantiate_STARS_jl.py +38 -0
  57. ECOv003_L2T_STARS/load_prior.py +248 -0
  58. ECOv003_L2T_STARS/prior.py +56 -0
  59. ECOv003_L2T_STARS/process_ECOSTRESS_data_fusion_distributed_bias.jl +420 -0
  60. ECOv003_L2T_STARS/process_STARS_product.py +507 -0
  61. ECOv003_L2T_STARS/process_julia_data_fusion.py +110 -0
  62. ECOv003_L2T_STARS/retrieve_STARS_sources.py +101 -0
  63. ECOv003_L2T_STARS/runconfig.py +70 -0
  64. ECOv003_L2T_STARS/timer/__init__.py +1 -0
  65. ECOv003_L2T_STARS/timer/timer.py +77 -0
  66. ECOv003_L2T_STARS/version.py +8 -0
  67. ECOv003_L2T_STARS/version.txt +1 -0
  68. {ECOv003_L2T_STARS-1.0.0.dist-info → ecov003_l2t_stars-1.1.0.dist-info}/METADATA +30 -23
  69. ecov003_l2t_stars-1.1.0.dist-info/RECORD +73 -0
  70. {ECOv003_L2T_STARS-1.0.0.dist-info → ecov003_l2t_stars-1.1.0.dist-info}/WHEEL +1 -1
  71. ecov003_l2t_stars-1.1.0.dist-info/entry_points.txt +3 -0
  72. ecov003_l2t_stars-1.1.0.dist-info/top_level.txt +1 -0
  73. ECOv003_L2T_STARS-1.0.0.dist-info/RECORD +0 -5
  74. ECOv003_L2T_STARS-1.0.0.dist-info/top_level.txt +0 -1
  75. {ECOv003_L2T_STARS-1.0.0.dist-info → ecov003_l2t_stars-1.1.0.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,420 @@
1
+ using Glob
2
+ using Dates
3
+ using Rasters
4
+ using LinearAlgebra
5
+ using STARSDataFusion
6
+ using STARSDataFusion.BBoxes
7
+ using STARSDataFusion.sentinel_tiles
8
+ using STARSDataFusion.HLS
9
+ using STARSDataFusion.VNP43
10
+ using Logging
11
+ using Pkg
12
+ using Statistics
13
+ using Distributed
14
+ Pkg.add("OpenSSL")
15
+ using HTTP
16
+ using JSON
17
+
18
+ function read_json(file::String)::Dict
19
+ open(file, "r") do f
20
+ return JSON.parse(f)
21
+ end
22
+ end
23
+
24
+ function write_json(file::String, data::Dict)
25
+ open(file, "w") do f
26
+ JSON.print(f, data)
27
+ end
28
+ end
29
+
30
+ @info "processing STARS data fusion"
31
+
32
+ wrkrs = parse(Int64, ARGS[1])
33
+ # wrkrs = 8
34
+
35
+ @info "starting $(wrkrs) workers"
36
+ addprocs(wrkrs) ## need to set num workers
37
+
38
+ @everywhere using STARSDataFusion
39
+ @everywhere using LinearAlgebra
40
+ @everywhere BLAS.set_num_threads(1)
41
+
42
+ DEFAULT_MEAN = 0.12
43
+ DEFAULT_SD = 0.01
44
+
45
+ #### add bias components
46
+ DEFAULT_BIAS_MEAN = 0.0
47
+ DEFAULT_BIAS_SD = 0.001
48
+
49
+ struct CustomLogger <: AbstractLogger
50
+ stream::IO
51
+ min_level::LogLevel
52
+ end
53
+
54
+ Logging.min_enabled_level(logger::CustomLogger) = logger.min_level
55
+
56
+ function Logging.shouldlog(logger::CustomLogger, level, _module, group, id)
57
+ return level >= logger.min_level
58
+ end
59
+
60
+ function Logging.handle_message(logger::CustomLogger, level, message, _module, group, id, file, line; kwargs...)
61
+ t = Dates.format(now(), "yyyy-mm-dd HH:MM:SS")
62
+ println(logger.stream, "[$t $(uppercase(string(level)))] $message")
63
+ end
64
+
65
+ global_logger(CustomLogger(stdout, Logging.Info))
66
+
67
+ tile = ARGS[2]
68
+ @info "tile: $(tile)"
69
+ coarse_cell_size = parse(Int64, ARGS[3])
70
+ @info "coarse cell size: $(coarse_cell_size)"
71
+ fine_cell_size = parse(Int64, ARGS[4])
72
+ @info "fine cell size: $(fine_cell_size)"
73
+ VIIRS_start_date = Date(ARGS[5])
74
+ @info "VIIRS start date: $(VIIRS_start_date)"
75
+ VIIRS_end_date = Date(ARGS[6])
76
+ @info "VIIRS end date: $(VIIRS_end_date)"
77
+ HLS_start_date = Date(ARGS[7])
78
+ @info "HLS start date: $(HLS_start_date)"
79
+ HLS_end_date = Date(ARGS[8])
80
+ @info "HLS end date: $(HLS_end_date)"
81
+ coarse_directory = ARGS[9]
82
+ @info "coarse inputs directory: $(coarse_directory)"
83
+ fine_directory = ARGS[10]
84
+ @info "fine inputs directory: $(fine_directory)"
85
+ posterior_filename = ARGS[11]
86
+ @info "posterior filename: $(posterior_filename)"
87
+ posterior_UQ_filename = ARGS[12]
88
+ @info "posterior UQ filename: $(posterior_UQ_filename)"
89
+ posterior_flag_filename = ARGS[13]
90
+ @info "posterior flag filename: $(posterior_flag_filename)"
91
+ posterior_bias_filename = ARGS[14]
92
+ @info "posterior bias filename: $(posterior_bias_filename)"
93
+ posterior_bias_UQ_filename = ARGS[15]
94
+ @info "posterior bias UQ filename: $(posterior_bias_UQ_filename)"
95
+
96
+ if size(ARGS)[1] >= 19
97
+ prior_filename = ARGS[16]
98
+ @info "prior filename: $(prior_filename)"
99
+ prior_mean = Array(Raster(prior_filename))
100
+ prior_UQ_filename = ARGS[17]
101
+ @info "prior UQ filename: $(prior_UQ_filename)"
102
+ prior_sd = Array(Raster(prior_UQ_filename))
103
+ prior_bias_filename = ARGS[18]
104
+ @info "prior bias filename: $(prior_bias_filename)"
105
+ prior_bias_mean = Array(Raster(prior_bias_filename))
106
+ prior_bias_UQ_filename = ARGS[19]
107
+ @info "prior bias UQ filename: $(prior_bias_UQ_filename)"
108
+ prior_bias_sd = Array(Raster(prior_bias_UQ_filename))
109
+
110
+ replace!(prior_bias_mean, missing => NaN)
111
+ replace!(prior_bias_sd, missing => NaN)
112
+ replace!(prior_mean, missing => NaN)
113
+ replace!(prior_sd, missing => NaN)
114
+ ## if we do flag as HLS observed within last 7 days then we don't depend on prior flags
115
+ # prior_flag_filename = ARGS[20]
116
+ # @info "prior flag filename: $(prior_flag_filename)"
117
+ # prior_flag = Raster(prior_flag_filename)
118
+ else
119
+ prior_mean = nothing
120
+ end
121
+
122
+ x_coarse, y_coarse = sentinel_tile_dims(tile, coarse_cell_size)
123
+ x_coarse_size = size(x_coarse)[1]
124
+ y_coarse_size = size(y_coarse)[1]
125
+ @info "coarse x size: $(x_coarse_size)"
126
+ @info "coarse y size: $(y_coarse_size)"
127
+ x_fine, y_fine = sentinel_tile_dims(tile, fine_cell_size)
128
+ x_fine_size = size(x_fine)[1]
129
+ y_fine_size = size(y_fine)[1]
130
+ @info "fine x size: $(x_fine_size)"
131
+ @info "fine y size: $(y_fine_size)"
132
+
133
+ coarse_image_filenames = sort(glob("*.tif", coarse_directory))
134
+ coarse_dates_found = [Date(split(basename(filename), "_")[3]) for filename in coarse_image_filenames]
135
+
136
+ fine_image_filenames = sort(glob("*.tif", fine_directory))
137
+ fine_dates_found = [Date(split(basename(filename), "_")[3]) for filename in fine_image_filenames]
138
+
139
+ coarse_start_date = VIIRS_start_date
140
+ coarse_end_date = VIIRS_end_date
141
+
142
+ fine_flag_start_date = HLS_end_date - Day(7)
143
+ fine_start_date = HLS_start_date
144
+ fine_end_date = HLS_end_date
145
+
146
+ dates = [fine_start_date + Day(d - 1) for d in 1:((fine_end_date - fine_start_date).value + 1)]
147
+ t = Ti(dates)
148
+ coarse_dims = (x_coarse, y_coarse, t)
149
+ fine_dims = (x_fine, y_fine, t)
150
+
151
+ covariance_dates = [coarse_start_date + Day(d - 1) for d in 1:((coarse_end_date - coarse_start_date).value + 1)]
152
+ t_covariance = Ti(covariance_dates)
153
+ covariance_dims = (x_coarse, y_coarse, t_covariance)
154
+
155
+ covariance_images = []
156
+
157
+ for (i, date) in enumerate(covariance_dates)
158
+ date = Dates.format(date, dateformat"yyyy-mm-dd")
159
+ match = findfirst(x -> occursin(date, x), coarse_image_filenames)
160
+ timestep_index = Band(i:i)
161
+ timestep_dims = (x_coarse, y_coarse, timestep_index)
162
+
163
+ if match === nothing
164
+ @info "coarse image is not available on $(date)"
165
+ covariance_image = Raster(fill(NaN, x_coarse_size, y_coarse_size, 1), dims=timestep_dims, missingval=NaN)
166
+ @info size(covariance_image)
167
+ else
168
+ filename = coarse_image_filenames[match]
169
+ @info "ingesting coarse image on $(date): $(filename)"
170
+ covariance_image = Raster(reshape(Raster(filename), x_coarse_size, y_coarse_size, 1), dims=timestep_dims, missingval=NaN)
171
+ replace!(covariance_image, missing => NaN)
172
+ @info size(covariance_image)
173
+ end
174
+
175
+ push!(covariance_images, covariance_image)
176
+ end
177
+
178
+ @info "concatenating coarse images for covariance calculation"
179
+ covariance_images = Raster(cat(covariance_images..., dims=3), dims=covariance_dims, missingval=NaN)
180
+
181
+ # estimate spatial var parameter
182
+ n_eff = compute_n_eff(Int(round(coarse_cell_size / fine_cell_size)), 2, smoothness=1.5) ## Matern: range = 200m, smoothness = 1.5
183
+ sp_var = fast_var_est(covariance_images, n_eff_agg = n_eff)
184
+
185
+ coarse_images = []
186
+ coarse_dates = Vector{Date}(undef,0)
187
+
188
+ tk=1
189
+ for (i, date) in enumerate(dates)
190
+ date = Dates.format(date, dateformat"yyyy-mm-dd")
191
+ matched = findfirst(x -> occursin(date, x), coarse_image_filenames)
192
+
193
+ if matched === nothing
194
+ @info "coarse image is not available on $(date)"
195
+ # coarse_image = Raster(fill(NaN, x_coarse_size, y_coarse_size, 1), dims=timestep_dims, missingval=NaN)
196
+ # @info size(coarse_image)
197
+ else
198
+ timestep_index = Band(tk:tk)
199
+ timestep_dims = (x_coarse, y_coarse, timestep_index)
200
+ filename = coarse_image_filenames[matched]
201
+ @info "ingesting coarse image on $(date): $(filename)"
202
+ coarse_image = Raster(reshape(Raster(filename), x_coarse_size, y_coarse_size, 1), dims=timestep_dims, missingval=NaN)
203
+ replace!(coarse_image, missing => NaN)
204
+ @info size(coarse_image)
205
+ push!(coarse_dates, dates[i])
206
+ push!(coarse_images, coarse_image)
207
+ global tk += 1
208
+ end
209
+ end
210
+ @info "concatenating coarse image inputs"
211
+ if length(coarse_images) == 0
212
+ coarse_images = Raster(fill(NaN, x_coarse_size, y_coarse_size, 1), dims=(coarse_dims[1:2]..., Band(1:1)), missingval=NaN)
213
+ coarse_array = zeros(x_coarse_size, y_coarse_size, 1)
214
+ coarse_array .= NaN
215
+ coarse_dates = [dates[1]]
216
+ else
217
+ coarse_images = Raster(cat(coarse_images..., dims=3), dims=(coarse_dims[1:2]..., Band(1:length(coarse_dates))), missingval=NaN)
218
+ coarse_array = Array{Float64}(coarse_images)
219
+ end
220
+
221
+ fine_images = []
222
+ fine_dates = Vector{Date}(undef,0)
223
+
224
+ tk=1
225
+ for (i, date) in enumerate(dates)
226
+ date = Dates.format(date, dateformat"yyyy-mm-dd")
227
+ match = findfirst(x -> occursin(date, x), fine_image_filenames)
228
+
229
+ if match === nothing
230
+ @info "fine image is not available on $(date)"
231
+ # fine_image = Raster(fill(NaN, x_fine_size, y_fine_size, 1), dims=timestep_dims, missingval=NaN)
232
+ # @info size(fine_image)
233
+ else
234
+ timestep_index = Band(tk:tk)
235
+ timestep_dims = (x_fine, y_fine, timestep_index)
236
+ filename = fine_image_filenames[match]
237
+ @info "ingesting fine image on $(date): $(filename)"
238
+ fine_image = Raster(reshape(Raster(filename), x_fine_size, y_fine_size, 1), dims=timestep_dims, missingval=NaN)
239
+ replace!(fine_image, missing => NaN)
240
+ @info size(fine_image)
241
+ push!(fine_images, fine_image)
242
+ push!(fine_dates, dates[i])
243
+ global tk += 1
244
+ end
245
+ end
246
+
247
+ @info "concatenating fine image inputs"
248
+ if length(fine_images) == 0
249
+ fine_images = Raster(fill(NaN, x_fine_size, y_fine_size, 1), dims=(fine_dims[1:2]..., Band(1:1)), missingval=NaN)
250
+ fine_array = zeros(x_fine_size, y_fine_size, 1)
251
+ fine_array .= NaN
252
+ fine_dates = [dates[1]]
253
+ else
254
+ fine_images = Raster(cat(fine_images..., dims=3), dims=(fine_dims[1:2]..., Band(1:length(fine_dates))), missingval=NaN)
255
+ fine_array = Array{Float64}(fine_images)
256
+ end
257
+
258
+ target_date = dates[end]
259
+ target_time = length(dates)
260
+
261
+ ## 0, 1 mask
262
+ fine_pixels = sum(.!isnan.(fine_images),dims=3)
263
+ if sum(fine_pixels.==0) > 0
264
+ if fine_flag_start_date < fine_start_date
265
+ flag_dates = [fine_flag_start_date + Day(d - 1) for d in 1:((fine_start_date - Day(1) - fine_flag_start_date).value + 1)]
266
+ tf = Ti(flag_dates)
267
+ fine_flag_dims = (x_fine, y_fine, tf)
268
+
269
+ for (i, date) in enumerate(flag_dates)
270
+ date = Dates.format(date, dateformat"yyyy-mm-dd")
271
+ match = findfirst(x -> occursin(date, x), fine_image_filenames)
272
+
273
+ if match === nothing
274
+ @info "fine image for 7-day flag is not available on $(date)"
275
+ else
276
+ timestep_dims = (x_fine, y_fine, Band(1:1))
277
+ filename = fine_image_filenames[match]
278
+ @info "ingesting fine image for 7-day flag on $(date): $(filename)"
279
+ fine_image = Raster(reshape(Raster(filename), x_fine_size, y_fine_size, 1), dims=timestep_dims, missingval=NaN)
280
+ replace!(fine_image, missing => NaN)
281
+
282
+ fine_pixels .+= sum(.!isnan.(fine_image),dims=3)
283
+ end
284
+ end
285
+ end
286
+ end
287
+
288
+ hls_flag = Array(fine_pixels[:,:,1] .== 0)
289
+
290
+ ### nan pixels with no historical data
291
+ if isnothing(prior_mean)
292
+ prior_flag = trues(size(fine_images)[1:2])
293
+ fine_obs = sum(.!isnan.(fine_images),dims=3)
294
+ ## uncomment to keep viirs-only pixels
295
+ if sum(fine_obs.==0) > 0
296
+ coarse_nans = resample(sum(.!isnan.(coarse_images),dims=3), to=fine_images[:,:,1], method=:near)
297
+ prior_flag[coarse_nans[:,:,1] .> 0] .= false
298
+ end
299
+
300
+ prior_flag[fine_pixels[:,:,1] .> 0] .= false
301
+ elseif sum(isnan.(prior_mean)) .> 0
302
+ prior_flag = isnan.(prior_mean[:,:,1]) .> 0
303
+ fine_obs = sum(.!isnan.(fine_images),dims=3)
304
+ ## uncomment to keep viirs-only pixels
305
+ if sum(fine_obs.==0) > 0
306
+ coarse_nans = resample(sum(.!isnan.(coarse_images),dims=3), to=fine_images[:,:,1], method=:near)
307
+ prior_flag[coarse_nans[:,:,1] .> 0] .= false
308
+ end
309
+ prior_flag[fine_pixels[:,:,1] .> 0] .= false
310
+ else
311
+ prior_flag = falses(size(fine_images)[1:2])
312
+ end
313
+
314
+ @info "running data fusion"
315
+
316
+ #### new approach
317
+ fine_times = findall(dates .∈ Ref(fine_dates))
318
+ coarse_times = findall(dates .∈ Ref(coarse_dates))
319
+
320
+ fine_ndims = collect(size(fine_images)[1:2])
321
+ coarse_ndims = collect(size(coarse_images)[1:2])
322
+
323
+ ## instrument origins and cell sizes
324
+ fine_origin = get_centroid_origin_raster(fine_images)
325
+ coarse_origin = get_centroid_origin_raster(coarse_images)
326
+
327
+ fine_csize = collect(cell_size(fine_images))
328
+ coarse_csize = collect(cell_size(coarse_images))
329
+
330
+ fine_geodata = STARSInstrumentGeoData(fine_origin, fine_csize, fine_ndims, 0, fine_times)
331
+ coarse_geodata = STARSInstrumentGeoData(coarse_origin, coarse_csize, coarse_ndims, 2, coarse_times)
332
+
333
+ fine_data = STARSInstrumentData(fine_array, 0.0, 1e-6, false, nothing, abs.(fine_csize), fine_times, [1. 1.])
334
+ coarse_data = STARSInstrumentData(coarse_array, 0.0, 1e-6, true, [1.0,1e-6], abs.(coarse_csize), coarse_times, [1. 1.])
335
+
336
+ nsamp=100
337
+ window_buffer = 4 ## set these differently for NDVI and albedo?
338
+
339
+ cov_pars = ones((size(fine_images)[1], size(fine_images)[2], 4))
340
+
341
+ sp_rs = resample(log.(sqrt.(sp_var[:,:,1])); to=fine_images[:,:,1], size=size(fine_images)[1:2], method=:cubicspline)
342
+ sp_rs[isnan.(sp_rs)] .= nanmean(sp_rs) ### the resampling won't go outside extent
343
+
344
+ cov_pars[:,:,1] = Array{Float64}(exp.(sp_rs))
345
+ cov_pars[:,:,2] .= coarse_cell_size
346
+ # cov_pars[:,:,2] .= 200.0
347
+ cov_pars[:,:,3] .= 1e-10
348
+ cov_pars[:,:,4] .= 0.5
349
+
350
+ if isnothing(prior_mean)
351
+ fused_images, fused_sd_images, fused_bias_images, fused_bias_sd_images = coarse_fine_scene_fusion_cbias_pmap(fine_data,
352
+ coarse_data,
353
+ fine_geodata,
354
+ coarse_geodata,
355
+ DEFAULT_MEAN .* ones(fine_ndims...),
356
+ DEFAULT_SD^2 .* ones(fine_ndims...),
357
+ DEFAULT_BIAS_MEAN .* ones(coarse_ndims...),
358
+ DEFAULT_BIAS_SD^2 .* ones(coarse_ndims...),
359
+ cov_pars;
360
+ nsamp = nsamp,
361
+ window_buffer = window_buffer,
362
+ target_times = [target_time],
363
+ spatial_mod = exp_cor,
364
+ obs_operator = unif_weighted_obs_operator_centroid,
365
+ state_in_cov = false,
366
+ cov_wt = 0.2,
367
+ nb_coarse = 2.0);
368
+ else
369
+ ## fill in prior mean with mean prior
370
+ nkp = isnan.(prior_mean)
371
+ if sum(nkp) > 0
372
+ mp = nanmean(prior_mean)
373
+ prior_mean[nkp] .= mp
374
+ end
375
+
376
+ fused_images, fused_sd_images, fused_bias_images, fused_bias_sd_images = coarse_fine_scene_fusion_cbias_pmap(fine_data,
377
+ coarse_data,
378
+ fine_geodata,
379
+ coarse_geodata,
380
+ prior_mean,
381
+ prior_sd.^2,
382
+ prior_bias_mean,
383
+ prior_bias_sd.^2,
384
+ cov_pars;
385
+ nsamp = nsamp,
386
+ window_buffer = window_buffer,
387
+ target_times = [target_time],
388
+ spatial_mod = exp_cor,
389
+ obs_operator = unif_weighted_obs_operator_centroid,
390
+ state_in_cov = false,
391
+ cov_wt = 0.2,
392
+ nb_coarse = 2.0);
393
+ end;
394
+
395
+ ## remove workers
396
+ rmprocs(workers())
397
+
398
+ if occursin("NDVI", posterior_filename)
399
+ clamp!(fused_images, -1, 1) # NDVI clipped to [-1,1] range
400
+ else
401
+ clamp!(fused_images, 0, 1) # albedo clipped to [0,1]
402
+ end
403
+
404
+ dd = fused_images[:,:,:]
405
+ dd[prior_flag,:] .= NaN # set no data to NaN
406
+
407
+ fused_raster = Raster(dd, dims=(x_fine, y_fine, Band(1:1)), missingval=NaN)
408
+ flag_raster = Raster(Int.(hls_flag), dims=(x_fine, y_fine), missingval=NaN)
409
+
410
+ @info "writing fused mean: $(posterior_filename)"
411
+ write(posterior_filename, fused_raster, force=true)
412
+ @info "writing fused flag: $(posterior_flag_filename)"
413
+ write(posterior_flag_filename, flag_raster, force=true)
414
+ @info "writing fused SD: $(posterior_UQ_filename)"
415
+ write(posterior_UQ_filename, Raster(fused_sd_images, dims=(x_fine, y_fine, Band(1:1)), missingval=NaN), force=true)
416
+ @info "writing bias mean: $(posterior_bias_filename)"
417
+ write(posterior_bias_filename, Raster(fused_bias_images, dims=(x_coarse, y_coarse, Band(1:1)), missingval=NaN), force=true)
418
+ @info "writing bias SD: $(posterior_bias_UQ_filename)"
419
+ write(posterior_bias_UQ_filename, Raster(fused_bias_sd_images, dims=(x_coarse, y_coarse, Band(1:1)), missingval=NaN), force=true)
420
+