Values from class into variable - python

I have got 2 classes, one that's called MineField and one that's called Options, in the options-class there is scales that i get the values from through a function inside that class, def assign():, the MineField-class have three parameters (w,h,m). I want to assign values to these parameters from the scales in the Options-class. (I use tkinter)
Class Options:
def __init__(self, w, h, m)
...
minorinput = Scale.(...)
mainloop()
...
def assign():
self.width = widthinput.get()
self.height = heightinput.get()
self.minor = minorinput.get()
def main():
ins = Options(0,0,0)
ins.assign()
w = ins.width
h = ins.height
m = ins.minor
game.MineField(w,h,m)
So how do I get these values from the scales into game.MineField?

Your code is highly unusual. In essence, you can't do what you are asking to do. At least, not in the way you're trying to do it.
Are you aware that once you call mainloop, the remainder of your code after that statement won't run until you destroy your window? Once the window is destroyed, you can't query the widgets for their values since they don't exist.

Related

Writing classes that simulate random walks

Regarding a question that I made yesterday: How can I implement (I think via inheritance) a new class, with a parameter of the parent class, and a paremeter which comes from another module?
Now my task continues this way:
Create a method of Simulation called get next event that chooses a neighboring node of the current walker’s position uniformly at random and draws a waiting time from an exponential distribution with parameter lambda_. The method should then return the time of the next move and the next position of the walker.
My code now looks like this:
import networkx as nx
import random
class RandomWalker:
def __init__(self, position=0):
self.position = position
class Simulation:
def __init__(self, random_walker, G, lambda_, t_end):
self.random_walker = random_walker
self.G = G
self.lambda_ = lambda_
self.t_end = t_end
G = nx.Graph()
random_walker = RandomWalker(position)
simulation = Simulation(random_walker, G, lambda_, t_end)
def get_next_event(self, G, lambda_):
neighbors = list(G.neighbors(random_walker))
next_event = random.choice(neighbors)
position = next_event
waiting_time = np.random.exponential(lambda_)
return 'Waiting time: '+waiting_time+ '. New position: '+position
Since I'm new to the "classes creation method", I still have in my code (I have python 3.8.1 on Spyder) errors about, for example, undefined name position at line 20, and others similar afterwards, although I have them in the classes initialization.
Now, I didn't understand if, when calling variables that were defined in the class initialization, e.g. that one in line 20, i have to write RandomWalker.positionmaybe?
Any help is appreciated, thank you.

When should I use classes and self method in Python?

