Clearing NeoPixel LEDs after running animate()? - python

I'm trying to run an animation for a period of time, then clear the LEDs and go back to setting the colors manually with Neopixel.pixels.fill(). Only, after I run animation.animate(), I lose the ability to use pixels.fill() I tried using the sequence library with the auto_clear and auto_reset flags, but those did not seem to work either.
rainbow = Rainbow(macropad.pixels, speed = 0.005, period = 2)
animations = AnimationSequence(rainbow, auto_clear=True, auto_reset=True)
i = 0
while True:
animations.animate()
i += 1
if (i == 100):
animations.reset()
break

Related

My FuncAnimation Python code on Mac will only continue its loops if I move my mouse, but works on Linux?

I have some Python code which uses a generator to run the FuncAnimation, and I want it to loop over that generator several times. So the generator has one input, and generates, say, 100 plots, and then is meant to close once the generator is exhausted. Then, the generator is reset with another input and FuncAnimation starts the loop again.
My problem is: if I run the code on a Linux computer, the exhaustion of the generator will automatically begin the next loop. However, if I run the code on a Mac, which is what I'd like to do, the generator reaches the last graph and stops. Even if I use plt.close() to get rid of that graph, the next loop will ONLY begin if I perform any interaction with my computer - be it move my mouse (even just a few pixels!) or click somewhere, or press a key.
The fact that this problem only arises on a Mac and not a Linux computer tells me it's a problem with how python communicates with the Mac. However, I can't figure out how to get around it.
I realise that I should be adding the minimum reproducible code for the error, but I'll avoid that for now unless someone asks, because it doesn't seem to be the python code itself that's causing me problems.
Edit: here's a minimum reproducible version of it.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def generate_data(array, counter):
array *= -1
return array
def update(array_data):
matrix.set_data(array_data)
return matrix
def data_gen(array, counter):
# attempt at ending the loop, so that the rest of the code can continue. In this
# example, the loop will just start the same kind of code, to keep things simple.
while True:
if counter < 10:
counter += 1
print('counter at ', counter)
yield generate_data(array, counter)
else:
# reset at end of loop
counter = 0
plt.close()
# generate an array of random 1's and 0's, so that it can be plotted with plt.imshow().
array = np.ones([50,50])
for k in range(50):
for j in range(50):
if np.random.random() < 0.5:
array[k, j] *= -1
# set counter to reset the loop of the animation. If you are a mac user, you may
# experience a stop after the last graph closes. The code will only progress
# if you interact with your computer, such as move your mouse!
counter = 0
for n in range(5):
fig, ax = plt.subplots()
matrix = plt.imshow(generate_data(array, counter))
# even using repeat = False doesn't work.
ani = animation.FuncAnimation(fig, update, data_gen(array, counter), interval=200, repeat = False)
plt.show()
I tried to use plt.close(), and plt.show(block = False), but neither of them worked. Running it on Linux works perfectly - what is going wrong here?

Spotipy request speed in while loop

count = 0
while True:
if count > 20:
count = 0
current_track = spotify.current_user_playing_track()
if current_track is None:
display_string = ""
else:
display_string = current_track['item']['name']+" - "+current_track['item']['artists'][0]['name']+" | "
if display_string != previous_track:
sphd.clear()
sphd.write_string(display_string,brightness=0.1)
previous_track = display_string[:]
time.sleep(0.05)
sphd.show()
sphd.scroll(1)
count += 1
The code above is run on a Pi Zero to get the currently playing track every second and display it on a scrollphathd display. The problem is that the process of getting the track causes the display to freeze for about 0.25s. Is there any way of running the loop to get the track separately to refreshing the display's scrolling or any way to speed up getting the track? Thanks for any help in advance.
Possibly the reason of that freeze is the low performance that the Raspberry Pi Zero has.

How to change values of a running pi script

I have a LED-board which is powered with python.
To turn on the LED's a script has to continue running. But how do I influence the color variables of a running script?
I could read an sql(lite?) db, read the values of a file. Get values of some rest api. Or maybe something completely else.
What is the most neat way to do this?
I'm new to python so feel free to point out I'm completely doing it wrong.
Or provide alternative.
Please do provide sample code which I could follow.
#!/usr/bin/env python
import time
import unicornhat as unicorn
unicorn.set_layout(unicorn.AUTO)
unicorn.rotation(0)
unicorn.brightness(0.3)
count = 0
while True:
# somehow change these color values
# syqlite? reading a file? rest requesting some url? or some signal? how to do this?
color=[
[255,0,0], #red
[255,255,0], #yellow
[0,255,0], #green
[0,255,255], #light blue
[0,0,255], # blue
[255,0,255], #purple
[255,255,255], #white
[0,0,0], #off
]
unicorn.clear()
for y in xrange(8):
# make it "scroll"
row = y+count
if row>7:
row -= 8
for x in xrange(8):
unicorn.set_pixel(y, x, color[row][0], color[row][1], color[row][2])
unicorn.show()
if count == 7:
count = 0
else:
count = count + 1
time.sleep(0.2)

