TUFLOW-Support / QGIS-TUFLOW-Plugin

TUFLOW related QGIS Plugins
11 stars 7 forks source link

Using tuflow plugin from a headless state #41

Open stevenjh opened 3 months ago

stevenjh commented 3 months ago

Hi there, I have TUFLOW model results, and am looking to create custom flow time series charts as represented on this page

However I'm looking to run these without having a user open QGIS/Tuflow plugin, the polyline will be drawn in a different system and I want to use the TUFLOW plugin in the background to execute the 'Plot Flux From Map' feature, returning the charting x/y values required to render the plot in a different system.

I've only just started exploring the plugin but am wondering:

I come from a Software/GIS background and have started tracing it backwards from the button tooltip, any guidance will be appreciated!

Thanks!

EllisSymons commented 3 months ago

Hi, yes this is possible to do. The below example script will plot flow from a given XMDF using a shapefile to define the locations for extraction. This script will run headless if you can get your QGIS python environment setup (there is a python-qgis.bat file within the bin folder in the QGIS installation directory that should help with this).

If you running from within the console in QGIS, then you can remove a lot of the setup (can probably start from where the viewer is initialised).

import sys

sys.path.append(r"C:\Users\ellis.symons\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins")  # path to qgis plugins - needs to be changed to your path
sys.path.append(r'C:\OSGeo4W\apps\qgis\python')  # you may need to add this path as well, this is the path to the qgis.core libraries - may need to be changed depending on your installation location

import matplotlib.pyplot as plt
from qgis.core import QgsApplication, QgsVectorLayer
from tuflow.tuflowqgis_tuviewer.tuflowqgis_tuview import TuView
from tuflow.tuflowqgis_tuviewer.tuflowqgis_tuplot import TuPlot

XMDF_PATH = 'EG00_000.xmdf'  # path to the xmdf file - needs to be updated
FLOW_LINE_PATH = 'flowline.shp'  # path to the shapefile - needs to be updated

if __name__ == '__main__':
    # initialise QGIS
    argv = [bytes(x, 'utf-8') for x in sys.argv]
    qgis = QgsApplication(argv, False)
    qgis.initQgis()

    # initialise the vector layer
    layer = QgsVectorLayer(FLOW_LINE_PATH, 'flowline', 'ogr')
    if not layer.isValid():
        raise Exception('Layer failed to load!')

    # select desired features within the layer for plotting - selectAll in this example
    feats = layer.selectAll()

    # initialise viewer and load results
    viewer = TuView()
    success = viewer.tuResults.importResults('mesh', [XMDF_PATH])
    if not success:
        raise Exception('Failed to load results!')

    # get the gui menu item associated with flow
    menu = viewer.tuPlot.tuPlotToolbar.plotDataToPlotMenu[TuPlot.DataFlow2D]
    menu.setChecked(True)  # set the menu to checked
    viewer.cboSelectType.setCurrentText('Layer Selection')  # sets the selection type to layer selection rather than interactive drawing on map canvas

    # trigger the plotting - mesh_rendered needs to be False when running headless
    viewer.tuPlot.tuPlotToolbar.mapOutputPlottingButtonClicked(TuPlot.DataFlow2D, layer=layer, mesh_rendered=False)

    # get the fig, ax objects from the viewer that is associated with the time series tab
    fig, ax = viewer.tuPlot.plotEnumerator(TuPlot.TimeSeries)[1:3]

    # test if it's working - can remove and replace with whatever you want to do with the data
    fig.savefig('flow.png')

    # cleanup when finished
    viewer.tuMenuBar.tuMenuFunctions.remove2dResults()  # removes active results
    viewer.qgisDisconnect(completely_remove=True)
    plt.close('all')
stevenjh commented 3 months ago

Oh amazing reply, thanks so much, I'm not needing to do this but really want to give it a go now!