I've been trying to write a Python program to calculate a point location, based on distance from 4 anchors. I decided to calculate it as intersection points of 4 circles.
I have a question regarding not the algorithm but rather the use of classes in such program. I don't really have much experience with OOP. Is it really necessary to use classes here or does it at least improve a program in any way?
Here's my code:
import math
class Program():
def __init__(self, anchor_1, anchor_2, anchor_3, anchor_4, data):
self.anchor_1 = anchor_1
self.anchor_2 = anchor_2
self.anchor_3 = anchor_3
self.anchor_4 = anchor_4
def intersection(self, P1, P2, dist1, dist2):
PX = abs(P1[0]-P2[0])
PY = abs(P1[1]-P2[1])
d = math.sqrt(PX*PX+PY*PY)
if d < dist1+ dist2 and d > (abs(dist1-dist2)):
ex = (P2[0]-P1[0])/d
ey = (P2[1]-P1[1])/d
x = (dist1*dist1 - dist2*dist2 + d*d) / (2*d)
y = math.sqrt(dist1*dist1 - x*x)
P3 = ((P1[0] + x * ex - y * ey),(P1[1] + x*ey + y*ex))
P4 = ((P1[0] + x * ex + y * ey),(P1[1] + x*ey - y*ex))
return (P3,P4)
elif d == dist1 + dist2:
ex = (P2[0]-P1[0])/d
ey = (P2[1]-P1[1])/d
x = (dist1*dist1 - dist2*dist2 + d*d) / (2*d)
y = math.sqrt(dist1*dist1 - x*x)
P3 = ((P1[0] + x * ex + y * ey),(P1[1] + x*ey + y*ex))
return(P3, None)
else:
return (None, None)
def calc_point(self, my_list):
if len(my_list) != 5:
print("Wrong data")
else:
tag_id = my_list[0];
self.dist_1 = my_list[1];
self.dist_2 = my_list[2];
self.dist_3 = my_list[3];
self.dist_4 = my_list[4];
(self.X1, self.X2) = self.intersection(self.anchor_1, self.anchor_2, self.dist_1, self.dist_2)
(self.X3, self.X4) = self.intersection(self.anchor_1, self.anchor_3, self.dist_1, self.dist_3)
(self.X5, self.X6) = self.intersection(self.anchor_1, self.anchor_4, self.dist_1, self.dist_4)
with open('distances.txt') as f:
dist_to_anchor = f.readlines()
dist_to_anchor = [x.strip() for x in dist_to_anchor]
dist_to_anchor = [x.split() for x in dist_to_anchor]
for row in dist_to_anchor:
for k in range(0,5):
row[k] = float(row[k])
anchor_1= (1,1)
anchor_2 = (-1,1)
anchor_3 = (-1, -1)
anchor_4 = (1, -1)
My_program = Program (anchor_1, anchor_2, anchor_3, anchor_4, dist_to_anchor)
My_program.calc_point(dist_to_anchor[0])
print(My_program.X1)
print(My_program.X2)
print(My_program.X3)
print(My_program.X4)
print(My_program.X5)
print(My_program.X6)
Also, I don't quite understand where should I use self keyword and where it is needless.
Is it really necessary to use classes here or does it at least improve a program in any way?
Classes are never necessary, but they are often very useful for organizing code.
In your case, you've taken procedural code and just wrapped it in a class. It's still basically a bunch of function calls. You'd be better off either writing it as procedures or writing proper classes.
Let's look at how you'd do some geometry in a procedural style vs an object oriented style.
Procedural programming is all about writing functions (procedures) which take some data, process it, and return some data.
def area_circle(radius):
return math.pi * radius * radius
print(area_circle(5))
You have the radius of a circle and you get the area.
Object oriented programming is about asking data to do things.
class Circle():
def __init__(self, radius=0):
self.radius = radius
def area(self):
return math.pi * self.radius * self.radius
circle = Circle(radius=5)
print(circle.area())
You have a circle and you ask it for its area.
That seems a lot of extra code for a very subtle distinction. Why bother?
What happens if you need to calculate other shapes? Here's a Square in OO.
class Square():
def __init__(self, side=0):
self.side = side
def area(self):
return self.side * self.side
square = Square(side=5)
print(square.area())
And now procedural.
def area_square(side):
return side * side
print(area_square(5));
So what? What happens when you want to calculate the area of a shape? Procedurally, everywhere that wants to deal with shapes has to know what sort of shape it's dealing with and what procedure to call on it and where to get that procedure from. This logic might be scattered all over the code. To avoid this you could write a wrapper function and make sure its imported as needed.
from circle import 'area_circle'
from square import 'area_square'
def area(type, shape_data):
if type == 'circle':
return area_circle(shape_data)
elif type == 'square':
return area_square(shape_data)
else:
raise Exception("Unrecognized type")
print(area('circle', 5))
print(area('square', 5))
In OO you get that for free.
print(shape.area())
Whether shape is a Circle or a Square, shape.area() will work. You, the person using the shape, don't need to know anything about how it works. If you want to do more with your shapes, perhaps calculate the perimeter, add a perimeter method to your shape classes and now it's available wherever you have a shape.
As more shapes get added the procedural code gets more and more complex everywhere it needs to use shapes. The OO code remains exactly the same, instead you write more classes.
And that's the point of OO: hiding the details of how the work is done behind an interface. It doesn't matter to your code how it works so long as the result is the same.
Classes and OOP are IMHO always a good choice, by using them, you will be able to better organize and reuse your code, you can create new classes that derive from an existing class to extend its functionality (inheritance) or to change its behavior if you need it to (polymorphism) as well as to encapsulate the internals of your code so it becomes safer (no real encapsulation in Python, though).
In your specific case, for example, you are building a calculator, that uses a technique to calculate an intersection, if somebody else using your class wants to modify that behavior they could override the function (this is Polymorphism in action):
class PointCalculator:
def intersection(self, P1, P2, dist1, dist2):
# Your initial implementation
class FasterPointCalculator(PointCalculator):
def __init__(self):
super().__init__()
def intersection(self, P1, P2, dist1, dist2):
# New implementation
Or, you might extend the class in the future:
class BetterPointCalculator(PointCalculator):
def __init__(self):
super().__init__()
def distance(self, P1, P2):
# New function
You may need to initialize your class with some required data and you may not want users to be able to modify it, you could indicate encapsulation by naming your variables with an underscore:
class PointCalculator:
def __init__(self, p1, p2):
self._p1 = p1
self._p2 = p2
def do_something(self):
# Do something with your data
self._p1 + self._p2
As you have probably noticed, self is passed automatically when calling a function, it contains a reference to the current object (the instance of the class) so you can access anything declared in it like the variables _p1 and _p2 in the example above.
You can also create class methods (static methods) and then you don't have access to self, you should do this for methods that perform general calculations or any operation that doesn't need a specific instance, your intersection method could be a good candidate e.g.
class PointCalculator:
#staticmethod
def intersection(P1, P2, dist1, dist2):
# Return the result
Now you don't need an instance of PointCalculator, you can simply call PointCalculator.intersection(1, 2, 3, 4)
Another advantage of using classes could be memory optimization, Python will delete objects from memory when they go out of scope, so if you have a long script with a lot of data, they will not be released from memory until the script terminates.
Having said that, for small utility scripts that perform very specific tasks, for example, install an application, configure some service, run some OS administration task, etc... a simple script is totally fine and it is one of the reasons Python is so popular.

