I'm plotting an animation of circles. It looks and works great as long as speed is set to a positive number. However, I want to set speed to 0.0. When I do that, something changes and it no longer animates. Instead, I have to click the 'x' on the window after each frame. I tried using combinations of plt.draw() and plt.show() to get the same effect as plt.pause(), but the frames don't show up. How do I replicate the functionality of plt.pause() precisely either without the timer involved or with it set to 0.0?
speed = 0.0001
plt.ion()
for i in range(timesteps):
fig, ax = plt.subplots()
for j in range(num):
circle = plt.Circle(a[j], b[j]), r[j], color='b')
fig.gca().add_artist(circle)
plt.pause(speed)
#plt.draw()
#plt.show()
plt.clf()
plt.close()
I've copied the code of pyplot.pause() here:
def pause(interval):
"""
Pause for *interval* seconds.
If there is an active figure it will be updated and displayed,
and the GUI event loop will run during the pause.
If there is no active figure, or if a non-interactive backend
is in use, this executes time.sleep(interval).
This can be used for crude animation. For more complex
animation, see :mod:`matplotlib.animation`.
This function is experimental; its behavior may be changed
or extended in a future release.
"""
backend = rcParams['backend']
if backend in _interactive_bk:
figManager = _pylab_helpers.Gcf.get_active()
if figManager is not None:
canvas = figManager.canvas
canvas.draw()
show(block=False)
canvas.start_event_loop(interval)
return
# No on-screen figure is active, so sleep() is all we need.
import time
time.sleep(interval)
As you can see, it calls start_event_loop, which starts a separate crude event loop for interval seconds. What happens if interval == 0 seems backend-dependend. For instance, for the WX backend a value of 0 means that this loop is blocking and never ends (I had to look in the code here, it doesn't show up in the documentation. See line 773).
In short, 0 is a special case. Can't you set it to a small value, e.g. 0.1 seconds?
The pause docstring above says that it can only be used for crude anmiations, you may have to resort to the animation module if you want something more sophisticated.
Related
I am working on a project and am trying to write code for this project in circuitpython on a esp32 s2 board.
Currectly I don't have the hardware setup ready to function so I can't test codes I've written. So all I have to base my findings on are thought experiments and trying to understand what the code will do (which is a good training at it's own IMHO).
One of the difficulties, and the one for this question, is that I am dealing with getting the stepper motor to change direction when an (optical) limit switch is triggered (so far so good i think), but i will also need to keep it in this "reversed" direction once it no longer triggers that switch.
One way, to do so, seems to make it stop looking at the first limit switch as soon as it is triggered and start looking at the switch at the opposite end instead as well as change the direction. Unfortunately i understand this but have no clue how to set this up in code. When it reaches the trigger it this end it needs to do something else entirely so i am really only dealing with this one switch triggered change of direction during initialisation.
while True:
stepper_motor.onestep(direction=stepper.FORWARD, style=stepper.DOUBLE)
time.sleep(Interstep_delay)
while switch_top.value is False
stepper_motor.onestep(direction=stepper.BACKWARD, style=stepper.DOUBLE)
Step_count = Step_count + 1
time.sleep(Interstep_delay)
while switch_bottom.value is False
#stop stepper motor
Total_count = Step_count.
This is the code I have for now, but it just doesn't feel correct to me. Mainly because I (think I) make it look at the bottom switch but I don't make it stop looking at the top switch but I have no idea how to change this in a correct manner.
Any thought and suggestions are welcome.
Kind greats
PS: I added my code to clarify what I am doing and willing to do. Please help me with the thought experiment. This question is ofcourse not intended for me to end up with a working code still don't understand.
Since post i changed code to this
# initiasation
leds[0] = (255, 0, 0)
while True:
while switch_top.value:
stepper.onestep(direction=stepper.FORWARD, style=stepper.DOUBLE)
time.sleep(Interstep_delay)
if switch_bottom.value:
stepper.onestep(direction=stepper.BACKWARD, style=stepper.DOUBLE)
Step_count = Step_count + 1
time.sleep(Interstep_delay)
elif switch_bottom.value is False:
Step_count = Total_steps
leds[0] = (0, 255, 0)
if switch_start is False:
leds[0] = (0, 0, 255)
game_function()
but i am still in doubt if it would actually do what i intend it to do.
How can I use EnvGen in a loop in such a way that it won't restart at every iteration of the loop?
What I need it for: piecewise synthesis. I want e.g. 50ms of a xfade between first and second Klang, then a 50ms xfade between second and third Klang, then a 50ms xfade between third and fourth Klang and so on, and I want this concatenation as a whole to be modulated by an envelope.
Unfortunately the EnvGen seems to restart from the beginning on every iteration of the loop that plays the consecutive Klang pairs. I want a poiiiiinnnnnnnnnng, but no matter what I try all I get is popopopopopopopopo.
2019 EDIT:
OK, since nobody would answer the "how to achieve the goal" question, I am now downgrading this question to a mere "why doesn't this particular approach work", changing the title too.
Before I paste some code, a bit of an explanation: this is a very simplified example. While my original desire was to modulate a complicated, piecewise-generated sound with an envelope, this simplified example only "scissors" 100ms segments out of the output of a SinOsc, just to artificially create the "piecewise generation" situation.
What happens in this program is that the EnvGen seems to restart at every loop iteration: the envelope restarts from t=0. I expect to get one 1s long exponentially fading sound, like plucking a string. What I get is a series of 100ms "pings" due to the envelope restarting at the beginning of each loop iteration.
How do I prevent this from happening?
Here's the code:
//Exponential decay over 1 second
var envelope = {EnvGen.kr(Env.new([1,0.001],[1],curve: 'exp'), timeScale: 1, doneAction: 2)};
var myTask = Task({
//A simple tone
var oscillator = {SinOsc.ar(880,0,1);};
var scissor;
//Prepare a scissor that will cut 100ms of the oscillator signal
scissor = {EnvGen.kr(Env.new([1,0],[1],'hold'),timeScale: 0.1)};
10.do({
var scissored,modulated;
//Cut the signal with the scisor
scissored = oscillator*scissor;
//Try modulating with the envelope. The goal is to get a single 1s exponentially decaying ping.
modulated = {scissored*envelope};
//NASTY SURPRISE: envelope seems to restart here every iteration!!!
//How do I prevent this and allow the envelope to live its whole
//one-second life while the loop and the Task dance around it in 100ms steps?
modulated.play;
0.1.wait;
});
});
myTask.play;
(This issue, with which I initially struggled for MONTHS without success, actually caused me to shelve my efforts at learning SuperCollider for TWO YEARS, and now I'm picking up where I left off.)
You way of working here is kind of unusual.
With SuperCollider, the paradigm shift you're looking for is to create SynthDefs as discrete entities:
s.waitForBoot ({
b = Bus.new('control');
SynthDef(\scissors, {arg bus;
var env;
env = EnvGen.kr(Env.linen);
//EnvGen.kr(Env.new([1,0.001],[1],curve: 'exp'), timeScale: 1, doneAction: 2);
Out.kr(bus, env);
}).add;
SynthDef(\oscillator, {arg bus, out=0, freq=440, amp = 0.1;
var oscillator, scissored;
oscillator = SinOsc.ar(freq,0,1);
scissored = oscillator * In.kr(bus) * amp;
Out.ar(out, scissored);
}).add;
s.sync;
Task({
Synth(\scissors, [\bus, b]);
s.sync;
10.do({|i|
Synth(\oscillator, [\bus, b, \freq, 100 * (i+1)]);
0.1.wait;
});
}).play
});
I've changed for a longer envelope and a change in pitch, so you can hear all the oscillators start.
What I've done is I've defined two SynthDefs and a bus.
The first SynthDef has an envelope, which I've lengthened for purposes of audibility. It writes the value of that envelope out to a bus. This way, every other SynthDef that wants to use that shared envelope can get it by reading the bus.
The second SynthDef has an a SinOsc. We multiply the output of that by the bus input. This uses the shared envelope to change the amplitude.
This "works", but if you run it a second time, you'll get another nasty surprise! The oscillator SynthDefs haven't ended and you'll hear them again. To solve this, you'll need to give them their own envelopes or something else with a doneAction. Otherwise, they'll live forever.Putting envelopes on each individual oscillator synth is also a good way to shape the onset of each one.
The other new thing you might notice in this example is the s.sync; lines. A major feature of SuperCollider is that the audio server and the language are separate processes. That line makes sure the server has caught up, so we don't try to use server-side resources before they're ready. This client/server split is also why it's best to define synthdefs before using them.
I hope that the long wait for an answer has not turned you off permanently. You may find it helpful to look at some tutorials and get started that way.
I am trying to process a video in Matlab that I read in using VideoReader. I can process the the frames without a problem, but I only want to process every fifth frame. I tried using the step function but this doesn't work on my videoreader object. Right now I can call readFrame five times, but this obviously slows down the whole process (its a lot of video material). How can I efficiently skip five frames, process five frame, skip another five, ... using Matlab?
Error message:
Undefined function 'step' for input arguments of type 'VideoReader'.
However, calling the help function on step gets me this example:
WORKED=step(VR,DELTA)
Moves the frame counter by DELTA frames for video VR. This is a
generalization of NEXT. Returns 0 on an unsuccessful step. Note that
not all plugins support stepping, especially with negative numbers. In
the following example, both IM1 and IM2 should be the same for most
plugins.
vr = videoReader(...myurl...);
if (~next(vr)), error('couldn''t read first frame'); end
im1 = getframe(vr);
if (~step(vr,-1)), error('could not step back to frame 0'); end
im2 = getframe(vr);
if (any(im1 ~= im2)),
error('first frame and frame 0 are not the same');
end
vr = close(vr);
FNUM should be an integer.
After the videoReader constructor is called, NEXT, SEEK, or step should
be called at least once before GETFRAME is called.
Here, step is clearly called on a VideoReader object, is it not? Help would be greatly appreciated.
I've had this issue too. Without using deprecated code, the only way to do what you are trying is to call readFrame five times for every output frame. This is slow and very inefficient. However, if you use the deprecated read method (and assuming your video is a file rather than a stream), you can specify a frame number as well. I don't know why The MathWorks have gone backwards on this. I suggest that you file a service request to ask about it and say why this functionality is important to you.
In the meantime, you can try out my frame2jpg function that extracts particular frames from a video file. It tries to use the deprecated read method and falls back to readFrame if that fails. I've found the read method to be ten times faster in my own application with 1080p 60 fps MPEG-4 video. Feel free to modify the code to suit your your needs.
Don`t know if this is still of use but I´ve found a way to work around the issue.
As the readFrame reads the CURRENT frame, provided by the vid.CurrentTime property you can simply advance the property by the amount of frames you want to skip.
vid = VideoReader('myvid.mpeg')
vidFig = figure();
currAxes = axes;
n = 10;
while hasFrame(vid)
vidFrame = readFrame(vid);
vid.CurrentTime = vid.CurrentTime + n/vid.FrameRate;
image(vidFrame, 'Parent', currAxes);
currAxes.Visible = 'off';
end
Changing the value of n makes the video skip the amount of frames through every loop. I hope this helped.
I'm using Flash CS6 with AS2.
I'm in a Game Design class here in High School and we have learned some basic coding. I am currently trying to add a "speed boost" feature when you press the shift button. You're supposed to be able to press it and that would give you a 5 second speed boost. After those 5 seconds, you'd revert back to normal speed. These are the variables I have made:
speed = 6;
boost = 16;
boost_timer = 0;
I've set my speed to 6, and I called 16 (the ASCII code for the Shift Key) "boost". I've also added in a timer for the boos to count to the 5 seconds when I call for it in the main code. Here that part of the code:
if(Key.isDown(boost))
{
speed = 0;
boost_timer++;
speed = 12
}
-
if(boost_timer >= 5)
{
boost_timer = 0;
speed = 6;
}
Now, what I'm trying to do here is make it so that when I press "boost", it will set my "boost_timer" to 0 (which would only matter if and when it's not already at 0). Then, it will start increasing my "boost_timer" and set my "speed" to double the original speed.
In the second piece of code, I make it so that once it reaches 5, it should set the timer back to 0. However, because "boost_timer++" had already been set, even with it getting set back to 0, it would still be increasing. But, even when it gets to 5, it will simply restart the timer and continue resetting the speed to 6. The next time I press the "boost" button, it should set the "boost_timer" back to 0 and re-do the whole thing.
I am planning on adding some sort of power up function for later that will restrict the amount of times you can use the boost, but for now, I would first like to make sure that my game is actually capable of using the boost multiple times.
The actual problem I'm having with the coding I have so far is that whenever I now press the "boost" button, it does, in fact, increase the speed. However, it stays at the boosted speed and never goes back on its own. And for some reason, whenever I press the "boost" button again while already boosted, it reverts back to original speed. It's as if the "boost" button is working as an activate and deactivate button for the boost, but I have no idea why and what part of my code is causing this.
Thank you very much for any help you can give!
Found an answer for you from newgrounds:
If you just want to test if the key isnt pressed at the time, just use:
if(Key.isDown(Key.UP) == false)
or
if(!Key.isDown(Key.UP))
however, if you want to test for the exact point the key is lifted only, you have to use a latch sysetm:
if(Key.isDown(Key.UP)){
latch = true;
}
if(!Key.isDown(Key.UP) && latch){
latch = false;
// put your actions here
}
you can see that it will only be that !Key.isDown(Key.UP) && latch once after the key is pressed, so it will perform the actions,then
will wait until the key is pressed then released again to do the
actions again.
And you shall probably run some function at the point where key is lifted up, to reduce speed and store speed boost leftover values.
also this latch variable shall be set to false on every frame at the point where no more functions precedes, so after event program enters next frame with its value being false
Umh! There is event listener for this already made: adobeMX
I'm a MATLAB beginner and I would like to know how I can acquire and save 20 images at 5 second intervals from my camera. Thank you very much.
First construct a video input interface
vid = videoinput('winvideo',1,'RGB24_400x300');
You'll need to adjust the last bit for your webcam. To find a list of webcam devices (and other things besides) use:
imaqhwinfo
The following makes the first webcam into an object
a=imaqhwinfo('winvideo',1)
Find the list of supported video formats with
a.SupportedFormats
You'll then want to start up the interface:
start(vid);
preview(vid);
Now you can do the following:
pics=cell(1,20)
for i=1:20
pause(5);
pics{i}=getsnapshot(vid);
end
Or, as other commentators have noted, you could also use a Matlab timer for the interval.
If you wish to capture images with a considerably shorter interval (1 or more per second), it may be more useful to consider the webcam as a video source. I've left an answer to this question which lays out methods for achieving that.
There are several ways to go about this, each with advantages and disadvantages. Based on the information that you've posted so far, here is how I would do this:
vid = videoinput('dcam', 1'); % Change for your hardware of course.
vid.FramesPerTrigger = 20;
vid.TriggerRepeat = inf;
triggerconfig(vid, 'manual');
vid.TimerFcn = 'trigger(vid)';
vid.TimerPeriod = 5;
start(vid);
This will acquire 20 images every five seconds until you call STOP. You can change the TriggerRepeat parameter to change how many times acquisition will occur.
This obviously doesn't do any processing on the images after they are acquired.
Here is a quick tutorial on getting one image http://www.mathworks.com/products/imaq/description5.html Have you gotten this kind of thing to work yet?
EDIT:
Now that you can get one image, you want to get twenty. A timer object or a simple for loop is what you are going to need.
Simple timer object example
Video example of timers in MATLAB
Be sure to set the "tasks to execute" field to twenty. Also, you should wrap up all the code you have for one picture snap into a single function.
To acquire the image, does the camera comes with some documented way to control it from a computer? MATLAB supports linking to outside libraries. Or you can buy the appropriate MATLAB toolbox as suggested by MatlabDoug.
To save the image, IMWRITE is probably the easiest option.
To repeat the action, a simple FOR loop with a PAUSE will give you roughly what you want with very little work:
for ctr = 1:20
img = AcquireImage(); % your function goes here
fname = ['Image' num2str(ctr)]; % make a file name
imwrite(img, fname, 'TIFF');
pause(5); % or whatever number suits your needs
end
If, however, you need exact 5 second intervals, you'll have to dive into TIMERs. Here's a simple example:
function AcquireAndSave
persistent FileNum;
if isempty(FileNum)
FileNum = 1;
end
img = AcquireImage();
fname = ['Image' num2str(FileNum)];
imwrite(img, fname, 'TIFF');
disp(['Just saved image ' fname]);
FileNum = FileNum + 1;
end
>> t = timer('TimerFcn', 'ShowTime', 'Period', 5.0, 'ExecutionMode', 'fixedRate');
>> start(t);
...you should see the disp line from AcquireAndSave repeat every 5 seconds...
>> stop(t);
>> delete(t);