Difference between revisions of "Python Library TUFLOW Results"
(7 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
− | [[File:TUPython.png | | + | [[File:TUPython.png | 435px]] |
− | |||
=Introduction= | =Introduction= | ||
For the 2016 version of TUFLOW a new output format for time-series was made available, this has the following changes from previous versions: | For the 2016 version of TUFLOW a new output format for time-series was made available, this has the following changes from previous versions: | ||
Line 10: | Line 9: | ||
This is the default approach for the 2016 version but can be modified with the TUFLOW command "<tt>Output Approach == Pre 2016</tt>" (refer to the manual for more information on this command.<br> | This is the default approach for the 2016 version but can be modified with the TUFLOW command "<tt>Output Approach == Pre 2016</tt>" (refer to the manual for more information on this command.<br> | ||
To make this data easier to work with an open source python library has been created and made available. This allows the user to load results and then interact with these. This library does not have any plotting functionality directly, with the returns typically being arrays (e.g. time and flows) however, the examples below give some examples using common plotting libraries such as matplotlib.<br> | To make this data easier to work with an open source python library has been created and made available. This allows the user to load results and then interact with these. This library does not have any plotting functionality directly, with the returns typically being arrays (e.g. time and flows) however, the examples below give some examples using common plotting libraries such as matplotlib.<br> | ||
+ | =Getting the TUFLOW results python library= | ||
+ | You can find the TUFLOW_results.py (previously TUFLOW_Results2016.py) on the QGIS plugin repository, on the TUFLOW support GitHub repository or if you have QGIS and the TUFLOW plugin installed, you will already have it on your computer. | ||
+ | <ol> | ||
+ | <li>QGIS plugin repo: [https://plugins.qgis.org/plugins/tuflow/ https://plugins.qgis.org/plugins/tuflow/]<br> | ||
+ | : If you select '''Download Latest''' and save the .zip file, the TUFLOW_results.py sits inside the .zip file.</li> | ||
+ | <li>GitHub: [https://github.com/TUFLOW-Support/QGIS-TUFLOW-Plugin QGIS plugin https://github.com/TUFLOW-Support/QGIS-TUFLOW-Plugin]<br> | ||
+ | : If you select '''Clone or Download''' and then select '''Download Zip''' and save the .zip file, the TUFLOW_results.py sits inside the .zip file.</li> | ||
+ | <li>QGIS<br> | ||
+ | : If you have QGIS2 with the TUFLOW plugin installed via the plugin repository, the TUFLOW_results.py sits within: C:\Users\<User Name>\.qgis2\python\plugins\tuflow<br> | ||
+ | : If you have QGIS3 with the TUFLOW plugin installed via the plugin repository, the TUFLOW_results.py sits within: C:\Users\<User Name>\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\tuflow<br></li> | ||
+ | </ol> | ||
+ | The TUFLOW python library does not need to be installed in python (through pip or otherwise) like other common modules, the TUFLOW_results.py file just needs to be in the same location as your python project. | ||
+ | |||
+ | Note it shouldn’t matter if you’re using python 2 or python 3. | ||
=Dependencies= | =Dependencies= | ||
− | The TUFLOW results library calls a number of python | + | The TUFLOW results library calls a number of python modules, these are: |
* csv | * csv | ||
* numpy | * numpy | ||
* os | * os | ||
* sys | * sys | ||
− | Of these the csv, os and sys functionality should be available directly with the python install. Depending on the method used to install python numpy may need to be installed. If installation of numpy is required, please refer to the numpy documentation [http://www.numpy.org/ http://www.numpy.org/]. | + | Of these the csv, os and sys functionality should be available directly with the python install. Depending on the method used to install python, numpy may need to be installed. If installation of numpy is required, please refer to the numpy documentation [http://www.numpy.org/ http://www.numpy.org/]. |
=Compatible Python Versions= | =Compatible Python Versions= | ||
The functionality has been developed for Python 2.7, but should be compatible with Python 3.5. Other versions of python are currently untested. | The functionality has been developed for Python 2.7, but should be compatible with Python 3.5. Other versions of python are currently untested. | ||
Line 24: | Line 37: | ||
==Import== | ==Import== | ||
This library is imported with the typical python syntax.<br> | This library is imported with the typical python syntax.<br> | ||
− | <pre>import | + | <pre>import TUFLOW_results</pre> |
==Initialise Results (ResData)== | ==Initialise Results (ResData)== | ||
The results data functionality has a class defined, this is named '''ResData'''. An instance of the results can be initialised with the following syntax: | The results data functionality has a class defined, this is named '''ResData'''. An instance of the results can be initialised with the following syntax: | ||
− | <pre>res = | + | <pre>res = TUFLOW_results.ResData()</pre> |
==Defined Methods (Functions)== | ==Defined Methods (Functions)== | ||
The following are the defined '''functions''' in the results data class (ResData). | The following are the defined '''functions''' in the results data class (ResData). | ||
Line 45: | Line 58: | ||
<li>Domain - The domain to return the results for, this will be one of '''1D''', '''2D''' or '''RL''' (for reporting location data)</li> | <li>Domain - The domain to return the results for, this will be one of '''1D''', '''2D''' or '''RL''' (for reporting location data)</li> | ||
<li>Results Type - The results type to be returned. This includes H (level), Q (flow), V (velocity), E (energy), QA (flow area) depending on the data types that have been output!</li> | <li>Results Type - The results type to be returned. This includes H (level), Q (flow), V (velocity), E (energy), QA (flow area) depending on the data types that have been output!</li> | ||
− | <li>Geometry - The GIS geometry of the object, '''L''' for line, or '''P''' for point. If unsure or unknown this can be set to a | + | <li>Geometry - The GIS geometry of the object, '''L''' for line, or '''P''' for point. If unsure or unknown this can be set to a blank string such as ''.</li> |
The return arguments are: | The return arguments are: | ||
<li>found (logical) - Returns True if the data has been found, False if the data can not be found or an error has occurred.</li> | <li>found (logical) - Returns True if the data has been found, False if the data can not be found or an error has occurred.</li> | ||
Line 146: | Line 159: | ||
=Examples= | =Examples= | ||
− | These examples can be downloaded | + | These examples work with the Tutorial Model module 4 results. The tutorial model can be downloaded on the [https://www.tuflow.com/Tuflow%20Tutorial%20Models.aspx TUFLOW website]. |
==Plot Flow in Channel== | ==Plot Flow in Channel== | ||
<pre> | <pre> | ||
Line 152: | Line 165: | ||
import sys #system functions | import sys #system functions | ||
import matplotlib.pyplot as plt | import matplotlib.pyplot as plt | ||
− | import | + | import TUFLOW_results |
+ | |||
+ | input_res = r'C:\TUFLOW\Models\Tutorials\QGIS\Complete_Model\TUFLOW\results\M04\2d\plot\M04_5m_001.tpc' | ||
# initialise the results class | # initialise the results class | ||
− | res = | + | res = TUFLOW_results.ResData() |
# Load the data and terminate if error returned | # Load the data and terminate if error returned | ||
Line 170: | Line 185: | ||
#Get flow data | #Get flow data | ||
chan_id = 'ds3' # this is the channel ID to use | chan_id = 'ds3' # this is the channel ID to use | ||
− | found, results, message = res. | + | found, results, message = res.getTSData(chan_id,'1D','Q','L') |
if found: | if found: | ||
− | print 'found requested data' | + | print('found requested data') |
# plot data | # plot data | ||
ax1.plot(res.times,results,color='b',label='Flow - '+chan_id) | ax1.plot(res.times,results,color='b',label='Flow - '+chan_id) | ||
else: | else: | ||
− | print message | + | print(message) |
sys.exit() | sys.exit() | ||
Line 193: | Line 208: | ||
This will create a figure that looks like the above. | This will create a figure that looks like the above. | ||
<br> | <br> | ||
+ | |||
==Plot Multiple Water Levels== | ==Plot Multiple Water Levels== | ||
In this example, it is assumed that the results data has been loaded as per the above. | In this example, it is assumed that the results data has been loaded as per the above. | ||
Line 205: | Line 221: | ||
#Get water level data | #Get water level data | ||
for node_id in node_ids: #for each node in the list above | for node_id in node_ids: #for each node in the list above | ||
− | found, results, message = res. | + | found, results, message = res.getTSData(node_id,'1D','H','P') |
if found: | if found: | ||
− | print 'found requested data' | + | print('found requested data') |
# plot data | # plot data | ||
ax1.plot(res.times,results,label='Level - '+node_id) | ax1.plot(res.times,results,label='Level - '+node_id) | ||
else: | else: | ||
− | print message | + | print(message) |
sys.exit() | sys.exit() | ||
Line 239: | Line 255: | ||
#Get flow data | #Get flow data | ||
− | found, results, message = res. | + | found, results, message = res.getTSData(chan_id,'1D','Q','L') |
if found: | if found: | ||
− | print 'found requested data' | + | print('found requested data') |
ax1.plot(res.times,results,color='b',label='Flow - '+chan_id) | ax1.plot(res.times,results,color='b',label='Flow - '+chan_id) | ||
else: | else: | ||
− | print message | + | print(message) |
sys.exit() | sys.exit() | ||
#Get velocity data | #Get velocity data | ||
− | found, results, message = res. | + | found, results, message = res.getTSData(chan_id,'1D','V','L') |
if found: | if found: | ||
− | print 'found requested data' | + | print('found requested data') |
ax2.plot(res.times,results,color='r',label='Velocity - '+chan_id) | ax2.plot(res.times,results,color='r',label='Velocity - '+chan_id) | ||
else: | else: | ||
− | print message | + | print(message) |
sys.exit() | sys.exit() | ||
Line 280: | Line 296: | ||
error, message = res.LP_getConnectivity(us_chan,ds_chan) | error, message = res.LP_getConnectivity(us_chan,ds_chan) | ||
if error: | if error: | ||
− | print message | + | print(message) |
sys.exit() | sys.exit() | ||
else: | else: | ||
− | print 'LP connectivity determined.' | + | print('LP connectivity determined.') |
− | print 'Get LP static data' | + | print('Get LP static data') |
error, message = res.LP_getStaticData() | error, message = res.LP_getStaticData() | ||
if error: | if error: | ||
− | print message | + | print(message) |
sys.exit() | sys.exit() | ||
else: | else: | ||
− | print 'LP static data retrieved' | + | print('LP static data retrieved') |
#create plot | #create plot | ||
Line 317: | Line 333: | ||
This will create a figure that looks like the above.<br> | This will create a figure that looks like the above.<br> | ||
− | |||
− | |||
− | |||
− | |||
=Other Versions= | =Other Versions= | ||
An older version of the library that is compatible with results from the 2013 version of TUFLOW (this is limited to the 1D results) is also available. This is currently undocumented, however, if you would like this please contact support@tuflow.com. | An older version of the library that is compatible with results from the 2013 version of TUFLOW (this is limited to the 1D results) is also available. This is currently undocumented, however, if you would like this please contact support@tuflow.com. |
Latest revision as of 15:48, 10 May 2018
Introduction
For the 2016 version of TUFLOW a new output format for time-series was made available, this has the following changes from previous versions:
- Combines the 1D results, 2D plot outputs and new reporting location data
- The outputs are stored in a separate Plot folder in the TUFLOW results directory
- .tpc (TUFLOW Plot Control file links to data in csv and gis folders
- Has additional Node and Channel information files contain connectivity information
This is the default approach for the 2016 version but can be modified with the TUFLOW command "Output Approach == Pre 2016" (refer to the manual for more information on this command.
To make this data easier to work with an open source python library has been created and made available. This allows the user to load results and then interact with these. This library does not have any plotting functionality directly, with the returns typically being arrays (e.g. time and flows) however, the examples below give some examples using common plotting libraries such as matplotlib.
Getting the TUFLOW results python library
You can find the TUFLOW_results.py (previously TUFLOW_Results2016.py) on the QGIS plugin repository, on the TUFLOW support GitHub repository or if you have QGIS and the TUFLOW plugin installed, you will already have it on your computer.
- QGIS plugin repo: https://plugins.qgis.org/plugins/tuflow/
- If you select Download Latest and save the .zip file, the TUFLOW_results.py sits inside the .zip file.
- GitHub: QGIS plugin https://github.com/TUFLOW-Support/QGIS-TUFLOW-Plugin
- If you select Clone or Download and then select Download Zip and save the .zip file, the TUFLOW_results.py sits inside the .zip file.
- QGIS
- If you have QGIS2 with the TUFLOW plugin installed via the plugin repository, the TUFLOW_results.py sits within: C:\Users\<User Name>\.qgis2\python\plugins\tuflow
- If you have QGIS3 with the TUFLOW plugin installed via the plugin repository, the TUFLOW_results.py sits within: C:\Users\<User Name>\AppData\Roaming\QGIS\QGIS3\profiles\default\python\plugins\tuflow
- If you have QGIS2 with the TUFLOW plugin installed via the plugin repository, the TUFLOW_results.py sits within: C:\Users\<User Name>\.qgis2\python\plugins\tuflow
The TUFLOW python library does not need to be installed in python (through pip or otherwise) like other common modules, the TUFLOW_results.py file just needs to be in the same location as your python project.
Note it shouldn’t matter if you’re using python 2 or python 3.
Dependencies
The TUFLOW results library calls a number of python modules, these are:
- csv
- numpy
- os
- sys
Of these the csv, os and sys functionality should be available directly with the python install. Depending on the method used to install python, numpy may need to be installed. If installation of numpy is required, please refer to the numpy documentation http://www.numpy.org/.
Compatible Python Versions
The functionality has been developed for Python 2.7, but should be compatible with Python 3.5. Other versions of python are currently untested.
Usage
Import
This library is imported with the typical python syntax.
import TUFLOW_results
Initialise Results (ResData)
The results data functionality has a class defined, this is named ResData. An instance of the results can be initialised with the following syntax:
res = TUFLOW_results.ResData()
Defined Methods (Functions)
The following are the defined functions in the results data class (ResData).
Load Results
Results are loaded in with the syntax below.
error, message = res.Load(r'D:\TUFLOW\QGIS\test\plot\Plot_Example.tpc')
The two return arguments are:
- error (logical) set to True if an error has been encountered.
- message (string), if an error has occurred the message string will be populated with an error message.
Get Time-series
Time-series at a 1D, 2D or reporting location can be returned using the following syntax:
found, results, message = res.getTSData(<ID>,<domain>,<results type>,<geometry>)
The inputs to this are:
The return arguments are:
For example:
found, results, message = res.getTS('ds3','1D','Q','L')
Will return flow (Q) data for the 1D channel with ID ds3. The optional 'L' geometry indicates that this is stored on a line object in the GIS plot objects. Note As the time data typically does not change (this is not a return argument) but can be accessed by the res.times. See the examples below.
Long Profile Functions
When dealing with 1D long profile data, if a single 1D channel is specified the data for all channels downstream will returned. If two channels are specified, long profile data will only be returned for the channels between the specified channels.
Get Long Profile Connectivity (LP_getConnectivity)
This determines and stores the connectivity of the specified channels. This is used in later routines to determine the channels and nodes to plot for the long profile. The syntax is:
error, message = res.LP_getConnectivity(<US Channel ID>,<US Channel ID or None>)
The inputs to this are:
The return arguments are:
error, message = res.LP_getConnectivity('FC01.40',None)
Determines all the channels downstream of FC01.40.
error, message = res.LP_getConnectivity('FC01.40','ds3')
Determines the channels between FC01.40 and ds3, an error will be returned if these channels are not connected.
Get Long Profile Static Data (LP_getStaticData)
Once the connectivity between two channels has been determined, this routine can be used to get data that does not change between time-steps. This includes:
- distance information
- maximum data
- bed levels
The syntax is:
error, message = res.LP_getStaticData()
There are no input arguments as the channel connectivity is stored in the res.LP class. The return arguments are:
Get Long Profile Data (LP_getData)
This function gets data at a specific time. If looping through timesteps (e.g. for an animation) the channel connectivity and static data will not change between timesteps and therefore only the LP_getData will need to be repeated. The syntax is:
error, message = res.LP_getData(<data type>,<time>,<time search tolerance>)
The inputs to this are:
The return arguments are:
error, message = res.LP_getData('Head',1,0.01)
Returns the water level (head) data at time 1 hours using a search tolerance of 0.01 hours.
Other Attributes
Once initialised the ResData class also has a number of attributes associated with it as well as the defined functions described above, these are outlined in the table below.
Attribute Name | Type | Description |
---|---|---|
script_version | string | Contains a version number of the TUFLOW results library, e.g. '2016-01-AA' |
filename | string | The full filepath to the .tpc file. |
fpath | string | The path of the folder which contains the .tpc file. |
nTypes | integer | The number of data types that are stored in the dataset. |
Types | list | A lists of the data types that are stored in the dataset. |
LP | class (LP) | Contains Long profile information, connectivity, distances etc. |
Data_1D | class(Data_1D) | The 1D results are all stored in this class. |
Data_2D | class(Data_2D) | The 2D results are all stored in this class. |
Data_RL | class(Data_RL) | The reporting location results are all stored in this class. |
GIS | class(GIS) | This contains the information read in from the GIS Plot Layer csv files. |
formatVersion | integer | The format version of the results as defined in the .tpc file. |
units | string | The units as defined in the .tpc. E.g. "Metric" or "English" |
displayname | string | The simulation name e.g. "M04_5m_001_2015" |
Index | class(PlotObjects) | This contains data read from the "GIS Plot Objects" |
nodes | class(NodeInfo) | Contains information on the 1D nodes, as read from the "1D Node Info" .csv file. |
Channels | class(ChanInfo) | Contains information on the 1D nodes, as read from the "1D Channel Info" .csv file. |
times | numpy ndarray | The active times. This is typically static, however calls to function getTS may cause this array to be updated (if the 1D or 2D outputs have a different output interval) |
Examples
These examples work with the Tutorial Model module 4 results. The tutorial model can be downloaded on the TUFLOW website.
Plot Flow in Channel
import os #operating system functions import sys #system functions import matplotlib.pyplot as plt import TUFLOW_results input_res = r'C:\TUFLOW\Models\Tutorials\QGIS\Complete_Model\TUFLOW\results\M04\2d\plot\M04_5m_001.tpc' # initialise the results class res = TUFLOW_results.ResData() # Load the data and terminate if error returned error, message = res.Load(input_res) if error: print(message) sys.exit() print('loaded') #create a figure fig = plt.figure() #create new figure ax1 = fig.add_axes((0.10, 0.15, 0.85,0.75)) #add axis to figure #Get flow data chan_id = 'ds3' # this is the channel ID to use found, results, message = res.getTSData(chan_id,'1D','Q','L') if found: print('found requested data') # plot data ax1.plot(res.times,results,color='b',label='Flow - '+chan_id) else: print(message) sys.exit() # manage plot ax1.set_xlabel('Time (hours)') ax1.set_ylabel('Flow (m3/s)') ax1.set_title('Example time-series - single location') ax1.grid() ax1.legend() plt.show()
This will create a figure that looks like the above.
Plot Multiple Water Levels
In this example, it is assumed that the results data has been loaded as per the above.
#create plot fig = plt.figure() #create new figure ax1 = fig.add_axes((0.10, 0.15, 0.85,0.75)) #add axis to figure # list of nodes to plot node_ids = ['FC01.14.1','FC01.15.1','FC01.16.1','FC01.17.1'] #Get water level data for node_id in node_ids: #for each node in the list above found, results, message = res.getTSData(node_id,'1D','H','P') if found: print('found requested data') # plot data ax1.plot(res.times,results,label='Level - '+node_id) else: print(message) sys.exit() # manage plot ax1.set_xlabel('Time (hours)') ax1.set_ylabel('Water Level (mAHD)') ax1.set_title('Example time-series - multiple locations') ax1.set_ybound((38.,44.)) #overwrite the y axis bounds ax1.grid() ax1.legend(loc='lower right') plt.show()
This will create a figure that looks like the above.
Dual Axis (flow and velocity) Plot
In this example it is assumed the results have been loaded as per example 1.
# specify channel to plot chan_id = 'ds3' #create plot fig = plt.figure() #create new figure ax1 = fig.add_axes((0.10, 0.15, 0.80,0.75)) #add axis to figure ax2 = ax1.twinx() #create new axis with same x properties #Get flow data found, results, message = res.getTSData(chan_id,'1D','Q','L') if found: print('found requested data') ax1.plot(res.times,results,color='b',label='Flow - '+chan_id) else: print(message) sys.exit() #Get velocity data found, results, message = res.getTSData(chan_id,'1D','V','L') if found: print('found requested data') ax2.plot(res.times,results,color='r',label='Velocity - '+chan_id) else: print(message) sys.exit() # manage plot ax1.set_xlabel('Time (hours)') ax1.set_ylabel('Flow (m3/s)') ax2.set_ylabel('Velocity (m/s)') ax1.set_title('Example time-series - twin axis') ax1.grid() h1, l1 = ax1.get_legend_handles_labels() h2, l2 = ax2.get_legend_handles_labels() ax1.legend(h1+h2, l1+l2, loc='upper left') plt.show()
This will create a figure that looks like the above.
Long Profile Peak Levels
This also assumes that the data has been loaded as per example 1 above. The long profile data for all channels downstream of FC01.40 will be plotted.
us_chan = 'FC01.40' #upstream channel ds_chan = None #get connectivity between channels error, message = res.LP_getConnectivity(us_chan,ds_chan) if error: print(message) sys.exit() else: print('LP connectivity determined.') print('Get LP static data') error, message = res.LP_getStaticData() if error: print(message) sys.exit() else: print('LP static data retrieved') #create plot fig = plt.figure() #create new figure ax1 = fig.add_axes((0.10, 0.15, 0.85,0.80)) #add axis to figure #plot data # Max WL ax1.plot(res.LP.dist_nodes, res.LP.Hmax,color='r',label = 'Max Water Level') # Bed Level ax1.plot(res.LP.dist_chan_inverts, res.LP.chan_inv,color='brown',linewidth = '3',label = 'Bed Level Level') # manage plot ax1.set_xlabel('Distance (m)') ax1.set_ylabel('Level (mAHD)') ax1.set_title('Example Long Profile - Peak Levels') ax1.grid() ax1.legend(loc='upper right') plt.show()
This will create a figure that looks like the above.
Other Versions
An older version of the library that is compatible with results from the 2013 version of TUFLOW (this is limited to the 1D results) is also available. This is currently undocumented, however, if you would like this please contact support@tuflow.com.