@@ -297,6 +297,37 @@ def create_output_xarray(probabilities: np.ndarray, input_xr: xr.DataArray) -> x
297297 )
298298
299299
300+ def fill_missing_bands (cube : xr .DataArray , required_bands : List [str ], fill_value : float = np .nan ) -> xr .DataArray :
301+ """
302+ Ensure `cube` contains all `required_bands` along the 'bands' dimension.
303+ Missing bands are appended, filled with a constant `fill_value`.
304+ :param cube: Input xarray DataArray with a 'bands' dimension (plus spatial/time dims).
305+ :param required_bands: The list of band names needed.
306+ :param fill_value: Scalar value to use for missing bands (default: NaN).
307+ :return: DataArray containing all bands; newly added bands are filled with `fill_value`.
308+ """
309+ existing = set (cube .coords ["bands" ].values )
310+ missing = [b for b in required_bands if b not in existing ]
311+ if not missing :
312+ inspect (message = f"No missing bands" )
313+ return cube
314+
315+ inspect (message = f"Missing bands: { missing } . Filling with { fill_value } ." )
316+ # Get shape and coordinates excluding 'bands'
317+ sample = cube .isel (bands = 0 )
318+ data_shape = sample .shape
319+ dims = sample .dims
320+ coords = {dim : cube .coords [dim ] for dim in dims }
321+ # Create fill array
322+ fill_data = np .full ((len (missing ), * data_shape ), fill_value , dtype = cube .dtype )
323+ fill_array = xr .DataArray (
324+ data = fill_data ,
325+ coords = {"bands" : missing , ** coords },
326+ dims = ("bands" ,) + dims ,
327+ )
328+ return xr .concat ([cube , fill_array ], dim = "bands" )
329+
330+
300331def apply_datacube (cube : xr .DataArray , context : Dict ) -> xr .DataArray :
301332 """
302333 Applies multiple ONNX models on a given data cube for inference. The function ensures that the input
@@ -329,11 +360,14 @@ def apply_datacube(cube: xr.DataArray, context: Dict) -> xr.DataArray:
329360
330361 # load the ONNX model and extract metadata
331362 ort_session , metadata = load_onnx_model (url , cache_dir = "/tmp/cache" )
332- input_band = metadata ["input_features" ]
363+ input_bands = metadata ["input_features" ]
364+
365+ # Fill missing bands before subsetting
366+ cube = fill_missing_bands (cube , required_bands = input_bands , fill_value = 0 )
333367
334368 # Subset the data array using the selected indices
335369 inspect (message = f"Subsetting the feature datacube by needed input features." )
336- subsampled_data_array = cube .sel (bands = input_band )
370+ subsampled_data_array = cube .sel (bands = input_bands )
337371
338372 # preprocess input array to numpy array in correct shape
339373 input_np , input_shape = preprocess_input (subsampled_data_array , ort_session )
@@ -354,6 +388,7 @@ def apply_datacube(cube: xr.DataArray, context: Dict) -> xr.DataArray:
354388 else :
355389 # Append to output_cube starting from the second iteration
356390 output_cube = xr .concat ([output_cube , model_output_cube ], dim = "bands" )
391+
357392 # make sure output Xarray has the correct dtype
358393 output_cube = output_cube .astype ("uint8" )
359394
0 commit comments