with VTK Python API, add multiple scalars to unstructured grid cells - python

This Python script:
import numpy as np
import vtk
from vtk.util.numpy_support import numpy_to_vtk
# Open a file, and create an unstructured grid.
filename = 'example.vtk'
writer = vtk.vtkUnstructuredGridWriter()
writer.SetFileName(filename)
grid = vtk.vtkUnstructuredGrid()
# Create 3 points
A,B,C = (0,0,0), (0,1,0), (1,0,0)
points = np.array( (A,B,C) )
vtk_points = vtk.vtkPoints()
vtk_points.SetData( numpy_to_vtk(points) )
grid.SetPoints(vtk_points)
# Cells: just 1 triangle
ntriangles = 1
npoints_per_triangle = 3
cells = np.array( [npoints_per_triangle, 0, 1, 2] )
vtk_cells = vtk.vtkCellArray()
id_array = vtk.vtkIdTypeArray()
id_array.SetVoidArray(cells, len(cells), 1)
vtk_cells.SetCells(ntriangles, id_array)
# Cell types: just 1 triangle.
cell_types = np.array( [vtk.VTK_TRIANGLE] , 'B')
vtk_cell_types = numpy_to_vtk(cell_types)
# Cell locations: the triangle is in `cells` at index 0.
cell_locations = np.array( [0,])
vtk_cell_locations = numpy_to_vtk(cell_locations, deep=1,
array_type=vtk.VTK_ID_TYPE)
# Cells: add to grid
grid.SetCells(vtk_cell_types, vtk_cell_locations, vtk_cells)
data = grid.GetCellData()
# Add scalar data to the triangle
data.SetActiveScalars('foo')
foo = np.array( [11.,] )
vtk_foo = numpy_to_vtk(foo)
vtk_foo.SetName("foo")
data.SetScalars(vtk_foo)
# Add other scalar data to the triangle
data.SetActiveScalars('bar')
bar = np.array( [12.,] )
vtk_bar = numpy_to_vtk(bar)
vtk_bar.SetName("bar")
data.SetScalars(vtk_bar)
# Write to file.
writer.SetInput(grid)
writer.Write()
print open(filename).read()
Produce the file:
# vtk DataFile Version 3.0
vtk output
ASCII
DATASET UNSTRUCTURED_GRID
POINTS 3 long
0 0 0 0 1 0 1 0 0
CELLS 1 4
3 0 1 2
CELL_TYPES 1
5
CELL_DATA 1
SCALARS bar double
LOOKUP_TABLE default
12
FIELD FieldData 1
foo 1 1 double
11
But I want CELL_DATA section to be:
CELL_DATA 1
SCALARS foo double
LOOKUP_TABLE default
11
SCALARS bar double
LOOKUP_TABLE default
12
Edit
Looking at the source code (WriteCellData, WriteScalarData and deeper), it seems impossible.

You can add how many arrays you want using AddArray instead of SetActiveScalars
See also http://public.kitware.com/pipermail/vtkusers/2004-August/026366.html
http://www.vtk.org/doc/nightly/html/classvtkCellData-members.html

From what I've read, vtk can't write multiple SCALARS, but can read it. (What a good API!).
I'll continue using the good old pyvtk (which also has the adavange to be readable):
import pyvtk
filename = 'example.vtk'
title = 'Unstructured Grid Example'
points = [[0,0,0],[0,1,0],[0,0,1]]
triangles = [[0,1,2]]
grid = pyvtk.UnstructuredGrid(points, triangle=triangles)
celldata = pyvtk.CellData( pyvtk.Scalars([11.,], name="foo"),
pyvtk.Scalars([12.,], name="bar"))
vtk = pyvtk.VtkData(grid, celldata, title)
vtk.tofile(filename)
print open(filename).read()
Which produce:
# vtk DataFile Version 2.0
Unstructured Grid Example
ASCII
DATASET UNSTRUCTURED_GRID
POINTS 3 int
0 0 0
0 1 0
0 0 1
CELLS 1 4
3 0 1 2
CELL_TYPES 1
5
CELL_DATA 1
SCALARS foo float 1
LOOKUP_TABLE default
11.0
SCALARS bar float 1
LOOKUP_TABLE default
12.0

Related

How do I plot an interaction graph, like a schemaball, from a table showing correlation/interaction data in python?

