Related
I work on a crowd simulation, and I tried to get a simple representation at a given time like this : new to the site so here is the link. I work with Spyder and the code works wonderfully when I display the image in ipython with plt.show(), but when i try to save the images with plt.savefig() (I removed plt.show() prior to that, not the issue) i ended up with blank images. Here is the code :
p,v,t = resolve() #p[c][i] is the position vector of individual i at time t[c]
N = len(t) # number of instant
n = len(m) # number of individual
murs_x = [w[0] for w in W] # wall points x coordinates
murs_y = [w[1] for w in W] # wall points y coordinates
conv = 39.3701 #inch/m
L = longueur*conv/50 # width of figure
H = (largeur + decalage)*conv/50 # height of figure
for c in range(N):
fig1 = plt.figure(num="aff",figsize = (L,H), dpi = 200) # arbitrary num, allow to recreate the figure
ax = fig1.add_axes([1,1,1,1])
ax.set_axis_off() # visual purpose
ax.set_frame_on(False) # visual purpose
ax.axis([0,longueur,0,largeur+decalage])
ax.scatter(murs_x,murs_y,s=0.01,marker='.')
for i in range(n):
if p[c][i][1] <= (largeur + r[i]): # presence condition for individual i
ax.add_artist(plt.Circle((p[c][i][0], p[c][i][1]), r[i], alpha=1))
# drawing of the circle representing individual i
# here is the plt.show(), unused
fig1.savefig(str(c)+".png") # trying to save instant c visual represention
fig1.clf()
Moreover, without the 2 lines for visual purposes, the images are not totally blank but rather like this : another link.
I first attempted to use matplotlib.animation to create a video, however i had the same issue of a blank video with 2 cropped zeros in the upper right corner. I suppose that the issue is linked to the artist class (I had better results using scattered points instead of circles to represent each individual) but I am a beginner and do not know how to handle it precisely. At least the size of the image is the one expected one.
Thanks for reading this.
I've wrote a code to produce cylinder objects using vtk in python. This code works fine where it produces a 3D scene where i can zoom or turn around the cylinders which i have been made. The problem is i want to export this rendered scene to paraview to view and save it for later works. How can i do this?
Here is the code that produce a Y-shape with cylinders:
import vtk
import numpy as np
'''
Adding multiple Actors to one renderer scene using VTK package with python api.
Each cylinder is an Actor with three input specifications: Startpoint, Endpoint and radius.
After creating all the Actors, the preferred Actors will be added to a list and that list will be our input to the
renderer scene.
A list or numpy array with appropriate 3*1 shape could be used to specify starting and ending points.
There are two alternative ways to apply the transform.
1) Use vtkTransformPolyDataFilter to create a new transformed polydata.
This method is useful if the transformed polydata is needed
later in the pipeline
To do this, set USER_MATRIX = True
2) Apply the transform directly to the actor using vtkProp3D's SetUserMatrix.
No new data is produced.
To do this, set USER_MATRIX = False
'''
USER_MATRIX = True
def cylinder_object(startPoint, endPoint, radius, my_color="DarkRed"):
colors = vtk.vtkNamedColors()
# Create a cylinder.
# Cylinder height vector is (0,1,0).
# Cylinder center is in the middle of the cylinder
cylinderSource = vtk.vtkCylinderSource()
cylinderSource.SetRadius(radius)
cylinderSource.SetResolution(50)
# Generate a random start and end point
# startPoint = [0] * 3
# endPoint = [0] * 3
rng = vtk.vtkMinimalStandardRandomSequence()
rng.SetSeed(8775070) # For testing.8775070
# Compute a basis
normalizedX = [0] * 3
normalizedY = [0] * 3
normalizedZ = [0] * 3
# The X axis is a vector from start to end
vtk.vtkMath.Subtract(endPoint, startPoint, normalizedX)
length = vtk.vtkMath.Norm(normalizedX)
vtk.vtkMath.Normalize(normalizedX)
# The Z axis is an arbitrary vector cross X
arbitrary = [0] * 3
for i in range(0, 3):
rng.Next()
arbitrary[i] = rng.GetRangeValue(-10, 10)
vtk.vtkMath.Cross(normalizedX, arbitrary, normalizedZ)
vtk.vtkMath.Normalize(normalizedZ)
# The Y axis is Z cross X
vtk.vtkMath.Cross(normalizedZ, normalizedX, normalizedY)
matrix = vtk.vtkMatrix4x4()
# Create the direction cosine matrix
matrix.Identity()
for i in range(0, 3):
matrix.SetElement(i, 0, normalizedX[i])
matrix.SetElement(i, 1, normalizedY[i])
matrix.SetElement(i, 2, normalizedZ[i])
# Apply the transforms
transform = vtk.vtkTransform()
transform.Translate(startPoint) # translate to starting point
transform.Concatenate(matrix) # apply direction cosines
transform.RotateZ(-90.0) # align cylinder to x axis
transform.Scale(1.0, length, 1.0) # scale along the height vector
transform.Translate(0, .5, 0) # translate to start of cylinder
# Transform the polydata
transformPD = vtk.vtkTransformPolyDataFilter()
transformPD.SetTransform(transform)
transformPD.SetInputConnection(cylinderSource.GetOutputPort())
# Create a mapper and actor for the arrow
mapper = vtk.vtkPolyDataMapper()
actor = vtk.vtkActor()
if USER_MATRIX:
mapper.SetInputConnection(cylinderSource.GetOutputPort())
actor.SetUserMatrix(transform.GetMatrix())
else:
mapper.SetInputConnection(transformPD.GetOutputPort())
actor.SetMapper(mapper)
actor.GetProperty().SetColor(colors.GetColor3d(my_color))
return actor
def render_scene(my_actor_list):
renderer = vtk.vtkRenderer()
for arg in my_actor_list:
renderer.AddActor(arg)
namedColors = vtk.vtkNamedColors()
renderer.SetBackground(namedColors.GetColor3d("SlateGray"))
window = vtk.vtkRenderWindow()
window.SetWindowName("Oriented Cylinder")
window.AddRenderer(renderer)
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(window)
# Visualize
window.Render()
interactor.Start()
if __name__ == '__main__':
my_list = []
p0 = np.array([0, 0, 0])
p1 = np.array([0, 10, 0])
p2 = np.array([7, 17, 0])
p3 = np.array([-5, 15, 0])
my_list.append(cylinder_object(p0, p1, 1, "Red"))
my_list.append(cylinder_object(p1, p2, 0.8, "Green"))
my_list.append(cylinder_object(p1, p3, 0.75, "Navy"))
render_scene(my_list)
I have multiple actors where all of them are rendered together in one render scene, can i pass each actor into a vtk.vtkSTLWriter? this seems not working!
What you're looking for is subclasses of the vtkExporter class which, as per the linked doco:
vtkExporter is an abstract class that exports a scene to a file. It is very similar to vtkWriter except that a writer only writes out the geometric and topological data for an object, where an exporter can write out material properties, lighting, camera parameters etc.
As you can see from the inheritance diagram of the class there's about 15 classes that support exporting such a scene into a file that can be viewed in appropriate readers.
IMHO the one you'll have the most luck with is the vtkVRMLExporter class as it's a fairly common format. That being said I don't believe Paraview supports VRML files (at least based on some pretty ancient posts I've found) but I'm pretty sure MayaVi does.
Alternatively you could, as you mentioned, export objects into STL files but STL files simply contain triangle coordinates and info on how they connect. Such files cannot possibly describe info re the scene such as camera or lighting information. Also last I checked a single STL file can only contain a single object so your three cylinders would end up being a merged object so its probably not what you want.
I added these codes and it created a VRML file from my rendered scene.
exporter = vtk.vtkVRMLExporter()
exporter.SetRenderWindow(window)
exporter.SetFileName("cylinders.wrl")
exporter.Write()
exporter.Update()
Environment:
Python: 3.6.6
pyglet version: 1.3.2
Code base:
abstract_model.py
import pyglet
def get_texture_group(file, order_group_index):
texture = pyglet.image.load(file).texture
order_group = pyglet.graphics.OrderedGroup(order_group_index)
return pyglet.graphics.TextureGroup(texture, order_group)
class AbstractModel(object):
def _create_as_vertex(self):
v_x = self.cell_data.get("x") * 32
v_y = self.cell_data.get("y") * -1 * 32
texture_group = self.map_type_iamge.get(self.cell_data.get("t"))
x_offset = self.x_offset * self.scale
x, y, z = v_x + x_offset, v_y, self.z
x_ = (texture_group.texture.width * self.scale + x_offset + v_x)
y_ = (texture_group.texture.height * self.scale + v_y)
tex_coords = ('t2f', (0, 0, 1, 0, 1, 1, 0, 1))
self.vertices = self.batch.add(
4, pyglet.gl.GL_QUADS,
texture_group,
('v3f', (x, y, z,
x_, y, z,
x_, y_, z,
x, y_, z)),
tex_coords)
def _animate(self, dt):
# lets assume that I have list of pyglet.graphics.TextureGroup
# and they should somehow be drawn one after other
print("I need change image. dt=", dt, self)
pyglet.clock.schedule_once(self._animate, 1)
ground3d.py
import os
import pyglet
import settings
from models import abstract_model
GROUND_DIR = os.path.join(settings.STATIC_DIR, "ground")
order_group_index = 0
map_type_iamge = {
1: abstract_model.get_texture_group(os.path.join(GROUND_DIR, "w1.png"), order_group_index),
2: abstract_model.get_texture_group(os.path.join(GROUND_DIR, "t1.png"), order_group_index),
1001: abstract_model.get_texture_group(os.path.join(GROUND_DIR, "t1_direction.png"), order_group_index),
}
class Ground3D(abstract_model.AbstractModel):
def __init__(self, cell_data, batch):
self.batch = batch
self.cell_data = cell_data
self.map_type_iamge = map_type_iamge
self.scale = 1
self.x_offset = 0
self.z = 0
self.entity = None
self._create_as_vertex()
pyglet.clock.schedule_once(self._animate, 1)
Explanation:
I have models(just flat rect for an example) which should be placed on 3 dimensions. And these models should be animated, like picture_1, after second picture_2, ... etc.
As I understood from my previous question using pyglet.sprite.Sprite() in 3D batch is not a good idea.
Question:
How I can change pictures(using TextureGroup or any other approaches) on self.vertices?
Or which arroach/classes I use use to implement it. I can't find any examples for such (as for my simple vision) usual case as animation for some flat models in 3 dimensions.
There are many example about rotating/moving/resizing of vertices, but how to build a correct question(is animation aspect) for getting answer in google - I don't know.
PS: If you, reader, have any usefull links on this subject(for pyglet or just for OpenGL) I would be very appreciated you share this link(s) in comment.
Texture coordinates.
You should have a single texture atlas for all frames of all different things that are animated ever.
Preferably, everything should have same animation speed and same amount of frames all the time.
Let's say there's two sprites that have 2 frames for entire animation, and they are stored in 64x64 texture atlas. (EDIT: sorry for ambiguity, 64x64 PIXELS, just because it could imply that we have 64x64 tile atlas, same everywhere else where I mention this)
Now, you need to have a global timer with global value which indicates current animation frame, not game frame. It should be independent of framerate.
Said value should be updated every once in a while at your desired speed like this:
current_frame = (current_frame + 1) % animation_length
Since we have 2 frames in this example, it will turn out like this:
# init
animation_length = 2
current_frame = 0
# updates:
current_frame = (0 + 1) % 2 # 1 % 2 -> 1
current_frame = (1 + 1) % 2 # 2 % 2 -> 0
...
Now, you need to update UV's of all your sprites only when the frame changes.
UV's start from left right and go from 0 to 1 (as far as I remember, for the sake of this example, they do, shhh).
Since we have 2 frames each, we can calculate "tiles" in the UV coordinates like this:
tile_width = 1.0 / frames # 2 frames each, width will be 0.5
tile_height = 1.0 / sprites # 2 sprites each, height will be 0.5 too, perfect
Now, on first frame, you generate your UV's like normal, you just take vertical ID or something, and use tile_height * sprite_id to get current V coordinate, and your U is calculated like tile_width * current_frame.
This assumes that you already have sprite batching so what you do is go over every sprite on update, and basically just recalculate new UV's with new frame, meaning all sprites change their frame to the next one, yay!
If you want to have systems that are independent of eachother, say, very slow animations for some, and faster for others, you'll need different sprite batches or proper calculation on from where to where you need to update UV's in vertex buffer array. Everything else is exactly the same, except now current_frame won't be global but rather contained, preferebly in some list or separate object that manages timers for animations.
You don't need to change anything in your shaders, they just need right UV's for the frames and you're set.
By the way, this is very basic, you could apply some logic yourself so you could instead have 16x16 grid of 32x32 pixels in your texture, each line of sprites having 4 different animations, these could be either sprite's states (attack, run, etc), but how you do it is entirely on you, most importantly, get it to work. Goodluck.
But if you do it the way I said, then state will be another integer, and UV for state, assuming all states have exactly the same width, it would be like this:
state_width = 1 / states
tile_width = 1 / (states * frames_per_state)
U = state_width * current_state + tile_width * current_frame
Now, one issue arises, player could start his animation at the last attack frame.
It's normal, entities with actions should all have individual timers, what I described above, is for tons of sprites that are just background, like grass. Now when you divided it up, you could have a proper way to reset current frame to 0 when new state is assigned.
If your entities are objects, you could write proper methods that recalculate UV's every time you rebuild the sprite batch using those sprites, and then timers itselves could be contained in objects.
We need to draw something? Check animation state, has it changed, no? Send UV's that were calculated before, otherwise, wait a bit, we need to recalculate, only then add those to VBO, and well, render your thing, in the end, it will appear as if you have animations, even though really, it's just a simple, but great UV manipulation.
Goodluck.
I have a bit of code that draws an array of lines (32X32 grid). The actual code that draws it starts from #Nested loop to draw anti-aliased lines in a 32X32 grid. Because I have a patch within it that has lines of different orientation, the codes is a few lines long.
At the moment, I have a .draw() at the end of the nested loop that draws my array.
It doesn't seem like a good way to do this.
Is there a way to create a variable for this entire nested loop so i can call it as and when I want? For instance myStim.draw()
# Import what is needed
import numpy as np
from psychopy import visual, event, core, logging
from math import sin, cos
import random, math
# Create space variables and a window
lineSpaceX = 0.55
lineSpaceY = 0.55
patch_orientation = 45 # zero is vertical, going anti-clockwise
surround_orientation = 90
#Jitter values
g_posJitter = 0.05 #gaussian positional jitter
r_posJitter = 0.05 #random positional jitter
g_oriJitter = 5 #gaussian orientation jitter
r_oriJitter = 5 #random orientation jitter
#Region where the rectangular patch would appear
x_rand=random.randint(6,13) #random.randint(Return random integers from low (inclusive) to high (inclusive).
y_rand=random.randint(6,16)
#rectangular patch dimensions
width=15
height=12
message = visual.TextStim(win,pos=(0.0,-12.0),text='...Press SPACE to continue...')
# Initialize clock to record response time
rt_clock = core.Clock()
#Nested loop to draw anti-aliased lines in a 32X32 grid
for x in xrange(1,33): #32x32 grid.
for y in xrange(1,33):
##Define x & y value (Gaussian distribution-positional jitter)
x_pos = (x-32/2-1/2 )*lineSpaceX + random.gauss(0,g_posJitter) #random.gauss(mean,s.d); -1/2 is to center even-numbered stimuli; 32x32 grid
y_pos = (y-32/2-1/2 )*lineSpaceY + random.gauss(0,g_posJitter)
if (x >= x_rand and x < x_rand+width) and (y >= y_rand and y < y_rand+height): # note only "=" on one side
Line_Orientation = random.gauss(patch_orientation,g_oriJitter) #random.gauss(mean,s.d) - Gaussian func.
else:
Line_Orientation = random.gauss(surround_orientation,g_oriJitter) #random.gauss(mean,s.d) - Gaussian func.
#stimOri = random.uniform(xOri - r_oriJitter, xOri + r_oriJitter) #random.uniform(A,B) - Uniform func.
visual.Line(win, units = "deg", start=(0,0), end=(0.0,0.35), pos=(x_pos,y_pos), ori=Line_Orientation, autoLog=False).draw() #Gaussian func.
frameN = 0
for frameN in range(80): #for exactly 80 frames; 1 frame = 16.67ms on the 1920 x 1080 monitor
if frameN == 0:
rt_clock.reset() # set reaction time clock to 0
message.draw()
win.flip()# display stimulus
frameN = frameN + 1
keys = event.waitKeys(keyList=['space', 'escape','q']) #create key list response
# handle key responses
if len(keys)>0:
rt = rt_clock.getTime()
if keys == ['space']:
event.clearEvents()
break
else:
print 'Stopped Early'
win.close()
core.quit()
print x_rand, y_rand
print keys, rt #display response and reaction time on screen output window
It's not a variable you want, but a function.
The way you are currently doing things (via visual.Line(...).draw()) is very inefficient. You're creating a new line on very iteration, just to draw it once, and not storing a reference to it. A much more time-efficient scheme is to create just a single line object instance, referenced with a variable name, and then on every iteration, simply update its attributes (orientation etc), before drawing it.
An alternative would be to create multiple line object instances once, but store each in a list. Then drawing them again as required is a simple matter of:
for line_instance in line_list:
line_instance.draw()
I am a new Python user and would like to do some simple image processing. Essentially I will have a dynamic medical image - a series of 2D images at different time points which I would like to store as a 3D array. Due to the nature of the scanning technique there is likely to be occasional patient motion during certain imaging frames which makes the data unusable. I would like to delete such frames and recast the array - new dimensions (n-1, 256, 256). After deletion of the frame I would like to update the image display. What is the best way to achieve this goal? Here is the skeleton code I have so far:
import dicom
import numpy as np
import pylab
from matplotlib.widgets import Slider, Button
ds = dicom.read_file("/home/moadeep/Dropbox/FS1.dcm")
#data = ds.pixel_array
data = np.random.rand(16,256,256)
nframes = data.shape[0]
ax = pylab.subplot(111)
pylab.subplots_adjust(left=0.25, bottom=0.25)
frame = 0
l = pylab.imshow(data[frame,:,:]) #shows 1024x256 imagge, i.e. 0th frame*
axcolor = 'lightgoldenrodyellow'
axframe = pylab.axes([0.35, 0.1, 0.5, 0.03], axisbg=axcolor)
#add slider to scroll image frames
sframe = Slider(axframe, 'Frame', 0, nframes, valinit=0,valfmt='%1d'+'/'+str(nframes))
ax_delete = pylab.axes([0.8,0.025,0.1,0.04], axisbg=axcolor)
#add slider to scroll image frames
#Delete button to delete frame from data set
bDelete = Button(ax_delete, 'Delete')
def update(val):
frame = np.around(sframe.val)
pylab.subplot(111)
pylab.subplots_adjust(left=0.25, bottom=0.25)
pylab.imshow(data[frame,:,:])
sframe.on_changed(update)
pylab.gray()
pylab.show()
The short answer to your question is use numpy.delete. E.g.
import numpy as np
data = np.arange(1000).reshape((10,10,10))
# Delete the third slice along the first axis
# (note that you can delete multiple slices at once)
data = np.delete(data, [2], axis=0)
print data.shape
However, this is a poor approach if you're going to be removing individual slices many times.
The longer answer is to avoid doing this each time you want to delete a slice.
Numpy arrays have to be contiguous in memory. Therefore, this will make a new copy (and delete the old) each time. This will be relatively slow, and requires you to have twice the free memory space required to store the array.
In your case, why not store a python list of 2D arrays? That way you can pop the slices you don't want out without any problems. If you need it as a 3D array afterwards, just use numpy.dstack to create it.
Of course, if you need to do 3D processing, you'll need the 3D array. Therefore, another approach would be to store a list of "bad" indicies and remove them at the end using numpy.delete (note that the items to be deleted is a list, so you can just pass in your list of "bad" indicies).
On a side note, the way you're updating the image will be very slow.
You're creating lots of images, so each one will be redrawn each time and the update will become very slow as you go on.
You're better off setting the data of the image (im.set_data(next_slice)) instead of creating a new image each time.
Better yet, use blitting, but with image data in matplotlib, it's not as advantageous as it is for other types of plots due to matplotlib's slow-ish rescaling of images.
As a quick example:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
def main():
# Set up 3D coordinates from -10 to 10 over a 200x100x100 "open" grid
x, y, z = np.ogrid[-10:10:200j, -10:10:100j, -10:10:100j]
# Generate a cube of interesting data
data= np.sin(x*y*z) / (x*y*z)
# Visualize it
viewer = VolumeViewer(data)
viewer.show()
class VolumeViewer(object):
def __init__(self, data):
self.data = data
self.nframes = self.data.shape[0]
# Setup the axes.
self.fig, self.ax = plt.subplots()
self.slider_ax = self.fig.add_axes([0.2, 0.03, 0.65, 0.03])
# Make the slider
self.slider = Slider(self.slider_ax, 'Frame', 1, self.nframes,
valinit=1, valfmt='%1d/{}'.format(self.nframes))
self.slider.on_changed(self.update)
# Plot the first slice of the image
self.im = self.ax.imshow(data[0,:,:])
def update(self, value):
frame = int(np.round(value - 1))
# Update the image data
dat = self.data[frame,:,:]
self.im.set_data(dat)
# Reset the image scaling bounds (this may not be necessary for you)
self.im.set_clim([dat.min(), dat.max()])
# Redraw the plot
self.fig.canvas.draw()
def show(self):
plt.show()
if __name__ == '__main__':
main()