Changelog for 1.1
=================

1.1.10
------

Release date: 29 July 2026

- Fixed a bug with :meth:`NCMesh.profile()<pytuflow.NCMesh.profile>` when extracting data from a 2D vector type (e.g. velocity).

1.1.9
-----

Release date: 27 July 2026

- Fixed a bug where vector types that were not the "velocity" data type in the :class:`~pytuflow.NCMesh` format could cause an error when loading the results.

1.1.8
-----

Release date: 18 June 2026

- Fixed an uncaught exception if a TIF Projection command was present in a :class:`~pytuflow.TCF` and the file did not exist. The error is now logged, but loading will continue which matches other similar behaviour when attempting to loadi missing files.
- Improved logging messages when GDAL Python bindings are not installed and projection extraction fails as a consequence.
- Fixed a bug where files referenced in GIS attributes were incorrectly being added to the :attr:`~pytuflow.GisInput.files` property for projection commands.
- Fixed a bug when extracting time-series data from a bc_dbase where the source file was a CSV and contained a comment row above the header row.

1.1.7
-----

Release date: 08 June 2026

- Fixed a bug that could cause an error and prevent the :class:`~pytuflow.XMDF` output class from loading if the "Bathymetry" data type (produced by the "ZH" map output data type) was not within the "Temporal" folder within the XMDF.

1.1.6
-----

Release date: 05 June 2026

- Fixed a bug when the "ZH" map output data type was included in the XMDF result file which caused an error when loading the :class:`~pytuflow.XMDF` output class.
- Fixed a bug that could occur when extracting data from a 2D only :class:`~pytuflow.NCMesh` output with only QGIS drivers.

1.1.5
-----

Release date: 26 May 2026

- Fixed a bug when extracting data from a pit inlet database. The area column was incorrectly being applied as an "index add" column which caused the depth column to have the area added to the values.
- Fixed a bug for NetCDF mesh outputs that contained the "zb" result type. The "zb" result type would incorrectly be ignored, a fix has been added to ensure that the "zb" result type is correctly recognised and extracted.

1.1.4
-----

Release date: 13 May 2026

- Fixed a bug for the :meth:`DATCrossSections.ids()<pytuflow.DATCrossSections.ids>` method where the filter would only work if the filter matched an ID. This doesn't make sense for this method and it has been fixed to accept the usual filters such as a domain type.

1.1.3
-----

Release date: 12 May 2026

- Fixed a bug where comment inputs were not removed when called with :meth:`remove_input()<pytuflow.TCF.remove_input>`.
- Updated several docstrings to fix formatting.

1.1.2
-----

Release date: 1 May 2026

- Fixed a number of potential security vulnerabilities.

1.1.1
-----

Release date: 8 April 2026

- Fixed a bug in the :class:`TPC<pytuflow.TPC>` class when the 2D results included structure groups. The ``"u/s structure water level"`` and ``"d/s structure water level"`` data types were causing issues with PyTUFLOW's handling of the forward slash ``"/"`` character. This character has a special meaning in PyTUFLOW for separating context in the location/filter strings. This issue caused PyTUFLOW to not be able to plot from these data types. The ``"/"`` character is now replaced with a dash ``"-"`` character for these data types to avoid this issue.
- Fixed a bug in the :class:`TuflowBinaries<pytuflow.TuflowBinaries>` class where binaries found from installed locations from the Window MSI installation were incorrectly pointing at the folder rather than the ``.exe`` file.
- Fixed a bug when loading a TUFLOW-SWMM output with the :class:`GPKG1D()<pytuflow.GPKG1D>` class where the results would fail to load due to channels that contained all ``NaN`` values for a given data type. This caused a loading error when the class tried to calculate the time of maximum for that data type.
- Fixed a regression bug in the :class:`TCF<pytuflow.TCF>` class which would cause an error when encountering an absolute file path for folder inputs (e.g. ``Write Check Files == C:\TUFLOW\Model\Check\``).
- Fixed a regression bug in the :class:`TCF<pytuflow.TCF>`, and other control file classes, when a GPKG input contained a variable in the layer name (e.g. ``Read GIS PO == database.gpkg >> 2d_po_<<~s~>>_L``).
- Fixed a bug when loading a :class:`TCF<pytuflow.TCF>` file that contained an ``MI Projection == CoordSys...`` style command.

