Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1
  • 2

TOPIC: Matplotlib (pytel scripts)

Matplotlib (pytel scripts) 11 years 10 months ago #6790

  • Lufia
  • Lufia's Avatar
Dear all,

I am a new telemac user and found the very useful selafin reader (parserSELAFIN) and the example scripts for using the selafin reader in combination with matplotlib. Based on the examples I wrote a small script to plot simulation results with tricontourf.

I haven't found any post about matplotlib in this forum so I was wondering if someone else uses matplotlib for visualization?

Maybe it is possible to exchange experiences with matplotlib here.

Regards,

Leo
The administrator has disabled public write access.

Matplotlib (pytel scripts) 11 years 10 months ago #6813

  • ails
  • ails's Avatar
  • OFFLINE
  • Senior Boarder
  • Posts: 140
  • Thank you received: 17
Dear Leo,

Nive work. And you're right, I don't think this topic has been adressed before. In a near future, it might be interesting to open a specific section on Matplotlib.

Matplotlib has been very recently introduced in the openTELEMAC system by HR Wallingford. This is a very promising feature as it will offer a lot of built-in post-processing functionnalities.

Installation
This library is optional and only required for advanced post-processing uses with the PYTHON (Pytel) environment. Matplotlib is often provided on Linux, Windows installation is a bit more complex (Numpy must be previously installed).
The minimal required version of Matplotlib is 1.xx (2D and 3D plots (tricontourf) are not supported by older versions). Both Python 2.6 & 2.7 seems to work fine.

On development...
I must warn users that it is still on development and is only used at this time being for automatic validation purposes. New functionnalities and examples have been very recently added to the trunk and are being tested.

More information
More information about Matplotlib can be found at :
So, feedbacks and plots with Matplotlib are very welcomed.

Best regards,

Fabien

Tips
* Checking your version of Matplotlib
  > python
  import matplotlib
  matplotlib.__version__
If no module matplotlib is found, please refer to the installation procedure of Matplotlib.
The administrator has disabled public write access.

Matplotlib (pytel scripts) 11 years 10 months ago #6868

  • Lufia
  • Lufia's Avatar
Maybe this snippets help new users. They are based on the scripts in the pytel folder.

The first thing we have to do is to import the matplotlib and the pytel modules. First we import some standard python modules

import sys
from os import path
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import tri
import matplotlib.cm as cm

Now we add the path to pytel to be able to import the modules. You will have to change the path (PathToPytel).

sys.path.append(path.join( path.dirname(sys.argv[0]), \
                '/PathToPytel/opentelemac/v6p2/pytel')) 
from utils.files import getFileContent
from parsers.parserSortie import getValueHistorySortie
from parsers.parserSELAFIN import SELAFIN,getValueHistorySLF,parseSLF,\
                                  crossLocateMeshSLF,xyLocateMeshSLF,\
                                  getValuePolylineSLF,subsetVariablesSLF
from parsers.parserStrings import parseArrayPaires

Now we should be able to read selafin files. I don't know all functions of the reader (slf object). Here we read the mesh, I assume that we have a triangular grid.

slf = SELAFIN(filename)

xmin = np.min(slf.MESHX) 
xmax = np.max(slf.MESHX)
ymin = np.min(slf.MESHY)
ymax = np.max(slf.MESHY)
elements = np.dstack((slf.MESHX[slf.IKLE],slf.MESHY[slf.IKLE]))
mesh = np.array(slf.IKLE)
x = slf.MESHX
y = slf.MESHY

Now we can check the values and timesteps
for i,name in enumerate(slf.VARNAMES):
   print "%i   %s" %(i, name)

for i,time in enumerate(slf.tags["times"]):
   print "%i   %s" %(i, time)

At this point I was not sure. I think it is possible to get the values of a timestep i with getValues(i). Then the value can bee chosen by the number of the value (valueNumber).

values = slf.getVALUES(i)
ztri = values[valueNumber]


Now we are able to plot the value ztri and the mesh. First we make a new figure.

fig = plt.figure()
ax=fig.add_subplot(111)

There are different ways to plot the data. The best choice is to use the triplotcontourf function. We can define the levels of the plot.

zmintri = ztri.min()
zmaxtri = ztri.max()

nlevels = 15
levels = np.arange(zmintri,zmaxtri,(zmaxtri - zmintri)/nlevels)
triplotcontourf = plt.tricontourf(x,y,mesh,ztri,levels)
plt.colorbar()

Plotting the mesh can be done by defining polygons ( which is very slow) or with triplot (faster).

plt.triplot(x, y, mesh, 'k-',alpha= 0.2)


Velocities are plotted with quiver. Here we assume that the velocities are the first two entries of values. (See in the pytel scripts how the velocity can be normalized to improve the quality and get a nice plot)

u = values[0]
v = values[1]
cs = plt.quiver(x,y,u,v)