Storing output from Python function necessary despite not using output

I am trying to understand why I must store the output of a Python function (regardless of the name of the variable I use, and regardless of whether I subsequently use that variable). I think this is more general to Python and not specifically to the software NEURON, thus I put it here on Stackoverflow.
The line of interest is here:
clamp_output = attach_current_clamp(cell)
If I just write attach_current_clamp(cell), without storing the output of the function into a variable, the code does not work (plot is empty), and yet I don't use clamp_output at all. Why cannot I not just call the function? Why must I use a variable to store the output even without using the output?
import sys
import numpy
sys.path.append('/Applications/NEURON-7.4/nrn/lib/python')
from neuron import h, gui
from matplotlib import pyplot
#SET UP CELL
class SingleCell(object):
def __init__(self):
self.soma = h.Section(name='soma', cell=self)
self.soma.L = self.soma.diam = 12.6517
self.all = h.SectionList()
self.all.wholetree(sec=self.soma)
self.soma.insert('pas')
self.soma.e_pas = -65
for sec in self.all:
sec.cm = 20
#CURRENT CLAMP
def attach_current_clamp(cell):
stim = h.IClamp(cell.soma(1))
stim.delay = 100
stim.dur = 300
stim.amp = 0.2
return stim
cell = SingleCell()
#IF I CALL THIS FUNCTION WITHOUT STORING THE OUTPUT, THEN IT DOES NOT WORK
clamp_output = attach_current_clamp(cell)
#RECORD AND PLOT
soma_v_vec = h.Vector()
t_vec = h.Vector()
soma_v_vec.record(cell.soma(0.5)._ref_v)
t_vec.record(h._ref_t)
h.tstop = 800
h.run()
pyplot.figure(figsize=(8,4))
soma_plot = pyplot.plot(t_vec,soma_v_vec)
pyplot.show()
This is a NEURON+Python specific bug/feature. It has to do with Python garbage collection and the way NEURON implements the Python-HOC interface.
When there are no more references to a NEURON object (e.g. the IClamp) from within Python or HOC, the object is removed from NEURON.
Saving the IClamp as a property of the cell averts the problem in the same way as saving the result, so that could be an option for you:
# In __init__:
self.IClamps = []
# In attach_current_clamp:
stim.amp = 0.2
cell.IClamps.append(stim)
#return stim

python class property trouble

