
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "basic_examples/plot_dem_subtraction.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_basic_examples_plot_dem_subtraction.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_basic_examples_plot_dem_subtraction.py:


DEM differencing
================

Subtracting a DEM with another one should be easy.

xDEM allows to use any operator on :class:`xdem.DEM` objects, such as :func:`+<operator.add>` or :func:`-<operator.sub>` as well as most NumPy functions
while respecting nodata values and checking that georeferencing is consistent. This functionality is inherited from `GeoUtils' Raster class <https://geoutils.readthedocs.io>`_.

Before DEMs can be compared, they need to be reprojected to the same grid and have the same 3D CRSs. The :func:`~xdem.DEM.reproject` and :func:`~xdem.DEM.to_vcrs` methods are used for this.

.. GENERATED FROM PYTHON SOURCE LINES 13-18

.. code-block:: Python


    import geoutils as gu

    import xdem








.. GENERATED FROM PYTHON SOURCE LINES 19-20

We load two DEMs near Longyearbyen, Svalbard.

.. GENERATED FROM PYTHON SOURCE LINES 20-24

.. code-block:: Python


    dem_2009 = xdem.DEM(xdem.examples.get_path("longyearbyen_ref_dem"))
    dem_1990 = xdem.DEM(xdem.examples.get_path("longyearbyen_tba_dem_coreg"))








.. GENERATED FROM PYTHON SOURCE LINES 25-26

We can print the information about the DEMs for a "sanity check".

.. GENERATED FROM PYTHON SOURCE LINES 26-30

.. code-block:: Python


    dem_2009.info()
    dem_1990.info()





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    Driver:               GTiff 
    Opened from file:     /home/docs/checkouts/readthedocs.org/user_builds/xdem-ould-a/checkouts/latest/xdem/example_data/Longyearbyen/data/DEM_2009_ref.tif 
    Filename:             /home/docs/checkouts/readthedocs.org/user_builds/xdem-ould-a/checkouts/latest/xdem/example_data/Longyearbyen/data/DEM_2009_ref.tif 
    Loaded?               False 
    Modified since load?  False 
    Grid size:            1332, 985
    Number of bands:      1
    Data types:           float32
    Coordinate system:    ['EPSG:25833', 'None']
    Nodata value:         -9999.0
    Pixel interpretation: Area
    Pixel size:           20.0, 20.0
    Upper left corner:    502810.0, 8674030.0
    Lower right corner:   529450.0, 8654330.0

    Driver:               GTiff 
    Opened from file:     /home/docs/checkouts/readthedocs.org/user_builds/xdem-ould-a/checkouts/latest/xdem/example_data/Longyearbyen/processed/DEM_1990_coreg.tif 
    Filename:             /home/docs/checkouts/readthedocs.org/user_builds/xdem-ould-a/checkouts/latest/xdem/example_data/Longyearbyen/processed/DEM_1990_coreg.tif 
    Loaded?               False 
    Modified since load?  False 
    Grid size:            1332, 985
    Number of bands:      1
    Data types:           float32
    Coordinate system:    ['EPSG:25833', 'None']
    Nodata value:         -9999.0
    Pixel interpretation: Area
    Pixel size:           20.0, 20.0
    Upper left corner:    502810.0, 8674030.0
    Lower right corner:   529450.0, 8654330.0





.. GENERATED FROM PYTHON SOURCE LINES 31-33

In this particular case, the two DEMs are already on the same grid (they have the same bounds, resolution and coordinate system).
If they don't, we need to reproject one DEM to fit the other using :func:`xdem.DEM.reproject`:

.. GENERATED FROM PYTHON SOURCE LINES 33-36

.. code-block:: Python


    dem_1990 = dem_1990.reproject(dem_2009)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    /home/docs/checkouts/readthedocs.org/user_builds/xdem-ould-a/conda/latest/lib/python3.14/site-packages/geoutils/raster/geotransformations.py:101: UserWarning: Output projection, bounds and grid size are identical -> returning self (not a copy!)
      warnings.warn("Output projection, bounds and grid size are identical -> returning self (not a copy!)")




.. GENERATED FROM PYTHON SOURCE LINES 37-43

Oops!
GeoUtils just warned us that ``dem_1990`` did not need reprojection. We can hide this output with ``silent``.
By default, :func:`~xdem.DEM.reproject` uses "bilinear" resampling (assuming resampling is needed).
Other options are detailed at `geoutils.Raster.reproject() <https://geoutils.readthedocs.io/en/latest/api.html#geoutils.raster.Raster.reproject>`_ and `rasterio.enums.Resampling <https://rasterio.readthedocs.io/en/latest/api/rasterio.enums.html#rasterio.enums.Resampling>`_.

We now compute the difference by simply substracting, passing ``stats=True`` to :func:`xdem.DEM.info` to print statistics.

.. GENERATED FROM PYTHON SOURCE LINES 43-48

.. code-block:: Python


    ddem = dem_2009 - dem_1990

    ddem.info(stats=True)





.. rst-class:: sphx-glr-script-out

 .. code-block:: none

    Driver:               None 
    Opened from file:     None 
    Filename:             None 
    Loaded?               True 
    Modified since load?  True 
    Grid size:            1332, 985
    Number of bands:      1
    Data types:           float32
    Coordinate system:    ['EPSG:25833', 'None']
    Nodata value:         -9999.0
    Pixel interpretation: Area
    Pixel size:           20.0, 20.0
    Upper left corner:    502810.0, 8674030.0
    Lower right corner:   529450.0, 8654330.0

    Statistics:
    Mean                   : -1.19
    Median                 : -0.37
    Max                    : 49.90
    Min                    : -50.32
    Sum                    : -1560131.12
    Sum of squares         : 42497068.00
    90th percentile        : 3.33
    LE90                   : 16.11
    IQR                    : 3.82
    NMAD                   : 2.83
    RMSE                   : 5.69
    Standard deviation     : 5.57
    Valid count            : 1312020.00
    Total count            : 1312020.00
    Percentage valid points: 100.00





.. GENERATED FROM PYTHON SOURCE LINES 49-51

It is a new :class:`~xdem.DEM` instance, loaded in memory.
Let's visualize it, with some glacier outlines.

.. GENERATED FROM PYTHON SOURCE LINES 51-58

.. code-block:: Python


    # Load the outlines
    glacier_outlines = gu.Vector(xdem.examples.get_path("longyearbyen_glacier_outlines"))
    glacier_outlines = glacier_outlines.crop(ddem, clip=True)
    ddem.plot(cmap="RdYlBu", vmin=-20, vmax=20, cbar_title="Elevation differences (m)")
    glacier_outlines.plot(ref_crs=ddem, fc="none", ec="k")




.. image-sg:: /basic_examples/images/sphx_glr_plot_dem_subtraction_001.png
   :alt: plot dem subtraction
   :srcset: /basic_examples/images/sphx_glr_plot_dem_subtraction_001.png
   :class: sphx-glr-single-img





.. GENERATED FROM PYTHON SOURCE LINES 59-60

And we save the output to file.

.. GENERATED FROM PYTHON SOURCE LINES 60-62

.. code-block:: Python


    ddem.to_file("temp.tif")








.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (0 minutes 8.520 seconds)


.. _sphx_glr_download_basic_examples_plot_dem_subtraction.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: plot_dem_subtraction.ipynb <plot_dem_subtraction.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: plot_dem_subtraction.py <plot_dem_subtraction.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: plot_dem_subtraction.zip <plot_dem_subtraction.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
