Skip to content

Add possibility to have a raster path_to_mask in Workflows config file - #970

Open
marinebcht wants to merge 19 commits into
GlacioHack:mainfrom
marinebcht:954_mask_tiff
Open

Add possibility to have a raster path_to_mask in Workflows config file#970
marinebcht wants to merge 19 commits into
GlacioHack:mainfrom
marinebcht:954_mask_tiff

Conversation

@marinebcht

@marinebcht marinebcht commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Resolves #954

Workflow accuracy and topo now accept raster path_to_mask, no matter its projection/footprint :

inputs:
  reference_elev:
    path_to_elev: "longyearbyen_ref_dem"
    path_to_mask: "path/mask.tif"
  to_be_aligned_elev:
    path_to_elev: "longyearbyen_tba_dem"
  sampling_grid: reference_elev
inputs:
  - path_to_elev: "longyearbyen_ref_dem"
    path_to_mask: "path/mask.tif"

Nan values in the mask

Nan value are translated by False : see here. For example, in the glacier mask case: NaN (no data before or after reprojection) values are not conidarated as Glacier.

Operation

This mask is :

  1. read as Raster
  2. translated as boolean (0 is False, !=0 is True)
  3. filled with False
  4. reprojected in the corresponding dem projection

@marinebcht

marinebcht commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@belletva raster path_to_mask must it necessarily be a boolean or are int+ rasters accepted?

@marinebcht marinebcht closed this Jun 18, 2026
@marinebcht
marinebcht deleted the 954_mask_tiff branch June 18, 2026 14:11
@marinebcht
marinebcht restored the 954_mask_tiff branch June 18, 2026 14:11
@marinebcht marinebcht reopened this Jun 18, 2026
@marinebcht

marinebcht commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

Some thoughts :

  • A) shapefile -> create_mask(dem) -> raster with true : pink, false: black
image
  • B) from this raster, inlier mask used mask in terrain/coreg become true : black, pink: white -> black is the values needed to be masked
image

To use raster as mask we need to provide a tiff as the input of (A) :

  • True = glacier = to be masked
  • False = to keep, whitch is prettry logical

Is the case where we have a mask smaller than the dem : the projection need to fit it gives nan values.
Nan values need to be considerate as values to keep (false) = there is no glaciers in it.


If mask not boolean => mask.astype(bool) (0 values = True, != 0 set False
If mask with nan => mask.data.filled(False)

marinebcht and others added 8 commits June 24, 2026 17:23
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@marinebcht

Copy link
Copy Markdown
Contributor Author

Hi @rhugonnet, can you confirm the process presented above to translate a raster in a actual mask ? :) Thanks

@marinebcht marinebcht self-assigned this Jul 6, 2026
@rhugonnet

Copy link
Copy Markdown
Member

@marinebcht Seems good to me.
@adehecq Do you see other cases?

The only thing that comes to mind right now is that the reprojection step should probably be done BEFORE masking if the mask is derived from a continuous-value raster, such as elevation (e.g., elevation > 500 m and < 1000 m), but I don't think this applies to a user input for Workflows (where the mask is a file already on disk).
If the user wants a different resampling of their raster being used as mask, they need to do this themselves beforehand anyway.

Another question for the API and to facilitate workflow input is: Do we only accept a single type of mask file from users (0 + NaN = False, other = True), or do we also allow a tag "invert_mask" to use the binary opposite of the mask (whether it is from a raster or vector)?

@marinebcht
marinebcht requested review from belletva and rhugonnet July 22, 2026 13:29
@marinebcht

Copy link
Copy Markdown
Contributor Author

@belletva @rhugonnet ready to review so :)

Comment thread tests/test_workflows/test_workflows.py Outdated
Comment thread xdem/workflows/workflows.py Outdated

inlier_mask = inlier_mask.reproject(dem, silent=True)
except rasterio.errors.RasterioIOError:
raise ValueError("You provided a 'path_to_mask' value that is not recognised as a mask.")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be more specific on the error message, and maybe collect original errors to return them through this one, something like:

# Treat the mask according to its type (Vector or Raster)
try:
    mask = gu.Vector(mask_path)
    inlier_mask = ~mask.create_mask(dem)

except pyogrio.errors.DataSourceError as vector_error:
    try:
        inlier_mask = gu.Raster(mask_path).astype(bool)
        inlier_mask.data = inlier_mask.data.filled(False)
        inlier_mask = inlier_mask.reproject(dem, silent=True)

    except rasterio.errors.RasterioIOError as raster_error:
        errors = ExceptionGroup(
            f"Could not read {mask_path!r} as either a vector or raster mask.",
            [vector_error, raster_error],
        )
        raise ValueError(
            "You provided a 'path_to_mask' value that is not recognised as a mask."
        ) from errors

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for introducing me to ExceptionGroup; I’ve just discovered it.
But what is the added value, as it is not the dependancies ?
PS1: Non-existent files also first raise an error during the schema validation step.
PS2: rasterio gives the reason above our "ValueError"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The added value is that the errors are traced all the way back, instead of being interrupted by our own ValueError in xDEM.

Concretely: In case of an error, instead of just printing "ValueError in xdem.xxx: You provided a .... that is not recognized as a mask" and stopping there, it also prints "from RasterioIOError in rasterio.xxx: message". Most often, the "message" from Rasterio will be "GDAL could not recognize filename path_to_mask as a valid input...".
So the user knows all the underlying causes, and it's easier to debug.

Not sure I understood your point about "not in the dependencies": if related to ExceptionGroup, it is available in base Python! 😄

rhugonnet
rhugonnet previously approved these changes Jul 22, 2026

@rhugonnet rhugonnet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, a few comments above.
I wondered: do we also need to update the documentation to specify how this behaves?

dependabot Bot and others added 3 commits July 24, 2026 10:32
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Comment thread xdem/workflows/workflows.py Outdated

inlier_mask = inlier_mask.reproject(dem, silent=True)
except rasterio.errors.RasterioIOError:
raise ValueError("You provided a 'path_to_mask' value that is not recognised as a mask.")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for introducing me to ExceptionGroup; I’ve just discovered it.
But what is the added value, as it is not the dependancies ?
PS1: Non-existent files also first raise an error during the schema validation step.
PS2: rasterio gives the reason above our "ValueError"

:::

:::{note}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove empty line


To set the vertical CRS or to override one that might exist in the metadata with ``force_vcrs``,
please refer to {ref}`vertical-ref`.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The renduring

Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Raster masks not supported in workflows

3 participants