How to compute contour for a triangular grid with matplotlib - python

I have a set of x, y, z data but with a constraint on x and y such as y < x :
I would like to draw contours of these data on an 2D plot. I first interpolated the data with the scipy.interpolate.SmoothBivariateSpline class and then I drew contours. But in order to do that, I defined a rectangular grid from the range of x and y and I used that grid for the interpolation and the contours plot. How can I avoid to use a rectangular grid ? Does it exist an equivalent of scipy.meshgrid function for a triangular grid which can be used to plot contours ?
At the end I obtain the following plot. I added a filled triangle to hide the not relevant data.
But if you look at the result of the interpolation, the splines diverge where there is no data. It is not a problem as I do not use it but I would prefer to use a grid corresponding to the constraint on x and y :

Related

Integration of a curve generated using matplotlib

I have generated a graph using basic function -
plt.plot(tm, o1)
tm is list of all x coordinates and o1 is a list of all y coordinates
NOTE
there is no specific function such as y=f(x), rather a certain y value remains constant for a given range of x.. see figure for clarity
My question is how to integrate this function, either using the matplotlib figure or using the lists (tm and o1)
The integral corresponds to computing the area under the curve.
The most easy way to compute (or approximate) the integral "numerically" is using the rectangle rule which is basically approximating the area under the curve by summing area of rectangles (see https://en.wikipedia.org/wiki/Numerical_integration#Quadrature_rules_based_on_interpolating_functions).
Practically in your case, it quite straightforward since it is a step function.
First, I recomment to use numpy arrays instead of list (more handy for numerical computing):
import matplotlib.pyplot as plt
import numpy as np
x = np.array([0,1,3,4,6,7,8,11,13,15])
y = np.array([8,5,2,2,2,5,6,5,9,9])
plt.plot(x,y)
Then, we compute the width of rectangles using np.diff():
w = np.diff(x)
Then, the height of the same rectangles (multiple possibilities exist):
h = y[:-1]
Here I chose the 2nd value of each two successive y values. the top right angle of rectangle is on the curve. You can choose the mean value of each two successive y values h = (y[1:]+y[:-1])/2 in which the middle of the top of the rectangle coincide with the curve.
Then , you will need to multiply and sum:
area = (w*h).sum()

How to extract and store x, z coordinates associated to a specific y coordinate on a UnstructuredGrid in Python?

Starting from an image I did some processing (like thresholding) and I obtained its representation as UnstructuredGrid using VTK and PyVista. I would like to create an array of shape (n, 3) filled with x, y, z coordinates associated with a specific y coordinate of which I know the value, but not the position of corresponding cells in the UnstructuredGrid.
I didn't understand too well what an UnstructuredGrid is so I don't know how to access and extract specific point values and coordinates.
My goal is to create a list of coordinates of the front face of the image, that will be the input for a ray tracing algorithm.
Most of the tooling you need is the UnstructuredGrid.extract_cells() filter, which lets you select cells based on a boolean mask array or integer indices. Building such a mask is fairly easy if you compare the y coordinates of cell centers with the specific value you are looking for:
import pyvista as pv
from pyvista.examples import download_puppy
# example data
mesh = download_puppy().threshold(80)
# example point coordinates: use middle cell's center
mesh_cell_centers = mesh.cell_centers()
x0, y0, z0 = mesh_cell_centers.points[mesh.n_cells // 2, :]
# plot example mesh
def plot_puppy():
"""Helper function to plot puppy twice."""
pl = pv.Plotter()
pl.background_color = 'lightblue'
pl.add_mesh(mesh, scalars='JPEGImage', rgb=True)
pl.add_bounding_box()
pl.camera.tight(padding=0.1)
return pl
plotter = plot_puppy()
plotter.show()
# extract cells with center y coordinate same as y0
indices_to_keep = mesh_cell_centers.points[:, 1] == y0 # boolean mask
# for inexact matching we could use np.isclose(mesh_cell_centers.points[:, 1], y0)
subset = mesh.extract_cells(indices_to_keep)
# visualize extracted cell centers with points
plotter = plot_puppy()
plotter.add_points(subset, color='red', render_points_as_spheres=True)
plotter.show()
The x0, y0, z0 in my example are the coordinates of the "middle" cell left after thresholding, in your actual use case you need something like y0 = mesh_cell_centers.points[:, 1].min() if you want to match the cells with the lowest y coordinate. In any case calling cell_centers() is an important step to obtain the cell coordinates as points of an auxiliary mesh.
Here's what the thresholded puppy looks like:
The thresholding turns the original UniformGrid image into an UnstructuredGrid of scattered pixels. Starting from a UniformGrid is also useful for matching y coordinates exactly using ==, but even without this we could use np.isclose for approximate matching of float values (as I pointed out in a comment).
Here's the second image, where red spheres are superimposed on the puppy at positions that were matched in the mesh subset (another UnstructuredGrid):
This agrees with our expectations: we only see cells with a specific y coordinate, and we only see cells where the puppy is not transparent.
Since you need the coordinates of the corresponding cells, you can just use subset.cell_centers().points for an (n, 3)-shaped array, or pick out the x and z coordinates with subset.cell_centers().points[:, [0, 2]] with shape (n, 2).

Mapping the grid values to their physical ones

I am doing a cosmological simulation. I have a contour plot which represents a density field. The y and x axes have values of grid points. I work with Python. What I want is, to put things in Mpc/h (distance unit). The size of my simulation box is 100 Mpc/h, so the range should be from 0 to 100. And I should modify both my x and y axes from grid points to Mpc/h.
I try to find a function to map my grid values (from 0 to 128) to my physical ones (0-100). Which is this function and how is it applied? Could someone help me with that please?

Python - Problems contour plotting offset grid of data

My data is regularly spaced, but not quite a grid - each row of points is slightly offset from the one below.
The data is in the form of 3 1D arrays, x, y, z, with each index corresponding to a point. It is smoothly varying data - approximately Gaussian.
The point density is quite high. What is the best way to plot this data?
I tried meshgrid, but it gives me some bad contours through regions that have no data points near the contour's value.
I have tried rbf interpolation according to this post:
Python : 2d contour plot from 3 lists : x, y and rho?
but this just gives me nonsense - all the contours are on one edge - does not reflect the data at all.
Any other ideas for what I can try. Maybe I should be using some sort of nearest neighbour interpolation? Here is a picture of about a 1/4 of my data points: http://imgur.com/a/b00R6
I'm surprised it is causing me such difficulty - it seems like it should be fairly easy to plot.
The easiest way to plot ungridded data is probably tricontour or tricontourf (a filled tricontour plot).
Having 1D arrays of the x, y and z coordinates x, y and z, you'd simply call
plt.tricontourf(x,y,z, n, ...)
to obtain n levels of contours.
The other quick method is to interpolate on a grid using matplotlib.mlab.griddata to obtain a regular grid from the irregular points.
Both methods are compared in an example on the matplotlib page:
Tricontour vs. griddata
Found the answer: needed to rescale my data.

Plotting a 3D Cylindrical Surface plot in Python

I am trying to create a cylindrical 3D surface plot using Python, where my independent variables are z and theta, and the dependent variable is radius (i.e., radius is a function of vertical position and azimuth angle).
So far, I have only been able to find ways to create a 3D surface plot that:
has z as a function of r and theta
has r as a function of z, but does not change with theta (so, the end product looks like a revolved contour; for example, the case of r = sin(z) + 1 ).
I would like to have r as a function of z and theta, because my function will produce a shape that, at any given height, will be a complex function of theta.
On top of that, I need the surface plot be able to have (but does not have to have, depending on the properties of the function) an open top or bottom. For example, if r is constant from z = 0 to z = 1 (a perfect cylinder), I would want a surface plot that would only consist of the side of the cylinder, not the top or bottom. The plot should look like a hollow shell.
I already have the function r defined.
Thanks for any help!
Apparently, after some trial and error, the best/easiest thing to do in this case is to just to convert the r, theta, and z data points (defined as 2D arrays, just like for an x,y,z plot) into cartesian coordinates:
# convert to rectangular
x = r*numpy.cos(theta)
y = r*numpy.sin(theta)
z = z
The new x,y,z arrays can be plotted just like any other x,y,z arrays generated from a polynomial where z is a function of x,y. I had originally thought that the data points would get screwed up because of overlapping z values or maybe the adjacent data points would not be connected correctly, but apparently that is not the case.

Categories