how to set the orientation of the stimulus for each trial in psychopy

I am fairly new to the python language and psychopy. I am practicing it by creating dummy experiments. Here, I am trying to create an experiment about bayesian brain. Non-vertical lines will be presented to the participant while no respond is expected from the participants, just exposure. Then for the last trial (it stays on the monitor for longer period of time to be responded), it is expected from the participant to judge whether the last line trial is vertical or not? (after exposing to non-vertical lines, I am expecting to see a change in perception of verticality).
However, there are so many things that I couldn't learn from the web. I am pretty sure you guys can help me easily.
My primary problem is; how to set up the orientation of the line? I found out the stim.ori but not sure how to use it on 'line' stimuli. Below I've attached the codes that I made so far. Also, I have added some extra questions with #.
I tried to be clear as much as I can. Sorry for my bad english.
Thank you!
from psychopy import visual, core, event #import some libraries from PsychoPy
import random
#create a window
mywin = visual.Window([800,600],monitor="testMonitor", units="deg")
#stimuli
lineo = visual.Line(mywin, start=(-5, -1), end=(-5, 1))
fixation = visual.GratingStim(mywin, size=0.2, pos=[0,0], color = 'black')
#draw the stimuli and update the window
n = 5 # trial number
i = 0
while i < n:
#fixation
fixation.draw()
mywin.flip()
presses = event.waitKeys(1)
# stimulus
orientationlist = [20,30,40,50,60] # I want to draw the orientation info from this list
x = random.choice(orientationlist)
lineo.ori((x)) #
lineo.draw()
mywin.flip()
presses= event.waitKeys(2)
i +=1
if i == 5: # how do I change the number into the length of the trial; len(int(n) didnt work.
lineo.draw()
mywin.flip()
presses = event.waitKeys(4)
#quiting
# I dont know how to command psychopy for quiting the
# experiment when 'escape' is pressed.
#cleanup
mywin.close()
core.quit()
There's a few things that you would want to do differently. I've updated your code and marked changes with the comment "CHANGE". Changing the orientation of a stimulus is pretty consistent in psychopy, so it's no different for Line than any other visual stimulus type.
from psychopy import visual, core, event #import some libraries from PsychoPy
import random
#create a window
mywin = visual.Window([800,600],monitor="testMonitor", units="deg")
#stimuli
lineo = visual.Line(mywin, start=(-5, -1), end=(-5, 1))
fixation = visual.GratingStim(mywin, size=0.2, pos=[0,0], color = 'black')
orientationlist = [20,30,40,50,60] # CHANGED. No need to redefine on every iteration of the while-loop.
#draw the stimuli and update the window
n = 5 # trial number
for i in range(n): # CHANGED. This is much neater in your case than a while loop. No need to "manually" increment i.
#fixation
fixation.draw()
mywin.flip()
event.waitKeys(1) # CHANGED. No need to assign output to anything if it isn't used.
# stimulus
lineo.ori = random.choice(orientationlist) # CHANGED. Alternative: lineo.setOri(random.choice(orientationlist)).
lineo.draw()
mywin.flip()
event.waitKeys(2)
# At this point, all the stimuli have been shown. So no need to do an if-statement within the loop. The following code will run at the appropriate time
lineo.draw()
mywin.flip()
event.waitKeys(keyList=['escape']) # CHANGED. Listen for escape, do not assign to variable
# CHANGED. No need to call core.quit() or myWin.close() here since python automatically cleans everything up on script end.

Having a certain piece of code run for a specified amount of time

I'm working on a galactica type of game using pygame and livewires. However, in this game, instead of enemy's, there are balloons that you fire at. Every 25 mouse clicks, I have the balloons move down a row using the dy property set to a value of 1. If a balloon reaches the bottom, the game is over. However, I'm having some trouble figuring out how to get this to run only for, say, 1 second, or 2 seconds. Because I don't have a way to "time" the results, the dy value just indefinitely gets set to 1. Therefore, after the first 25 clicks, the row just keeps moving down. This is ok, but like I said, it's not my intended result.
Here is the code I have so far for this action:
if games.mouse.is_pressed(0):
new_missile = missile(self.left + 6, self.top)
games.screen.add(new_missile)
MISSILE_WAIT = 0 #25
CLICKS += 1
if CLICKS == 25:
SPEED = 1
CLICKS = 0
CLICKS, and MISSILE_WAIT are global variables that are created and set to an initial value of 0 before this block of code. What I'm trying to figure out is the algorithim to put underneath the if CLICKS statement. I've looked through the python documentation on the time module, but just can't seem to find anything that would suit this purpose. Also, I don't think using a while loop would work here, because the computer checks those results instantly, while I need an actual timer.
I'm not sure if I got your question but what I can suggest is that:
class Foo():
def __init__(self):
self.start_time = time.time()
self.time_delay = 25 # seconds
def my_balloon_func(self):
if(time.time() - self.start_time) > self.time_delay:
self.start_time = time.time()
else:
# do something

Categories

Resources