# Output control: nodata, validity mask, windowing GridR gives you several knobs to control exactly what ends up in your output buffer: how invalid samples are reported, where in the output buffer the result is written, and which region of the output is computed in the first place. This page covers them all in one place. **What you'll learn** - Controlling invalid samples with ``nodata_out`` - Producing a validity mask with ``array_out_mask`` - Selecting a region of interest with ``win`` - Pre-allocating ``array_out`` for tiled processing - Writing into a sub-region of a larger buffer with ``array_out_win`` ## Setting the NoData output value and output mask Let's replay the previous translation transform by setting `nodata_out` to its default value, ie 0. As you will see, the right strip border is filled with zeros. We also take this opportunity to introduce the use of the `array_mask_out` parameter and examine the second array returned by the function. We will verify that the mask correctly matches the `nodata` region of the resampled image. Here we set the `array_out_mask` parameter to `True` ; that's a convenient way to let the `array_grid_resampling` method allocate the right sized `unsigned byte` (ie. uint8) array and return it. Please note that we can also directly pass a preallocated array similarly to the `array_out` parameter. ```python array_out_translation_left, array_out_translation_left_mask = array_grid_resampling( interp="cubic", array_in=array_in, grid_row=yy, grid_col=xx_translated, grid_resolution=(1,1), array_out=None, win=None, array_in_mask=None, grid_mask=None, array_out_mask=True, nodata_out=0., standalone=True, boundary_condition=None, trust_padding=False, ) array_out_translation_left[:, -53:] ``` array([[124.875 , 0. , 0. , ..., 0. , 0. , 0. ], [130. , 0. , 0. , ..., 0. , 0. , 0. ], [102.8125, 0. , 0. , ..., 0. , 0. , 0. ], ..., [102.5625, 0. , 0. , ..., 0. , 0. , 0. ], [ 86.5625, 0. , 0. , ..., 0. , 0. , 0. ], [ 3.5625, 0. , 0. , ..., 0. , 0. , 0. ]], shape=(512, 53)) Let's display the output validity mask ```python array_out_translation_left_mask[:, -53:] ``` array([[1, 0, 0, ..., 0, 0, 0], [1, 0, 0, ..., 0, 0, 0], [1, 0, 0, ..., 0, 0, 0], ..., [1, 0, 0, ..., 0, 0, 0], [1, 0, 0, ..., 0, 0, 0], [1, 0, 0, ..., 0, 0, 0]], shape=(512, 53), dtype=uint8) ![003_mask-out.png](grid_resampling_003_output_control_files/003_mask-out.png) ## Apply a window The `array_grid_resampling` method provides the `win` parameter in order to set a window to limit the region to compute. The indices used in the `win` definition refers to indices considering the full resolution output. Below, we first define a window centered on the mandrill's left eye. Since we are considering an identity grid, the grid coordinates align with the input array's image coordinates ```python win_center = np.array((58, 175)) # left eye win_shape = np.array((100, 100)) win = np.array((win_center - win_shape//2, win_center - win_shape//2 + win_shape - 1)).T ``` ![003_full_output.png](grid_resampling_003_output_control_files/003_full_output.png) ```python array_out_id_win_1_1, _ = array_grid_resampling( interp="cubic", array_in=array_in, grid_row=yy, grid_col=xx, grid_resolution=(1,1), array_out=None, win=win, array_in_mask=None, grid_mask=None, array_out_mask=None, nodata_out=None, standalone=True, boundary_condition=None, trust_padding=False, ) ``` ![003_windowed_output.png](grid_resampling_003_output_control_files/003_windowed_output.png) ## Pre-allocating the output buffer Let's now replay the rotation transform. This time we will pre-allocate the output buffer. ```python # We have to init the out buffer with the right shape array_out = np.zeros(xrot.shape, dtype=data_out_dtype, order="C") # Lets call the grid resampling _, mask_out = array_grid_resampling( interp="cubic", array_in=array_in, grid_row=yrot, grid_col=xrot, grid_resolution=(1,1), array_out=array_out, win=None, array_in_mask=None, grid_mask=None, array_out_mask=True, nodata_out=None, standalone=True, boundary_condition=None, trust_padding=False, ) ``` ```python plot_im({'array_out':array_out, 'mask_out': mask_out}, None, prefix='003_prealloc_buffer') ``` ![003_prealloc_buffer.png](grid_resampling_003_output_control_files/003_prealloc_buffer.png) ## Specifying an output target window In the previous step we opt to pre-allocate the output buffer for the image. What if the requested production window is smaller than the `array_out` buffer ? ```python # Set a window to focus on the left eye (we get the coordinates from the previous resampled image) win = np.asarray([[250, 320], [120, 220]]) # We have to init the out buffer with an sufficient shape array_out = np.zeros((200, 200), dtype=data_out_dtype) # Lets call the grid resampling _, mask_out = array_grid_resampling( interp="cubic", array_in=array_in, grid_row=yrot, grid_col=xrot, grid_resolution=(1,1), array_out=array_out, win=win, array_in_mask=None, grid_mask=None, array_out_mask=True, nodata_out=None, standalone=True, boundary_condition=None, trust_padding=False, ) ``` ![003_output_target_window_off.png](grid_resampling_003_output_control_files/003_output_target_window_off.png) It’s worth noting that even without passing a preallocated output validity mask, the internally generated one will still match the shape of the `array_out` buffer. As shown above, the resampled window is written starting at the origin of `array_out` (i.e., at [0, 0]). In some cases - for example, when working with tiles that share a common output buffer - it may be necessary to write the result to a specific region within `array_out`. This is precisely the purpose of the `array_out_win` parameter. ```python # Set a window to focus on the left eye (we get the coordinates from the previous resampled image) win = np.asarray([[250, 320], [120, 220]]) # We have to init the out buffer with an sufficient shape # Here we will also demonstrate that the resampling only modify the target window # For that purpose we do not initialize with zeros but with arange array_out = np.arange(200*200, dtype=data_out_dtype).reshape((200, 200)) % 255 # We also preallocate the validity mask for the same purpose mask_out = np.arange(array_out.size, dtype=np.uint8).reshape(array_out.shape) % 10 # Let's define where we want to place the resampled window array_out_win_origin = np.asarray([25, 40]) array_out_win = np.asarray([ [array_out_win_origin[0], array_out_win_origin[0] + win[0][1] - win[0][0]], [array_out_win_origin[1], array_out_win_origin[1] + win[1][1] - win[1][0]]]) # Lets call the grid resampling _, _ = array_grid_resampling( interp="cubic", array_in=array_in, grid_row=yrot, grid_col=xrot, grid_resolution=(1,1), array_out=array_out, array_out_win=array_out_win, # <= new parameter win=win, array_in_mask=None, grid_mask=None, array_out_mask=mask_out, nodata_out=None, standalone=True, boundary_condition=None, trust_padding=False, ) ``` ![003_output_target_window_on.png](grid_resampling_003_output_control_files/003_output_target_window_on.png) Note that this example also demonstrates that operating on a specific window only affects the corresponding region in the output array, leaving all other areas unchanged.