How to call method of an instance in python - python

I am having an issue calling a method in a very simple python class. I have something that looks like this:
from shape import Shape
class Figure:
def __init__(self):
self.shapes = [] # the shape objects that make up self
self.shape0 = shape([1, 3, 2], [30, 20])
self.shape1 = shape([2, 3, 4], [25, 35])
def get_points(self):
# Returns all .points of all members of self.shapes
all_points = self.shape0
all_points.extend(self.shape1)
print(all_points)
get_points()
In get_points I'm trying to create a list of all of the instances of shape whether they be squares, pentagons, or anything. Right now, they are only triangles (the first array is a label of their points, the second is the angle of two of their vertices).
I'm currently trying to test if all_points returns a list of all of the points in both triangles (so 1,2,3,4). But currently, I'm getting an error trying to call get_points(). Does anyone know why I can't call get_points() right here? Error says, 'Unresolved reference 'get_points'.

Create an instance of Figure first.
f = Figure()
f.get_points()

You need an instance of Figure to call the method upon:
f = Figure()
print f.get_points()

Related

How to animate a plot in python using the VisVis package?

I am trying to animate a plot using visvis.
This is the example code they have:
import visvis as vv
# read image
ims = [vv.imread('astronaut.png')]
# make list of images: decrease red channel in subsequent images
for i in range(9):
im = ims[i].copy()
im[:,:,0] = im[:,:,0]*0.9
ims.append(im)
# create figure, axes, and data container object
a = vv.gca()
m = vv.MotionDataContainer(a)
# create textures, loading them into opengl memory, and insert into container.
for im in ims:
t = vv.imshow(im)
t.parent = m
and I added:
app = vv.use()
app.Run()
This worked. But I needed to animate a plot, not an image, so I tried doing this:
import visvis as vv
from visvis.functions import getframe
# create figure, axes, and data container object
a = vv.gca()
m = vv.MotionDataContainer(a, interval=100)
for i in range(3):
vv.plot([0, 2+i*10], [0, 2+i*10])
f = getframe(a)
t = vv.imshow(f)
t.parent = m
a.SetLimits(rangeX=[-2, 25], rangeY=[-2, 25])
app = vv.use()
app.Run()
The axes are being initialized very big, that is why I am using set limits, and the output is not animated. I am getting only the last frame so a line from (0,0) to (22, 22).
Does anyone know a way of doing this with visvis?
It turns out adding the frame as a child of MotionDataContainer was not the way to go. The function vv.plot returns an instance of the class Line, and one should add the line as a child. If anyone is having the same problem, I could write a more detailed answer.
EDIT Adding a more detailed answer as requested:
To animate a plot made of lines, one must simply add the lines as children of MotionDataContainer. Taking my example in the question above, one would write:
import visvis as vv
# create figure, axes, and data container object
a = vv.gca()
m = vv.MotionDataContainer(a, interval=100)
for i in range(3):
line = vv.plot([0, 2+i*10], [0, 2+i*10])
line.parent = m
app = vv.use()
app.Run()
In my special case, I even needed to animate multiple lines being drawn at the same time.
To do this, I ended up defining a new class that, like MotionDataContainer, also inherits from MotionMixin, and change the class attribute delta which specifies how many objects should be made visible at the same time. For that, one has to also rewrite the function _SetMotionIndex.
(See visvis official source code: https://github.com/almarklein/visvis/blob/master/wobjects/motion.py)
Disclaimer: Concerning the animation of multiple objects, I have no idea if this is the intended use or if this is the easiest solution, but this is what worked for me.

How to combine same variables in classes

Trying to create a n-body simulation and currently creating a particle class. I initialise the class by inputing a number of variables such as position and velocity. I was wondering if I could somehow combine all the same variable into one array. For instance when I call upon the Particle class it saves all the variables but the variables are all about that particular particle and tied to it. I was wondering if I would be able to find a way to return the velocities for all the particles in one array.
class Particle:
Position = np.full((1, 3), 0, dtype=float)
Velocity = np.full((1, 3), 0, dtype=float)
Acceleration = np.full((1, 3), 0, dtype=float)
Name = np.full((1, 1), 0, dtype=float)
Mass = np.full((1, 1), 0, dtype=float)
"""Initialisng all all the data members for each Particle"""
def __init__(self, Name, Mass, initPosition, initVelocity, initAcceleration):
self.Name = Name
self.Mass = Mass
self.Position = np.array(initPosition)
self.Velocity = np.array(initVelocity)
self.Aceleration = np.array(initAcceleration)
def arrays(self, Positions, Velocities, Accelerations, Names, Masses):
Positions.append(self.Position)
Velocities.append(self.Velocity)
Accelerations.append(self.Acceleration)
Names.append(self.Name)
Masses.append(self.Mass)
my second definition "arrays" is trying to to that but unsuccessfully. The aim is so that I can type Positions and a (N,3) matrix is produced upon which I can perform calculations. Is this possible?
I am not sure what you want to do actually:
If you want to update and return all positions/velocities of one Particle object so you can define:
def arrays(self, Positions, Velocities, Accelerations, Names, Masses):
self.Positions = np.append(self.Position, Position)
self.Velocities = np.append(self.Velocity, Velocity)
self.Accelerations = np.append(self.Acceleration, Acceleration)
self.Names = np.append(self.Name, Name)
self.Masses = np.append(self.Mass, Mass)
and then you can access class properties like:
p1 = Particle(...)
p1.Positions
you can update your particle properties from outside and can access it.
However in your case(i guess at least) you will probably need multiple particle objects. So it is better define a new class that takes particles collection[Particle(*args, **kwargs), Particle(*args, **kwargs), ...] as an input and then you can access all the particles properties and do whatever you want.
Actually, 'numpy.ndarray' object has no attribute 'append'.
Use append of numpy:
a = np.array([1, 2])
a = np.append(a, 3)
And note that the result of the execution must be assigned, otherwise nothing will be added.
def arrays(self, Positions, Velocities, Accelerations, Names, Masses):
self.Positions.append(Position)
self.Velocities.append(Velocity)
self.Accelerations.append(Acceleration)
self.Names.append(Name)
self.Masses.append(Mass)

using fig,axes in a loop matplotlib

I have a question about using fig, axes function in a loop in matplotlib.
I am trying to create a few plots with multiple subplots (the number of subplots isn not fixed) in a loop as follows:
def start_plot(self):
if self.running:
run_fig, run_ax = plt.subplots(*self.matrix)
if self.histogram:
hist_fig, hist_ax = plt.subplots(*self.matrix)
def create_signal_plots(self, iwindow, window_name):
if self.running:
run_ax[iwindow+1].plot(running_perf, label=window_name) # throws error run_ax not recognized
if self.histogram:
hist_ax[iwindow+1].hist(timeseries, label=window_name)
plot = plot_class(run =1, hist =1, matrix = get_matrix(*args)) # e.g. matrix = (3,2)
for istrat, strat in enumerate(strats):
plot.start_plot()
for iwindow, window in enumerate(windows):
plot.create_plots(iwindow, window)
Is there a way to make this work without having to return axes in function and pass it around? If I use plt.figure instead of fix,axes, then i can simply update any figure using plt.figure(fig_no).
You can store run_fig and run_ax in your object as instance attributes and then access them from any other method of that object. This would be done using self.
Use self.run_fig, etc. in start_plot and create_signal_plots as in:
def start_plot(self):
if self.running:
self.run_fig, self.run_ax = plt.subplots(*self.matrix)
if self.histogram:
self.hist_fig, self.hist_ax = plt.subplots(*self.matrix)
def create_signal_plots(self, iwindow, window_name):
if self.running:
self.run_ax[iwindow+1].plot(running_perf, label=window_name) # throws error run_ax not recognized
if self.histogram:
self.hist_ax[iwindow+1].hist(timeseries, label=window_name)

How do I add an attribute name to an array?

I was wondering how to add an attribute to an array.
When I do
errors1 = pm.Uniform('errors', 0, 100, size = 7)
the name 'errors' is added.
but then when I do
errors2 = [errors1[1], errors1[3], errors1[6]]
I have no idea how to add that name, and because I didn't add it, when I try to create a model with errors2, I get an error, saying that it doesn't have an attribute name.
Here's my full code:
import pymc as pm
from matplotlib import pyplot as plt
from pymc.Matplot import plot as mcplot
import numpy as np
from matplotlib import rc
first_res = [-27.020,3.570,8.191,9.898,9.603,9.945,10.056]
second_res = [18.752, 12.450, 11.832]
v1 = pm.Uniform('v1', -30, 15)
v2 = pm.Uniform('v2', 0, 20)
errors1 = pm.Uniform('errors', 0, 100, size = 7)
errors2 = [errors1[1], errors1[3], errors1[6]] # doesn't have an attribute name
taus1 = 1/(errors1 ** 2)
taus2 = [taus1[1], taus1[3], taus1[6]]
first_dist = pm.Normal('first_dist', mu = v1, tau = taus1, value = first_res, observed = True)
second_dist= pm.Normal('second_dist', mu = v2, tau = taus2, value = second_res, observed = True)
model=pm.Model([first_dist, second_dist, errors1, taus1, v1, v2])
mcmc=pm.MCMC(model)
mcmc.sample(20000,10000)
mcplot(mcmc.trace("errors"))
plt.figure()
model2=pm.Model([second_dist, errors2, taus2, v2]) # since errors2 doesn't have an attribute name, I get an error
mcmc2=pm.MCMC(model2)
mcmc2.sample(20000,10000)
mcplot(mcmc2.trace('second_dist'))
PyMC2 has some magic that lets us operate on nodes like errors1 as if they are numpy arrays, but it doesn't always work as you might expect. In cases like this, you can define a deterministic node explicitly with the pm.Lambda, e.g.
errors2 = pm.Lambda('errors2', lambda errors1=errors1: [errors1[1],
errors1[3],
errors1[6]])
Just to clarify on some python concepts, the way you define errors2, it is a python list. lists do not have any name attribute. The attributes that have the elements of a list are not the same attributes of the list as a whole (as an object).
In fact, arrays do not have any name attribute either, and if errors1 does have a name attribute it is because it is pymc object, a distribution.
I think you have to define errors2 in more detail. Is it a uniform distribution? What is its relation to errors1, not in python, but statistically?

mayavi - setting the [x,y,z] extent of an image programatically

I have some data that consists of several 2D images that I would like to render in specific [x,y,z] positions relative to one another using mayavi2 (v4.3.0).
From the documentation it seems that I should just be able to do this with mlab.imshow(). Unfortunately, mayavi throws an exception when I call imshow specifying the extent parameter (AttributeError: 'ImageActor' object has no attribute 'actor').
I also tried setting the x,y and z data directly by modifying im.mlab_source.x,y,z.... Weirdly, whilst this correctly changes the x and y extents, it does nothing to the z-position even though im.mlab_source.z clearly changes.
Here's a runnable example:
import numpy as np
from scipy.misc import lena
from mayavi import mlab
def normal_imshow(img=lena()):
return mlab.imshow(img,colormap='gray')
def set_extent(img=lena()):
return mlab.imshow(img,extent=[0,100,0,100,50,50],colormap='cool')
def set_xyz(img=lena()):
im = mlab.imshow(img,colormap='hot')
src = im.mlab_source
print 'Old z :',src.z
src.x = 100*(src.x - src.x.min())/(src.x.max() - src.x.min())
src.y = 100*(src.y - src.y.min())/(src.x.max() - src.y.min())
src.z[:] = 50
print 'New z :',src.z
return im
if __name__ == '__main__':
# this works
normal_imshow()
# # this fails (AttributeError)
# set_extent()
# weirdly, this seems to work for the x and y axes, but does not change
# the z-postion even though data.z does change
set_xyz()
Ok, it turns out that this is a known bug in mayavi. However, it is possible to change the orientation, position and scale of an ImageActor object after it has been created:
obj = mlab.imshow(img)
obj.actor.orientation = [0, 0, 0] # the required orientation
obj.actor.position = [0, 0, 0] # the required position
obj.actor.scale = [0, 0, 0] # the required scale

Categories

Resources