I have the following code:
class tile:
def __init__(self, value):
self.value = value
class map_2d:
def __init__(self, xsize, ysize):
self.dimx = xsize
self.dimy = ysize
self.canvas = [[tile(0)] * xsize for i in range(ysize)]
for yc in range(ysize):
for xc in range(xsize):
self.canvas[yc][xc].x = xc
self.canvas[yc][xc].y = yc #CHECKPOINT
#TEST:
mymap = map_2d(10, 10)
for line in mymap.canvas:
print ' | '.join('%d:%d' % (cell.x, cell.y) for cell in line)
I expect to have a map_2d instance with .canvas property, that is a 2d array of tile instances with x and y properties corresponding to the tile coordinates. Like 0:0, 1:0, 2:0, ...
Problem is, in the end ALL my tiles have an x property of xsize-1, 9 in the test above. It is utterly confusing, since at the moment marked by #CHECKPOINT everything is right and all tiles have their actual coordinates as x and y properties. Nothing is wrong with my visualization method either.
I would welcome any hints to help with this mystery. Any suggestions about achieving my goal (which is assigning coordinates to cells) more efficiently will be appreciated as well.
Moreover, if anyone reading this feels like "what the hell is this guy doing", I'd be grateful for any sound advice on how to deal with simple map generation, which is my ultimate goal in this case. I did all this to have a way of addressing tiles adjacent to another tile by coordinates, but my approach feels quite suboptimal.
This line doesn't do what you expect:
self.canvas = [[tile(0)] * xsize for i in range(size)]
Even though it seems to create a list of lists, you're actually getting lists that contain a reference to the same object tile(0). So when you modify canvas[0][0], you're also modifying canvas[0][1], canvas[0][2] and so on.
For example:
>>> [tile(0)] * 5
[<__main__.Tile instance at 0x10200eea8>, <__main__.Tile instance at 0x10200eea8>, <__main__.Tile instance at 0x10200eea8>, <__main__.Tile instance at 0x10200eea8>, <__main__.Tile instance at 0x10200eea8>]
Each object has the same memory address so it's a list of five elements which are actually all the same object.
You can solve this by explicitly creating new objects:
self.canvas = [[tile(0) for j in range(xsize)] for i in range(ysize)]

Python , my object claims to not have an access to a method

I'm writing some Python code and have a class as follows
class GO:
##irrelevant code
def getCenter(self):
xList = []
yList = []
# Put all the x and y coordinates from every GE
# into separate lists
for ge in self.GEList:
for point in ge.pointList:
xList.append(point[0])
yList.append(point[1])
# Return the point whose x and y values are halfway between
# the left- and right-most points, and the top- and
# bottom-most points.
centerX = min(xList) + (max(xList) - min(xList)) / 2
centerY = min(yList) + (max(yList) - min(yList)) / 2
return (centerX, centerY)
###more irrelevant code
def scale(self, factor):
matrix = [[factor,0,0],[0,factor,0],[0,0,1]]
for ge in self.GEList:
fpt = []
(Cx, Cy) = ge.getCenter()
for pt in ge.pointList:
newpt = [pt[0]-C[0],pt[1]-C[0],1]###OR USE TRANSLATE
spt = matrixPointMultiply(matrix, newpt)
finalpt = [spt[0]+C[0],spt[1]+C[0],1]
fpt.append(finalpt)
ge.pointList=fpt
return
Whenever I run it it says: AttributeError: circle instance has no attribute 'getCenter'.
How do I get the object to correctly the call the function upon itself?
This is kind of a noobish question and I am learning, so detailed advice would be helpful.
Have you checked your indenting to make sure it's all consistent? That's a classic Python beginner problem. You need to use consistent whitespace (either tabs or spaces, most people prefer spaces) and the right amount of whitespace.
For example, this may look OK, but it won't do what you expect:
class Dummy(object):
def foo(self):
print "foo!"
def bar(self):
print "bar!"
d = Dummy()
d.bar()
This will return:
AttributeError: 'Dummy' object has no attribute 'bar'
If that's not it, try to pare your code down to the minimum, and post that and how you're calling it. As it stands, the general form looks OK to me, unless I'm missing something.

Categories

Resources