1.1.0
-----

Release date: 26 March 2026

Removed QGIS Dependency Requirement
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

QGIS is no longer required for extracting data from mesh outputs. Prior to ``v1.1``, PyTUFLOW required a QGIS environment to be able to extract data from mesh outputs (e.g. :meth:`XMDF.time_series()<pytuflow.XMDF.time_series>`, :meth:`XMDF.section()<pytuflow.XMDF.section>` etc). In place of QGIS, PyTUFLOW will use `PyVista <https://docs.pyvista.org>`_ for mesh geometry operations and either `NetCDF4 <https://unidata.github.io/netcdf4-python/>`_ or `h5py <https://www.h5py.org/>`_ for extracting the dataset values (h5py is typically a little faster and will be preferred by PyTUFLOW).

This change comes with speed improvements for loading mesh outputs as well as significant speed improvements when extracting data along a linestring (e.g. for :meth:`XMDF.section()<pytuflow.XMDF.section>` and :meth:`XMDF.curtain()<pytuflow.XMDF.curtain>` methods). See the :ref:`Optimised Mesh Outputs<v1.1_optimisations>` section for more details.

Removed GDAL Dependency Requirement
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

GDAL is no longer required for GIS operations or data extraction. PyTUFLOW now uses `GeoPandas <https://geopandas.org>`_ for vector datasets and `Rasterio <https://rasterio.readthedocs.io>`_ for raster datasets. This change simplifies the installation process for PyTUFLOW.

GDAL can still be used in lieu of GeoPandas and Rasterio, however GeoPandas and Rasterio will be preferred by PyTUFLOW if they are available in the Python environment.

New Methods for Map Output Classes
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

New methods have been added to the map output classes (:meth:`XMDF<pytuflow.XMDF>`, :meth:`NCMesh<pytuflow.NCMesh>`, :meth:`DAT<pytuflow.DAT>`, :meth:`NCGrid<pytuflow.NCGrid>`, :meth:`CATCHJson<pytuflow.CATCHJson>`):

- :meth:`data_point()<pytuflow.XMDF.data_point>`: Extract a single data point at a given time and location.
- :meth:`maximum()<pytuflow.XMDF.maximum>`: Extract the maximum value over the entire simulation for a given location or set of locations.
- :meth:`minimum()<pytuflow.XMDF.minimum>`: Extract the minimum value over the entire simulation for a given location or set of locations.
- :meth:`surface()<pytuflow.XMDF.surface>`: Extract a 2D surface at a given time and data type.

.. _v1.1_optimisations:

Optimised Mesh Outputs
^^^^^^^^^^^^^^^^^^^^^^

New mesh drivers have been added for handling mesh outputs with QGIS libraries (nominally called "QGIS drivers") and without QGIS libraries (nominally called "Python drivers").

The best drivers will be chosen automatically based on the available libraries in your Python environment, but it is also possible to specify which drivers to use when initialising the output class. It is recommended to use the Python drivers where possible for speed improvements and to reduce the complexity of the Python environment. Python drivers also offer faster initialisation times since the mesh geometry is not loaded until it is required for data extraction.

The tables below summarise benchmarking results for the different drivers. The table is for comparison purposes only and the actual times will depend on the model size, computer hardware, and Python environment.

.. csv-table:: Benchmarking information
  :file: assets/tables/v1.1_benchmarking_specs.csv
  :header-rows: 1

\* Section() line cell count relates to the last table

.. csv-table:: Load times (XMDF) - including loading mesh geometry and generating spatial indexing (seconds)
  :file: assets/tables/v1.1_benchmarking_loading.csv
  :header-rows: 1