Now it is time to set the limits of the axis and plot our file.

ax.set_xlim(xmin,xmax)
ax.set_ylim(ymin,ymax)
ax.axis('equal')
plt.show()
plt.close()

Hope this helps new matplotlib users.
The administrator has disabled public write access.

Matplotlib (pytel scripts) 9 years 5 months ago #17261

  • cyamin
  • cyamin's Avatar
  • OFFLINE
  • openTELEMAC Guru
  • Posts: 997
  • Thank you received: 234
Hello,

I am trying to follow the example given here so as to start using python as a pre/post processing tool. I have managed to make it work but the code fails at this step:
elements = np.dstack((slf.MESHX[slf.IKLE],slf.MESHY[slf.IKLE]))
AttributeError: SELAFIN instance has no attribute 'IKLE'

I have no experience with python and I don't understand the reason why it fails.

Any help would be appreciated.

Regards,
Costas
The administrator has disabled public write access.

Matplotlib (pytel scripts) 9 years 5 months ago #17263

  • sebourban
  • sebourban's Avatar
  • OFFLINE
  • Administrator
  • Principal Scientist
  • Posts: 814
  • Thank you received: 219
it is slf.IKLE2 (or slf.IKLE3) depending.
The administrator has disabled public write access.
The following user(s) said Thank You: cyamin

Matplotlib (pytel scripts) 7 years 10 months ago #24959

  • Watermotion.eu
  • Watermotion.eu's Avatar
sebourban wrote:
it is slf.IKLE2 (or slf.IKLE3) depending.

May I ask depending on what? Which difference do they make?

Both are present in my selafin object:

>>> print slf.__dict__.keys()
['TITLE', 'fole', 'file', 'MESHX', 'MESHY', 'CLDUNITS', \
'CLDNAMES', 'NPOIN2', [b]'IKLE3'[/b], 'alterZnames', 'IPOB3', \ 
'IPOB2', 'VARUNITS', 'neighbours', 'NDP2', 'NDP3', 'NBV2',\
'NPLAN', 'NBV1', 'VARINDEX', 'tags', 'NVAR', 'IPARAM', \
'DATETIME', 'edges', [b]'IKLE2'[/b], 'NPOIN3', 'NELEM3', \
'NELEM2', 'tree', 'VARNAMES']

and the manual (release 7.0, appenidx 3) only mentions a single variable name 'IKLE'.
Thanks
The administrator has disabled public write access.

Matplotlib (pytel scripts) 11 years 7 months ago #8257

  • tivincent
  • tivincent's Avatar
hello !

I am a new user of telemac softwares.
I would like to use Python and "pytel" module for postprocessing.

Is there any examples scripts to download somewhere ?

thanks!
Vincent
The administrator has disabled public write access.

Matplotlib (pytel scripts) 11 years 7 months ago #8274

  • Lufia
  • Lufia's Avatar
You can just copy the lines of my earlier snippet into a file. You can get the variable number by adding a line to read the input from the command line

for i,name in enumerate(slf.VARNAMES):
   print "%i   %s" %(i, name)
valueNumber = input("Which Value to plot (number)?:")
print "You entered: %i \n" %valueNumber

and the timestep with the following

for i,time in enumerate(slf.tags["times"]):
   print "%i   %s" %(i, time)
timestep = input("Which timestep to plot (number)?:")
print "You entered %i \n" %timestep

One problem is that it is not so easy to do an interactive plot which allows to change the variable or timestep with matplotlib. It is possible but a more complex.
The administrator has disabled public write access.

Matplotlib (pytel scripts) 11 years 3 months ago #9849

  • Lufia
  • Lufia's Avatar
Thought this morning it is a good idea to make a small hack to be able to plot the boundary conditions with matplotlib. B)


"""Simple hack to plot boundary conditions with matplotlib


    we parse the cli file to plot the boundary conditions and the selafin
    file to get the boundary points. Plotting the whole mesh can be a pain
    for large meshes so we only plot the boundary nodes

 

    Warning! This is a first hack and must be checked!

    ToDo:   - use numpy 
            - not sure it's not clear if n / k allways works? 
            - naming labels544 was a stupid name but it is better to
              distinguish between different boundar conditions since it costs
              to plot with matplotlib.annotate
            - plot also different boundary conditions
      
"""


import sys
#Import python part
from os import path
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import tri
import matplotlib.cm as cm

#Get the telemac stuff
sys.path.append(path.join( path.dirname(sys.argv[0]), \
        '...path_to.../telemac/v6p2r1/pytel')) 
from utils.files import getFileContent
from parsers.parserSortie import getValueHistorySortie
from parsers.parserSELAFIN import SELAFIN,getValueHistorySLF,parseSLF,\
                                  crossLocateMeshSLF,xyLocateMeshSLF,\
                                  getValuePolylineSLF,subsetVariablesSLF
from parsers.parserStrings import parseArrayPaires