I've got a table with data from which I'd like to show the interaction in an informative way.
I have counted the interactions between different people, and inputted this in a table, which looks like this:
ideally, I'd like to visualise this data in interesting ways (if you know more, please let me know!). I found these things, and I'd like to create one from this data myself.
I found some tutorials online, however, I can't seem to get it to work as I am unable to input my data the right way in an NX graph: when iterating through the table, I end up attaching wrong ends to eachother or skipping data.
data:
A
B
C
D
E
F
A
x
2
1
3
0
0
B
2
x
0
4
5
1
C
1
0
x
3
0
2
D
3
4
3
x
1
1
E
0
5
0
1
x
1
F
0
1
2
1
1
x
Best-Effort code:
import matplotlib.pyplot as plt
import networkx as nx
import matplotlib
namelist = []
for i in range(0,len(systeem)):
namelist.append(systeem.iloc[i,0])
G=nx.Graph()
G.add_nodes_from(namelist)
weightlist=[]
for i in range(0,len(namelist)):
for j in range(1,len(namelist)):
if int(systeem.iloc[i,j]) > 0:
W=int(systeem.iloc[i,j])
weightlist.append(W)
G.add_edge(namelist[i-1],namelist[j], weight= W)
else:
continue
plt.figure(figsize=(40,40))
pos = nx.circular_layout(G)
cmap = matplotlib.cm.get_cmap('plasma_r')
nx.draw_networkx(G, pos, width=1, node_color="blue", edge_cmap=cmap, with_labels=False)
labels_pos = {name:[pos_list[0], pos_list[1]-0.04] for name, pos_list in pos.items()}
nx.draw_networkx_labels(G, labels_pos, font_size=40, font_family="sans-serif", font_color="#000000", font_weight="bold")
ax = plt.gca()
ax.margins(0.25)
plt.axis("equal")
plt.tight_layout()

Determine number of consecutive identical points in a grid

I have dataframe and grid size is 12*8
I want to calculate the number of consecutive red dots (only in the vertical direction ) and make new column with it (col = consecutive red ) for blue it will be zero
for example
X y red/blue consecutive red
1 1 blue 0
1 3 red 3
1 4 red 3
1 2 blue 0
1 5 red 3
9 4 red 5
[![enter image description here][1]][1]
Already have data for first 3 columns
from sklearn.neighbors import BallTree
red_points = df[df.red/blue== red]
blue_points = df[df.red/blue!= red]
tree = BallTree(red_points[['x','y']], leaf_size=40, metric='minkowski')
distance, index = tree.query(df[['x','y']], k=2)
I am not aware of such algorithm (there may very well be one), but writing the algo isn't that hard (I work with numpy because I'm used to it and because you can easily accelerate with CUDA and port to other data science python tools).
The data (0=blue, 1=red):
import numpy as np
import pandas as pd
# Generating dummy data for testing
ROWS=10
COLS=20
X = np.random.randint(2, size=(ROWS, COLS))
# Visualizing
df = pd.DataFrame(data=X)
bg='background-color: '
df.style.apply(lambda x: [bg+'red' if v>=1 else bg+'blue' for v in x])
The algorithm:
result = np.zeros((ROWS,COLS),dtype=np.int)
for y,x in np.ndindex(X.shape):
if X[y, x]==0:
continue
cons = 1 # consecutive in any direction including current
# Going backwward while we can
prev = y-1
while prev>=0:
if X[prev,x]==0:
break
cons+=1
prev-=1
# Going forward while we can
nxt = y+1
while nxt<=ROWS-1:
if X[nxt,x]==0:
break
cons+=1
nxt+=1
result[y,x]=cons
df2 = pd.DataFrame(data=result)
df2.style.apply(lambda x: [bg+'red' if v>=1 else bg+'blue' for v in x])
And the result:
Please note that in numpy the first coordinate represents the row index (y in your case), and the second the column (x in your case), you can use transpose on your data if you want to swap to x,y.

switch axis for a data cube (fits file)

I've some problems and I could not find any answer to my problem.
I'm trying to create a datacube in python, where the three axis are (RA,DEC,z), that is 2 sky position and red shift.
I think my code for generating the cube works, I define the cube as:
cube = np.zeros([int(size_x),int(size_y),int(Nchannel)])
where x and y are pixel coordinates and the redshift is sliced in channels. Having this cube I'm filling it with intensity of some lines. At the end I define my .fits header as follows:
hdr = fits.Header()
hdr['EQUINOX'] = 2000
hdr['CRPIX1'] = round(size_ra*3600./pix_size/2.)
hdr['CRPIX2'] = round(size_dec*3600./pix_size/2.)
hdr['CRPIX3'] = 0
hdr['CRVAL1'] = ra0
hdr['CRVAL2'] = dec0
hdr['CRVAL3'] = z_min
hdr['CD1_1'] = pix_size/3600.
hdr['CD1_2'] = 0.
hdr['CD2_1'] = 0.
hdr['CD2_2'] = pix_size/3600.
hdr['CTYPE1'] = "RA---TAN"
hdr['CTYPE2'] = "DEC--TAN"
hdr['CTYPE3'] = "Z"
hdr['BUNIT'] = "Jy/pixel"
fits.writeto('cube.fits',cube,hdr,overwrite=True)
And here is the problem, my cube.fits is in the "bad" direction. When I open it using ds9 the z-axis is not the redshift z...
I'm suspecting a bad header, but where can I specify the axis in the fits header?
Cheers
The axes are indeed inverted, FITS uses the Fortran convention (column-major order) whereas Python/Numpy uses the C convention (row-major order).
http://docs.astropy.org/en/latest/io/fits/appendix/faq.html#what-convention-does-astropy-use-for-indexing-such-as-of-image-coordinates
So for your cube you need to define the axes as (z, y, x):
In [1]: import numpy as np
In [2]: from astropy.io import fits
In [3]: fits.ImageHDU(data=np.zeros((5,4,3))).header
Out[3]:
XTENSION= 'IMAGE ' / Image extension
BITPIX = -64 / array data type
NAXIS = 3 / number of array dimensions
NAXIS1 = 3
NAXIS2 = 4
NAXIS3 = 5
PCOUNT = 0 / number of parameters
GCOUNT = 1 / number of groups