.. csv-table:: Single data point extraction (seconds)
  :file: assets/tables/v1.1_benchmarking_data_point.csv
  :header-rows: 1

.. csv-table:: Section extraction (seconds)
  :file: assets/tables/v1.1_benchmarking_section.csv
  :header-rows: 1

\* Did not finish within 30 minutes.

\*\* "New QGIS Drivers" refers to optimisations made to the Python code in PyTUFLOW for using QGIS and does not refer to any changes in QGIS itself.

Optimised NetCDF Grid Output
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The :class:`NCGrid<pytuflow.NCGrid>` output class has been optimised for speed when extracting data. In particular, the :meth:`NCGrid.section()<pytuflow.NCGrid.section>` has been optimised when finding the cells along a linestring. The :meth:`NCGrid.section()<pytuflow.NCGrid.section>` method is now ~2x faster than in previous versions.

Some data caching has also been implemented for faster repeated calls to the same data type.

Optimised TPC Output
^^^^^^^^^^^^^^^^^^^^

Significant speed up for loading TPC results from a model that contains a lot of channels (in the order of > 500). For example, a test was run on a model that contained approximately 5,000 pipes, and the load time went from 15 seconds to < 1 second.

Installed TUFLOW Locations
^^^^^^^^^^^^^^^^^^^^^^^^^^

PyTUFLOW will now automatically find installed TUFLOW versions. That is, versions of TUFLOW installed via the ``.msi`` installer on Windows or the ``.deb`` and ``.rpm`` packages on Linux. This means that users can use the :class:`TCFRunState.run()<pytuflow.TCFRunState.run>` method with installed versions of TUFLOW without needing to register the TUFLOW binary locations.

Minor New Features
^^^^^^^^^^^^^^^^^^

- Added Flood Modeller DAT cross-section output class - :class:`DATCrossSections<pytuflow.DATCrossSections>`. This is essentially a wrapper around the ``FmCrossSectionDatabaseDriver`` class and allows users to interact with Flood Modeller DAT files in an easier way via the ``Output`` class methods - e.g. :meth:`ids()<pytuflow.DATCrossSections.ids>`, :meth:`data_types()<pytuflow.DATCrossSections.data_types>`, :meth:`section()<pytuflow.DATCrossSections.section>`.
- Added :attr:`has_reference_time<pytuflow.XMDF.has_reference_time>` property to all output classes. This property holds whether the loaded output contains an explicit reference time. The :attr:`reference_time<pytuflow.XMDF.reference_time>` property will always return a value and as a consequence cannot be used for this purpose.
- Curtain plots will now return a fourth column for vector results that contain the vector projected onto the direction of the input linestring.
- ``direction_of_velocity`` and ``direction_of_unit_flow`` are now recognised as separate scalar datasets. Previously, these would be assumed to be combined with the velocity and unit flow magnitude datasets respectively and then treated as a vector dataset. This change allows the datasets to be treated separately and the available datasets align more closely with what is actually in the NetCDF file. This also allows users to plot the direction datasets as scalar datasets.
- Calculated offsets in the :meth:`section()<pytuflow.NCMesh.section>` and :meth:`curtain()<pytuflow.NCMesh.curtain>` methods will now return ellipsoid distances if the results are using spherical coordinates.
- :meth:`CATCHJson.time_series()<pytuflow.CATCHJson.time_series>` and :meth:`CATCHJson.profile()<pytuflow.CATCHJson.profile>` methods can now return results from multiple locations if the locations fall within different result domains (e.g. one point could sit within the TUFLOW HPC catchment result and the other within the 2D receiving TUFLOW FV receiving result).
- Additional context can now be added when extracting results from the :class:`TPC<pytuflow.TPC>` result class. For example, when extracting :meth:`time_series()<pytuflow.TPC.time_series>` results, it's possible to add additional context such as the domain (e.g. ``"channel"`` or ``"rl"``) by adding this context to the location with a ``"/"`` delimiter e.g. ``"rl/flow_line"``.
- Comments in material files are now kept in the resulting DataFrame.
- Adds a :attr:`line_number<pytuflow.SettingInput.line_number>` property to the :class:`Input<pytuflow.SettingInput>` class that represents the line in the control file the input command is on.
- Adds a :meth:`Scope.pretty_print()<pytuflow.Scope.pretty_print>` method.