def readCliFile(clifilename):
    """Read a Cli file

    We store the data of all boundary nodes in a list, numpy might be faster
    but until now there was no speed issue

    Some small remakrs on the boundary values

    LIHBOR      condition for depth h:
        1 -- wave
        2 -- no flow / closed
        4 -- free depth        
        5 -- prescribed depth
    
    LIUBOR and LIVBOR       velocity or flow rate condition:
        1 -- wave
        2 -- friction / slip
        3 -- 
        4 -- free velocity
        5 -- prescribed flow rate
        6 -- prescribed velocity
    
    LIBTOR      condition for tracer
        1 --
        2 -- no flow / closed
        3 --
        4 -- free tracer
        5 -- prescribed tracer
        6 --

    HBOR / UBOR / VBOR      values for the boundary 

    N       Total number of boundary points (unstructured mesh) or something
            else    

    K       global boundary node number point number or node colour

    """

    
    lihbor = []
    liubor = []
    livbor = []
    hbor = []
    ubor = []
    vbor = []
    aubor = []
    litbor = []
    tbor = []
    atbor = []
    btbor = []
    n = []
    k = []

    fobCli = open(clifilename)

    for line in fobCli:
        values = line.split()

        if len(values) >= 13:
            lihbor.append(values[0])
            liubor.append(values[1])
            livbor.append(values[2])
            hbor.append(values[3])
            ubor.append(values[4])
            vbor.append(values[5])
            aubor.append(values[6])
            litbor.append(values[7])
            tbor.append(values[8])
            atbor.append(values[9])
            btbor.append(values[10])
            n.append(values[11])
            k.append(values[12])

        else:
            print "warning! cli file line length was %d" %len(values)
            break

    cli = [lihbor,liubor,livbor,hbor,ubor,vbor,aubor,litbor,tbor,atbor,btbor,n,k]


    return cli
    

cli = readCliFile("geo_donau.cli")
slf = SELAFIN("geo_donau.slf")
xMesh = slf.MESHX
yMesh = slf.MESHY

nofBoundaryNodes = len(cli[0])

x = []
y = []

xlabel544 = []
ylabel544 = []
labels544 = []


for i in range(nofBoundaryNodes):
    ii = int(cli[11][i]) -1
    x.append(xMesh[ii])
    y.append(yMesh[ii])
    h = cli[0][i]
    v = cli[1][i]
    u = cli[2][i]

    #make 544 labe
    if (h != "2") or (v != "2") or (u != "2"):
        l = 'node: %d h: %s, v: %s, u %s' %(ii+1,h,v,u,)
        labels544.append(l)
        xlabel544.append(xMesh[ii])
        ylabel544.append(yMesh[ii])

plt.scatter(x,y)


for i,label in enumerate(labels544):
    plt.annotate(
        label, 
        xy = (xlabel544[i], ylabel544[i]), xytext = (-20, 30),
        textcoords = 'offset points', ha = 'right', va = 'bottom',
        bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
        arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'))

plt.show()
The administrator has disabled public write access.

Matplotlib (pytel scripts) 11 years 3 months ago #9852

  • Lufia
  • Lufia's Avatar
Plotting only parts of a mesh using the mask option. Here used to plot elements that are inside a box or on the boundary (boundary option must be improved)

#go through the mesh and mask elements 
mesh = np.array(slf.IKLE)
maskMesh = np.zeros(len(mesh))
for i in range(len(mesh)):
    #plot only mesh inside a box x0,y0 lower left corner dx/dy length
    x0 = 5300
    y0 = 4160
    dx = 200
    dy = 200

    minX = min(xMesh[mesh[i][0]],xMesh[mesh[i][1]],xMesh[mesh[i][2]])
    maxX = max(xMesh[mesh[i][0]],xMesh[mesh[i][1]],xMesh[mesh[i][2]])
    minY = min(yMesh[mesh[i][0]],yMesh[mesh[i][1]],yMesh[mesh[i][2]])
    maxY = max(yMesh[mesh[i][0]],yMesh[mesh[i][1]],yMesh[mesh[i][2]])

    if ((x0 < minX < (x0 + dx)) and   (y0 < maxY < (y0 + dy))):
        maskMesh[i] = 0.0
    else:
        maskMesh[i] = 1.0

    #search after node id's this helps if you like to plot the boundary
    """
    minId =  min(mesh[i][0],mesh[i][1],mesh[i][2])
    if (minId < nofBoundaryNodes):
        maskMesh[i] = 0.0
    else:
        maskMesh[i] = 1.0
    """

Zm = ma.masked_where(maskMesh > 0.5, maskMesh)
plt.triplot(xMesh, yMesh, mesh,'k-',alpha= 0.2,mask=Zm)
The administrator has disabled public write access.
  • Page:
  • 1
  • 2

The open TELEMAC-MASCARET template for Joomla!2.5, the HTML 4 version.