I am using the Turtles Module where I am creating a U.S. Flag. The user decides the size of the flag and with that size I will be using it to create the width and length.
I am trying to group/compress all of my subfunctions into one huge function so the user can simply type Draw_USAFlag(t, w) ## T = turtle W = Size and it will carry out the task of the 5 functions that I already have.
For example I have 2 subfunctions: draw_rectangle(t, w) and draw_stripes (t, w) ; I want to group these two subfunctions into one function that will be called Draw_USAFlag(t, w) where it will use the user inputted size (w) throughout all of the functions. Any help is greatly appreciated! Thanks!
Quite simply, make a function that calls the others:
def draw_rectangle(t, w):
# however you do this
...
def draw_rectangle(t, w):
# however you do this
...
def Draw_USAFlag(t, w):
draw_rectangle(t, w)
draw_stripes(t, w)
This assumes they don't return anything, so whatever they do works by side-effects on some other object. If e.g. they return an image, this will need changing depending on the exact structure of your system.
Related
I am trying to use Shady to present a sequence of image frames. I'm controlling the flow from another machine, so that I first instruct the machine running Shady to present the first frame, and later on to run the rest of the frames.
I create a World instance, and attach to it an animation callback function. Within this callback I listen for communications from the other machine (using UDP).
First I receive a command to load a given sequence (stored as a numpy array), and I do
def loadSequence(self, fname):
yy = np.load(fname)
pages = []
sz = yy.shape[0]
for j in range(yy.shape[1]/yy.shape[0]):
pages.append(yy[:, j*sz:(j+1)*sz])
deltax, deltay = (self.screen_px[0] - sz) / 2, (self.screen_px[1] - sz) / 2
if (self.sequence is None):
self.sequence = self.wind.Stimulus(pages, 'sequence', multipage=True, anchor=Shady.LOCATION.UPPER_LEFT, position=[deltax, deltay], visible=False)
else:
self.sequence.LoadPages(pages, visible=False)
When I receive the command to show the first frame, I then do:
def showFirstFrame(self, pars):
self.sequence.page = 0 if (pars[0] == 0) else (len(self.sequence.pages) - 1)
self.sequence.visible = True
But what do I do now to get the other frames to be be displayed? In the examples I see, s.page is set as a function of time, but I need to show all frames, regardless of time. So I was thinking of doing something along these lines:
def showOtherFrames(self, pars, ackClient):
direction, ack = pars[0], pars[2]
self.sequence.page = range(1, len(self.sequence.pages)) if (direction == 0) else range(len(self.sequence.pages)-2, -1, -1)
But this won't work. Alternatively I thought of defining a function that takes t as argument, but ignores it and uses instead a counter kept in a global variable, but I'd like to understand what is the proper way of doing this.
When you make s.page a dynamic property, the function assigned to it must take one argument (t), but you can still just use any variables in the space when defining that function, and not even use the time argument at all.
So, for example, you could do something as simple as:
w = Shady.World(...)
s = w.Stimulus(...)
s.page = lambda t: w.framesCompleted
which will set the page property to the current frame count. That sounds like it could be useful for your problem.
Your global-variable idea is one perfectly valid way to do this. Or, since it looks like you're defining things as methods of an instance of your own custom class, you could use instance methods as your animation callbacks and/or dynamic property values—then, instead of truly global variables, it makes sense to use attributes of self:
import Shady
class Foo(object):
def __init__(self, stimSources):
self.wind = Shady.World()
self.stim = self.wind.Stimulus(stimSources, multipage=True)
self.stim.page = self.determinePage # dynamic property assignment
def determinePage(self, t):
# Your logic here.
# Ignore `t` if you think that's appropriate.
# Use `self.wind.framesCompleted` if it's helpful.
# And/or use custom attributes of `self` if that's
# helpful (or, similarly, global variables if you must).
# But since this is called once per frame (whenever the
# frame happens to be) it could be as simple as:
return self.stim.page + 1
# ...which is indefinitely sustainable since page lookup
# will wrap around to the number of available pages.
# Let's demo this idea:
foo = Foo(Shady.PackagePath('examples/media/alien1/*.png'))
Shady.AutoFinish(foo.wind)
Equivalent to that simple example, you could have the statement self.stim.page += 1 (and whatever other logic) inside a more-general animation callback.
Another useful tool for frame-by-frame animation is support for python's generator functions, i.e. functions that include a yield statement. Worked examples are included in python -m Shady demo precision and python -m Shady demo dithering.
It can also be done in a StateMachine which is always my preferred answer to such things:
import Shady
class Foo(object):
def __init__(self, stimSources):
self.wind = Shady.World()
self.stim = self.wind.Stimulus(stimSources, multipage=True)
foo = Foo(Shady.PackagePath('examples/media/alien1/*.png'))
sm = Shady.StateMachine()
#sm.AddState
class PresentTenFrames(sm.State):
def ongoing(self): # called on every frame while the state is active
foo.stim.page += 1
if foo.stim.page > 9:
self.ChangeState()
#sm.AddState
class SelfDestruct(sm.State):
onset = foo.wind.Close
foo.wind.SetAnimationCallback(sm)
Shady.AutoFinish(foo.wind)
from Tkinter import *
top=Tk()
First Value A that user will input
A = Entry(top)
A.grid(row=1, column=1)
Second value B that user also inputs
B = Entry(top)
B.grid(row=1, column=2)
Calculation - Now I want to add those values (Preferably values with decimal points)
A1=float(A.get())
B1=float(B.get())
C1=A1+B1
Result - I want python to calculate result and show it to user when I input the first two values
C = Label(textvariable=C1)
C.grid(row=1, column=3)
top.mainloop()
First off, welcome to StackOverflow and nice job- your code does (mostly) everything you want it to do! The timing is just off- you create your objects and get the value, but the value hasn't been input by the user yet.
To solve that, you need to put your .get()'s in a function, and you should be using an actual text-variable that you set() after each one (if you just use C1=(float), you'll end up making new floats so the Label isn't pointing to the right one).
(setup... )
B.grid(...)
C1 = Tkinter.StringVar()
C = Label(textvariable=C1) # Using a StringVar will allow this to automagically update
def setC():
A1=float(A.get())
B1=float(B.get())
C1.set(str(A1+B1))
Additionally, you need to set this function so it goes off more than just "immediately on running the program". The simple way to do this is to just have the function call itself .after() some time (in milliseconds).
def setC():
# Body above
top.after(1000, setC) # Call setC after 1 second, so it keeps getting called.
setC() # You have to call it manually once, and then it repeats.
The slightly more advanced and efficient way to update involves events and bindings (binding setC() to fire every time A1 or B1 is changed), but the writeup on that is long so I'll give you that tip and send you to some documentation on that. (Effbot is good tkinter documentation regardless)
I am designing a Tkinter interface to be compatible with my datalogging script. Both are still WIP, but close to getting merged. This script is used for a Raspberry Pi to periodically make measurements using different sensors. In this case, of plants.
I have various Entry widgets to access my variables (input channels, measure interval and measurements per average value ), so i can change them without reprogramming the script itself.
3 entry widgets are associated with the textvariables:
gpio_light1_entry, interval_light1_entry, amount_light1_entry
The actual variables used by the datalogging script are:
gpio_light1, interval_light1, amount_light1
I want to define a function (That i will bind to a button.). That retrieves the entry window value (gpio_light1_entry.get()) and that updates the script variable.
Now I could just use:
gpio_light1 = gpio_light1_entry.get()
However I have at least 12 variables per plant. So coding it like this for some 12 times seems very inefficient to me.
I was thinking of using a for loop and lists.
settings_gpio1 = [gpio_light1, gpio_temp1, etc]
settings_gpio1_entry = [gpio_light1_entry, gpio_temp1_entry, etc]
But this had some problems:
1- It seems that changing a value in a list, does not change the variable used to construct the list.
2- I do not know how to make a "double" for loop to use both the _entry and non entry lists.
3- The _entry list needs a .get() function to retrieve the values, this function does not work on lists directly, but can be solved with a for loop.
Does anyone know a more efficient or easier way to reach my goal?
I advise you to create a class for each Gpio access:
The class it self should hold the values for accessing the hardware and displaying it.
If, for some reason, you already have the list of available gpios and entries, you can do some thing like this:
class Gpio:
def __init__(self,setting, entry):
self.setting = setting
self.entry = entry
def Get(self):
#Do whatever you need with self.entry
return 0
def __str__(self):
return self.setting
#staticmethod
def FromArray(names,settings, entries):
assert(len(settings) == len(entries) == len(names))
ret = {}
for i in range(len(settings)):
ret[names[i]] = Gpio(settings[i], entries[i])
return ret
Here I put a random example, I don't know what values you are going to use:
gpio_light1 = 33
gpio_light_entry = "hardware_address"
gpio_temp_entry = "0x80001234"
names = ["gpio_light1", "gpio_temp1"]
settings_gpio = [gpio_light1, "gpio_temp1"]
settings_gpio_entry = [gpio_light_entry, gpio_temp_entry]
access = Gpio.FromArray(names, settings_gpio, settings_gpio_entry)
print access["gpio_light1"].Get()
So, what I am trying to do in detail:
I have a device that acts as a display, although is technically not one (that's not really important, it can be handled like a normal display) and I want to display a series of images on it. When each image is displayed i call a function that takes readings from another device. So far I have used pyglet for that and I can get it to display the images in the correct order and where I want them, but the readings taken seem not to correspond to the right image.
The simplest way to explain what I want to do is:
for a in range(10):
display('image%d'%a)
values(a) = measure()
Imagine values being initiated in the correct form.
What I tried so far was:
import pyglet
import numpy as np
size = 64
no = 512/size
a,b,c = (0,0,0)
values = np.zeros((no,no,3))
display = pyglet.window.get_platform().get_default_display()
screens = []
for screen in display.get_screens():
screens.append(screen)
window = pyglet.window.Window(screen = screens[1], fullscreen=1)
#here i choose the mentioned device, since it is connected to my computer via display port
#window.event
def update(dt):
global a,b,c
if a == no/2. and b == no/2.:
values[a,b,c] = 0
window.clear()
else:
image = pyglet.image.load('folder_%d/grating_%d_%d_%d.bmp' % (size,a,b,c))
window.clear()
print (a,b,c)
image.blit(0,0)
values[a,b,c] = measure()
c+=1
if c == 3:
b += 1
c = 0
if b == no:
a += 1
b = 0
if a == no:
pyglet.app.exit()
pyglet.clock.schedule_interval(update, .2)
pyglet.app.run()
where measure() is my own function. "no" is an index for my images, they range from (0,0,0),(0,0,1),(0,0,2),(0,1,0)... to (no,no,2) and are called to be called one by one. Also the case of a = b = no/2 is a special case that is of no special importance to my problem, I think.
first of all: I am pretty sure this is neither elegant nor efficient but I am not creating software that anyone else is ever likely to use. I am also aware that using global variables is bad practice but their use is due to me not knowing how to use eventloops correctly.
I am not happy with this solution, because the readings i take always seem to correspond to the previous image.
I guess I misuse the eventloop badly, but the pyglet documentation does not really help me here.
Also I feel like I am building a whole truck just to carry a bag across the street...
I have already looked into pyplot as an alternative, since the imshow() function works in the way I want, but the plotting libraries seem to display images in random sizes, which I cannot figure out how to control properly.
I appreciate any help on using pyglet correctly as well as alternative libraries that can help.
Thank you already,
Mopsi
An extra-long comment, that requires formatted code
From your example, you don't need a,b,c outside of the update function and all the global stuff is about having values that stay alive across invocations. If I'm correct this is better suited by a closure, like
...
def make_update(no, window):
from itertools import product
abcs = product(range(no),range(no),range(3))
#window.event
def _update(...):
try:
a, b, c = next(abcs)
except StopIteration:
... wind up ...
...
return _update
update = make_update(no, window)
...
Alright, I did not actually solve the problem but found a workaround:
I just flatten my image nomenclature, e.g
0_0_0 -> 000
0_0_1 -> 001
0_0_2 -> 002
0_1_0 -> 003
etc.
With values now being an array with dimensions [no*no*3,1]
And since for the n-th iteration and therefore n-th measurement I see the (n-1)th image, I simply add a dummy image and assign the n-th measured value to values[n-1].
The first measurement being useless is no problem here, since values[-1] is the last element, which gets overwritten with a meaningful measurement in the end.
Since the number of images is known and predetermined I can reshape my array of values afterwards.
If anyone cares to explain why no the displayed image is shifted by one iteration (with no image at all being displayed at the first iteration) please go ahead.
This is surely a beginner's question, I'm just having trouble searching for it.
What I want to do is calculate points on a circle for thousands of circles which I will later render. Because I will be rendering many thousands of circles a second, I thought I'd try to avoid unncessary overhead. To do this, I've created a function that calculates a number of points (which I want to be variable, a larger circle will need more points calculated) on a unit circle, and another function which can take these points, translate them and then scale by the radius.
My original code ended up something like this:
class Circle():
...
def CalcCircle(segments):
does some stuff to calculate generic coordinates
def CreateCircle(x, y, r, segments):
does some stuff to create a circle using CalcCircle(segments)
Obviously the problem was that even though I might only want to create circles with 20 segments, I was calling the CalcCircle function (and repeating the same calculations) every time I called CreateCircle.
The only way I could figure out how to fix this was:
class Circle():
...
def CalcCircle(segments):
does some stuff to calculate generic coordinates
CreateCircle_has_not_been_run = True
def CreateCircle(x, y, r, segments):
if Circle.TransCircle_has_not_been_run:
generic_circle = Circle.CalcCircle(segments)
Circle.CreateCircle_has_not_been_run = False
does some stuff to create a circle using generic_circle
I've never formally learnt programming so I'm not sure if this is considered good design. Surely it would become messy if every time I wanted to "initialize" data or call a function only on the first run through I had to make a random class variable. The reason I ask is I'm constantly running into this problem, so I assume there must be a standard way of doing it.
Edit: An example of how the call will be made.
#window.event
def on_draw():
window.clear()
width = window.get_size()[0]
height = window.get_size()[1]
radius = int(width/50)
segments = int(radius*1.5)
for i in range(N):
pyglet.gl.glColor3f(0.05,0.2,0.9)
DrawCircle(positions[i][0],positions[i][1],width,segments)
DrawCage(width,height)
DrawLabel(width,height)
etc.
I'm aware that there's problems here but I'm just trying to illustrate the example (positions comes from the update function if anyone is wondering). As I've said earlier, this is a problem I run into all the time.
I could call Circle.CalcCircle() from the on_resize() function as per Achim's suggestion. I have a hard time believing however that standard practice is to stick two random functions into a class (as it stands neither of them necessarily need to even be in the Circle class), one of which is implicitly dependent on the other and both of which are called in different parts of the code.
I would do something like this:
class Circle:
def __init__(self):
self.unit_circle_points = None
def CalcCircle(self, segments):
# Do some stuff to calculate segments,
# assign calculated values to class attribute
self.unit_circle_points = calculated_points
def CreateCircle(self, X, y, r, segments):
# If circle points have not yet been calculated then calculate
# and store, else just load stored points
if self.unit_circle_points is None:
self.CalcCircle(segments)
unit_circle_points = self.unit_circle_points
# Now use unit_circle_points to do some calculations
Every time you instantiate a circle object it will come with an attribute named unit_circle_points that is initialized to None. When you call the CreateCircle method on that object for the first time it will see that the unit_circle_points attribute is None and perform the necessary computations by calling CalcCircle, storing the results. On subsequent calls to the CreateCircle method of this Circle object the unit_circle_points attribute will no longer be None, and the method will simply use the values stored in the attribute.
Edit:
If this requires to much "implicit" behavior for your taste, you can shift things around so that CalcCircle must be called explicitly by the user to generate the pre-calculated data.
class Circle:
def __init__(self):
self.unit_circle_points = None
def CalcCircle(self, segments):
# Do some stuff to calculate segments,
# assign calculated values to class attribute
self.unit_circle_points = calculated_points
return self
def CreateCircle(self, X, y, r):
# If circle points have not yet been calculated then raise an error,
# else load previously calculated points
if self.unit_circle_points is None:
raise Exception("You'd better explicitly call CalcCircle first.")
unit_circle_points = self.unit_circle_points
# Now use unit_circle_points to do some calculations