Bug Fixes
^^^^^^^^^

- ``"water depth"`` data type is now correctly recognised as ``"depth"`` .
- Max data types now correctly return maximum water surface elevation for 2D results for the :meth:`curtain()<pytuflow.XMDF.curtain>` method.
- Fixed a bug where ``"vector"`` was being removed from the data type ``"vector velocity"`` or ``"max vector velocity"`` when making calls to the plotting methods (:meth:`time_series()<pytuflow.XMDF.time_series>`, :meth:`section()<pytuflow.XMDF.section>` etc). Typically only matters for the :meth:`curtain()<pytuflow.XMDF.curtain>` method where the raw vector data can be used rather than the scalar values.
- Changed the :class:`NCGrid<pytuflow.NCGrid>` return DataFrame column names to be consistent with other output classes. Previously the columns were ``dat_type/name`` and now it is ``name/data_type``.
- ``magnitude_of_velocity`` and are recognised as ``velocity`` (affects :class:`NCGrid<pytuflow.NCGrid>` outputs).
- Fixed a bug for Quadtree results prior to the TUFLOW ``2026.0.0`` release. There was a bug in TUFLOW (fixed in ``2026.0.0``) where Quadtree hardcoded PO geometry types to "R" (region/polygon) in the ``plot/GIS/PLOT.csv`` file. This resulted in a downstream bug in PyTUFLOW when using any geometry filters in methods such as :meth:`data_types()<pytuflow.TPC.data_types>`. PyTUFLOW has been updated to double check the geometry types on load if encountering "R" geometries so results from TUFLOW versions prior to ``2026.0.0`` can still be used.
- Fixed a bug for :class:`GPKG2D<pytuflow.GPKG2D>` and :class:`GPKGRL<pytuflow.GPKGRL>` classes where using a ``"polygon"`` filter in either the :meth:`data_types()<pytuflow.GPKG2D.data_types>` or :meth:`ids()<pytuflow.GPKG2D.ids>` methods would return an empty list even if there were PO or RL polygons in the results.
- Fixed a bug for :meth:`section()<pytuflow.XMDF.section>` and :meth:`curtain()<pytuflow.XMDF.curtain>` methods for Quadtree results when the line intersected transition zones which could cause additional points to be added to the resulting DataFrame with ``NaN`` values.
- Fixed a bug for :meth:`CATCHJson.time_series()<pytuflow.CATCHJson.time_series>` method that incorrectly report an invalid data type if the location was not within the result domain that contained the data type (but the data type existed in another result domain). Example, ``"salinity"`` could exist within the TUFLOW FV receiving results but not in the TUFLOW HPC catchment results. If the location was within the TUFLOW HPC catchment results, then the method would incorrectly report that ``"salinity"`` was an invalid data type, even though it was a valid data type in the TUFLOW FV receiving results.
- :class:`FMTS<pytuflow.FMTS>` output class no longer returns ``"bed level"`` and ``"pipes"`` from the :meth:`FMTS.data_types()<pytuflow.FMTS.data_types>` method if a ``.dat`` file is not provided.
- Fixed instances where an integer key would cause an error or an empty return when getting a value from a database e.g. in a material file.
- TUFLOW cross-section database values now return the cross-section offset as the index in the returned DataFrame.
- :meth:`CATCHJson.time_series()<pytuflow.CATCHJson.time_series>` and :meth:`CATCHJson.profile()<pytuflow.CATCHJson.profile>` methods now search through all results. Previously, it would short circuit and return once it found any active results. This worked if only extracting from a single point, however if multiple points were passed in and they sat within different result domains, then the second point would return an invalid data type error since the method had already short circuited and returned the results from the first point.
- Better handling of corrupt TUFLOW version caches.