Matplotlib: Same title for 8 plots plotted using loop

I have the following code which generates 8 plots. I want to put the phases as titles in each plot. So I have succeded to put the phase on the plot. But instead of taking corresponding phase, it is always taking the last phase to show in each plot. The 8phases.txt file has the following 8 lines which I want to put in each plot -
-1 1 -1
-1 1 1
1 1 1
1 -1 1
-1 -1 -1
1 1 -1
1 -1 -1
-1 -1 1
Here is the code -
import numpy as np
import matplotlib.pyplot as plt
D=12
n=np.arange(1,4)
x = np.linspace(-D/2,D/2, 3000)
I = np.array([125,300,75])
phase = np.genfromtxt('8phases.txt')
I_phase = I*phase
for i in I_phase:
F = sum(m*np.cos(2*np.pi*l*x/D) for m,l in zip(i,n))
f,(ax1,ax2) = plt.subplots(2)
for row in phase:
ax1.plot(x,F,'g')
ax1.set_title(row)
plt.show()
I think your inner-most loop is unnecessary; it is recreating the same plot 8 times and updating the title 8 times with each of the 8 values.
If I understood what you are asking for, I believe this gives the correct results:
...
for index,i in enumerate(I_phase):
F = sum(m*np.cos(2*np.pi*l*x/D) for m,l in zip(i,n))
f,(ax1,ax2) = plt.subplots(2)
ax1.plot(x,F,'g')
ax1.set_title(phase[index])
...
(I would normally use "i" instead of "index", but you had already used "i")

Heat map of binary data using R or Python

I have a binary data set of 0 and 1, where 0 is an absence and 1 is a presence of an event.
A sample of the data set looks like this:
events germany Italy
Rain 0 1
hail 1 0
sunny 0 0
I'd like to get a red and white picture of this data in the form of heat map by reading the data from a file.
Edit: In response to comments below, here is a sample data file (saved on disk as "data.txt"):
Rain 0 0 0 0 1 0 1 0 0 1
Hail 0 1 0 0 0 0 0 1 0 0
Sunny 1 1 1 0 1 0 1 0 1 1
In python, we can read the labels and plot this "heatmap" by:
from numpy import loadtxt
import pylab as plt
labels = loadtxt("data.txt", usecols=[0,],dtype=str)
A = loadtxt("data.txt", usecols=range(1,10))
plt.imshow(A, interpolation='nearest', cmap=plt.cm.Reds)
plt.yticks(range(A.shape[0]), labels)
plt.show()
import pylab as plt
See ?image. With your data
dat <- data.matrix(data.frame(Germany = c(0,1,0), Italy = c(1,0,0)))
rownames(dat) <- c("Rain","Hail","Sunny")
This gets us close:
image(z = dat, col = c("white","red"))
but better handling of axis labels would be nice... Try:
op <- par(mar = c(5,5,4,2) + 0.1)
image(z = dat, col = c("white","red"), axes = FALSE)
axis(side = 1, labels = rownames(dat),
at = seq(0, by = 0.5, length.out = nrow(dat)))
axis(side = 2, labels = colnames(dat), at = c(0,1), las = 1)
box()
par(op)
Which gives
To have the heatmap the other way round, transpose dat (image(z = t(dat), ....)) and make in the axis() calls, change side to 2 in the first and 1 in the second call (and move the las = 1 to the other call. I.e.:
op <- par(mar = c(5,5,4,2) + 0.1)
image(z = t(dat2), col = c("white","red"), axes = FALSE)
axis(side = 2, labels = rownames(dat2),
at = seq(0, by = 0.5, length.out = nrow(dat2)), las = 1)
axis(side = 1, labels = colnames(dat2), at = c(0,1))
box()
par(op)
With reshape and ggplot2 in R
library(reshape)
library(ggplot2)
dat <- data.frame(weather=c("Rain","Hail","Sunny"), Germany = c(0,1,0), Italy = c(1,0,0))
melt.data<-melt(dat, id.vars="weather", variable_name="country")
qplot(data=melt.data,
x=country,
y=weather,
fill=factor(value),
geom="tile")+scale_fill_manual(values=c("0"="white", "1"="red"))
in R try:
library(bipartite)
mat<-matrix(c(0,1,1,0,1,1),byrow=TRUE,nrow=3)
rownames(mat)<-c("Rain","hail","sunny")
colnames(mat)<-c("Germany","Italy")
visweb(mat,type="None")
for red squares and label size control:
visweb(mat,type="None",labsize=2,square="b",box.col="red")
Probably the simplest solution in base R is:
rownames(dat) = dat$weather
heatmap(as.matrix(dat[,2:3]), scale='none')
... assuming that your data frame is called dat. The heatmap is not pretty but it's quick and easy. The first line is not necessary. It only serves to make the weather labels show in the heatmap.

Categories