Cannot delete matplotlib.animation.FuncAnimation objects - python-2.7

EDIT/TL;DR: It looks like there is a matplotlib.backends.backend_qt4.TimerQT object that hold a reference to my FuncAnimation object. How can I remove it to free the FuncAnimation object?
1 - A little context
I'm trying to animate a plot generated with matplotlib. I use matplotlib.animation.FuncAnimation.
This animated plot is contained in a FigureCanvasQTAgg (matplotlib.backends.backend_qt4agg), ie. a PyQt4 widget.
class ViewerWidget(FigureCanvasQTAgg):
def __init__(self, viewer, parent):
# viewer is my FuncAnimation, encapsulated in a class
self._viewer = viewer
FigureCanvasQTAgg.__init__(self, viewer.figure)
When a change of configuration occure in the GUI, the Figure is cleared (figure.clf()) and its subplots (axes and lines) replaced by new ones.
2 - Source code from Class Viewer (encapsulating FuncAnimation)
This is the most relevant part of my method Viewer.show(...), that instanciate the FuncAnimation
2.a - First, I tried:
animation.FuncAnimation(..., blit=True)
Of course, the instance was garbage collected immediatly
2.b - Then, I stored it in a class variable:
self._anim = animation.FuncAnimation(..., blit=True)
It worked for the first animation, but as soon as the configuration changed, I had artifacts from previous animations all over the new ones
2.c - So I manually added a del:
# Delete previous FuncAnimation if any
if self._anim:
del self._anim
self._anim = animation.FuncAnimation(..., blit=True)
Nothing changed
2.d - After some debugging, I checked the garbage collector:
# DEBUG: check garbage collector
def objects_by_id(id_):
for obj in gc.get_objects():
if id(obj) == id_:
return obj
self._id.remove(id_)
return "garbage collected"
# Delete previous FuncAnimation if any
if self._anim:
del self._anim
# DEBUG
print "-"*10
for i in self._id.copy():
print i, objects_by_id(i)
print "-"*10
self._anim = animation.FuncAnimation(self._figure_handler.figure,
update,
init_func=init,
interval=self._update_anim,
blit=True)
# DEBUG: store ids only, to enable object being garbage collected
self._anim_id.add(id(anim))
After 3 configuration changes, it showed:
----------
140488264081616 <matplotlib.animation.FuncAnimation object at 0x7fc5f91360d0>
140488264169104 <matplotlib.animation.FuncAnimation object at 0x7fc5f914b690>
140488145151824 <matplotlib.animation.FuncAnimation object at 0x7fc5f1fca750>
140488262315984 <matplotlib.animation.FuncAnimation object at 0x7fc5f8f86fd0>
----------
So, it confirmed that none of the FuncAnimation were garbage collected
2.e - Last try, with weakref:
# DEBUG: check garbage collector
def objects_by_id(id_):
for obj in gc.get_objects():
if id(obj) == id_:
return obj
self._id.remove(id_)
return "garbage collected"
# Delete previous FuncAnimation if any
if self._anim_ref:
anim = self._anim_ref()
del anim
# DEBUG
print "-"*10
for i in self._id.copy():
print i, objects_by_id(i)
print "-"*10
anim = animation.FuncAnimation(self._figure_handler.figure,
update,
init_func=init,
interval=self._update_anim,
blit=True)
self._anim_ref = weakref.ref(anim)
# DEBUG: store ids only, to enable object being garbage collected
self._id.add(id(anim))
This time, logs where confusing, I'm not sure what's going on.
----------
140141921353872 <built-in method alignment>
----------
----------
140141921353872 <built-in method alignment>
140141920643152 Bbox('array([[ 0., 0.],\n [ 1., 1.]])')
----------
----------
140141921353872 <built-in method alignment>
140141920643152 <viewer.FftPlot object at 0x7f755565e850>
140141903645328 Bbox('array([[ 0., 0.],\n [ 1., 1.]])')
----------
(...)
Where are my <matplotlib.animation.FuncAnimation object at 0x...>?
There were no more previous animation artifacts, so far so good, but... FuncAnimation is no longer able to execute the "update". Only the "init" part. My guess is the FuncAnimation is garbage collected as soon as the method Viewer.show(...) returns, sinces anim ids are already recycled.
3 - Help
I don't know where to look from here. Any suggestion?
EDIT:
I installed objgraph to visualize all back references to FuncAnimation, I got this:
import objgraph, time
objgraph.show_backrefs([self._anim],
max_depth=5,
filename="/tmp/debug/func_graph_%d.png"
% int(time.time()))
So, there is a matplotlib.backends.backend_qt4.TimerQT that still hold a reference. Any way to remove it?

To sort out what is going on here involves going down into the guts of how the animation module and two callback registries work.
When you create the Animation object it registers a callback into the mpl callback registry on the draw_event so that after the first time that the canvas is drawn after the Animation object is created the timed animation sets it self up (by registering a callback into a timer object) and a callback into the mpl callback registry on the close_event to tear the timer down.
The mpl callback registry does a bunch of introspection of the callables that come in and reconstructs bound methods into a weakref to the object an the relevant function. Thus, if you you create an animation object but don't keep a ref to it, it's refcount will go to zero, the weakref to it in the mpl callback registry will fail, and the animation will never start.
The way that the timer works it Qt is that you register a callable which is added to a list (I am getting this from your diagram at the bottom) so it is holding a hard reference to the Animation object, thus removing the ref you hold in your object is not enough to drive the ref count to zero. In the case of timers callbacks this is probably a feature, not a bug.
By artifacts, I now understand to mean you are creating a second Animation object and what you get is both of them running in parallel (which I am not sure what I expect to happen there).
To stop a running Animation and remove it from the timer's callback list use the private method (which should be public) _stop which is what responsible for the tear down (and is the method registered on close_event).

Related

How to instanciate indexed block in pyomo abstract model with parameters indexed with an index foreign from the block?

I am writing an extensive problem in pyomo in which i need to activate and deactivate assets in projects. I think the easiest way to model this is to write an abstract model and then put each asset into a block. Then every time a model would be instanciated it would be possible to activate only certain type of blocks and a certain number of each blocks (ie 3 block wind turbine). Therefore the block will be indexed. Inside these blocks I define parameters that are time dependent but the time will be a shared index between all so it won't be local set but a general set.
Here is a short example of the typical situation I am running into:
import pyomo.environ as pm
model=pm.AbstractModel()
model.A=pm.Set()
model.T=pm.Set(ordered=True) #the set of Time
def Ablock(b,g):
b.A_param=pm.Param(model.T)
model.A_block=pm.Block(model.A,rule=Ablock)
Amodel_dict = \
{None : dict(
A = {None:[1,2,3]},
T = {None:[4,12,23]},
A_block = { 1: dict(A_param = { 4:3, 12:4, 23:5}),
2: dict(A_param = { 4:5, 12:6, 23:7}),
3: dict(A_param = { 4:8, 12:9, 23:10})}
)
}
instance=model.create_instance(data=Amodel_dict)
This gives the error:
RuntimeError: Failed to set value for param=A_block[1].A_param, index=4, value=3.
source error message="Index '4' is not valid for indexed component 'A_block[1].A_param'"
Intuitively i feel it is wrong to call for model.T inside the function Ablock as it is not supposed to know what it refers to but if i give it as an argument of the function, it modifies the block creation to block indexed on time as well. Do you have any idea how to solve this ?
I found the solution that was quite simple but very practical. Instead of calling model.T one should navigate in the hierarchical structure by using the functions model() or parent_block().
A solution for my problem is to call:
b.model().T or b.parent_block().T

Ionic 3 Infinite Scroll 'cannot read property timestamp of null'

So I am using infinite scroll to load a very large reactive form in bits.
However I've noticed that if a form input event is triggered while the infinite scroll is loading other items this happens.
ERROR TypeError: Cannot read property 'timeStamp' of null
at InfiniteScroll._onScroll (infinite-scroll.js:229)
at SafeSubscriber.schedulerFn [as _next] (core.es5.js:3647)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:238)
at SafeSubscriber.next (Subscriber.js:185)
at Subscriber._next (Subscriber.js:125)
at Subscriber.next (Subscriber.js:89)
at EventEmitterProxy.Subject.next (Subject.js:55)
at EventEmitterProxy.EventEmitter.emit (core.es5.js:3621)
at ScrollView.scroll.onScroll (content.js:378)
at ScrollView.setScrolling (scroll-view.js:52)
at ScrollView.scrollTo (scroll-view.js:401)
at Content.scrollTo (content.js:433)
at TextInput._jsSetFocus (input.js:524)
at TextInput._pointerEnd (input.js:496)
at Object.eval [as handleEvent] (TextInput.ngfactory.js:130)
at Object.handleEvent (core.es5.js:11998)
at Object.handleEvent (core.es5.js:12717)
at dispatchEvent (core.es5.js:8614)
at core.es5.js:9228
at HTMLDivElement.<anonymous> (platform-browser.es5.js:2648)
at HTMLDivElement.wrapped (raven.js:350)
at t.invokeTask (polyfills.js:3)
at Object.onInvokeTask (core.es5.js:3881)
at t.invokeTask (polyfills.js:3)
at r.runTask (polyfills.js:3)
at e.invokeTask [as invoke] (polyfills.js:3)
at p (polyfills.js:2)
at HTMLDivElement.v (polyfills.js:2)
console.(anonymous function) # console.js:32
defaultErrorLogger # core.es5.js:1020
ErrorHandler.handleError # core.es5.js:1080
IonicErrorHandler.handleError # ionic-error-handler.js:61
webpackJsonp.381.SentryErrorHandler.handleError # sentry-
errorhandler.ts:11
(anonymous) # core.es5.js:9232
(anonymous) # platform-browser.es5.js:2648
wrapped # raven.js:350
t.invokeTask # polyfills.js:3
onInvokeTask # core.es5.js:3881
t.invokeTask # polyfills.js:3
r.runTask # polyfills.js:3
e.invokeTask # polyfills.js:3
p # polyfills.js:2
v # polyfills.js:2
It's really driving me crazy because not even a try catch can stop this error from crashing the app.
Please I need help!!
This is a current ionic issue, that unfortunately doesn't look like it will be patched before v4.
bug(infinite-scroll): throws uncatchable error if scrollToTop is called before it is resolved
The quickest way to try and avoid the issue (it doesn't work everytime) is to wrap a setTimeout around the scrollToTop / scrollToBottom
setTimeout(function(){
this.content.scrollToBottom()
},200);
I was experiencing a similar issue, ran into this:
TypeError: Cannot read property 'enableEvents' of null
at EventEmitterProxy.enableScrollListener [as onSubscribe]
This would happen intermittently after a function on a different Ionic page that refreshed external content within our app. I never figured out exactly why, but I noticed that it was only happening when the infinite-scroll had been triggered at some point during user interaction with the original page.
In our case, I was setting the InfiniteScroll instance to a local, component-level variable so that I could use the .enable() hooks programmatically in other functions, like so:
VIEW:
<ion-infinite-scroll (ionInfinite)="lazyLoad($event)"> ...
CONTROLLER:
public lazyLoad(infiniteScroll: InfiniteScroll) {
// ASSIGN THE LAZY LOADER INSTANCE ON FIRST RUN SO IT CAN BE ENABLED / DISABLED ELSEWHERE
this.lazyLoader = infiniteScroll;
....
}
But, then we would run into the above TypeError randomly when refreshing content, so it was almost like there was a call somewhere trying to reference that variable. So I just set the variable to null when the page left the view, and now it works. Weirdness.
(NOTE: all calls to the instance of InfiniteScroll were wrapped in an if (this.lazyLoader && this.lazyLoader !== null) gate to begin with so I'm not really sure what went wrong)
ionViewWillLeave() {
this.lazyLoader = null;
}
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
#Component({...})
export class MyPage{
scrollToTop() {
this.navCtrl.setRoot('MyPage'); //so you will go to the top of page.
}
}
Go to infinite-scroll.js
Check if ev is null
If null return 3;
//Do nothing

How to Initialize LSTMCell with tuple

I recently upgraded my tesnorflow from Rev8 to Rev12. In Rev8 the default "state_is_tuple" flag in rnn_cell.LSTMCell is set to False, so I initialized my LSTM Cell with an list, see code below.
#model definition
lstm_cell = rnn_cell.LSTMCell(self.config.hidden_dim)
outputs, states = tf.nn.rnn(lstm_cell, data, initial_state=self.init_state)
#init_state place holder and feed_dict
def add_placeholders(self):
self.init_state = tf.placeholder("float", [None, self.cell_size])
def get_feed_dict(self, data, label):
feed_dict = {self.input_data: data,
self.input_label: reg_label,
self.init_state: np.zeros((self.config.batch_size, self.cell_size))}
return feed_dict
In Rev12, the default "state_is_tuple" flag is set to True, in order to make my old code work I had to explicitly turn the flag to False. However, now I got an warning from tensorflow saying:
"Using a concatenated state is slower and will soon be deprecated.
Use state_is_tuple=True"
I tried to initialize LSTM cell with a tuple by changing the placeholder definition for self.init_state to the following:
self.init_state = tf.placeholder("float", (None, self.cell_size))
but now I got an error message saying:
"'Tensor' object is not iterable"
Does anyone know how to make this work?
Feeding a "zero state" to an LSTM is much simpler now using cell.zero_state. You do not need to explicitely define the initial state as a placeholder. Define it as a tensor instead and feed it if required. This is how it works,
lstm_cell = rnn_cell.LSTMCell(self.config.hidden_dim)
self.initial_state = lstm_cell.zero_state(self.batch_size, dtype=tf.float32)
outputs, states = tf.nn.rnn(lstm_cell, data, initial_state=self.init_state)
If you wish to feed some other value as the initial state, Let's say next_state = states[-1] for instance, calculate it in your session and pass it in the feed_dict like -
feed_dict[self.initial_state] = next_state
In the context of your question, lstm_cell.zero_state() should suffice.
Unrelated, but remember that you can pass both Tensors and Placeholders in the feed dictionary! That's how self.initial_state is working in the example above. Have a look at the PTB Tutorial for a working example.

PyGObject, Looping buttons

I'm tying to create a loop of buttons, and execute a command when they are pressed.
k=0
for row in list:
delete_list.append("button_delete"+str(k))
delete_list[k] = Gtk.Button(label="Delete")
grid.attach(delete_list[k], columns+1, k, 1, 1)
delete_list[k].connect("clicked",globals()["on_button"+str(k)+"_clicked"])
k+=1
The buttons are displayed correctly, but i'm having problems to connect the "clicked" signal.
delete_list[k].connect("clicked",globals()["on_button"+str(k)+"_clicked"])
KeyError: 'on_button0_clicked'
I first tought that the error was because there is no method on_button0_clicked, but i create it and i stil getting the same error.
Also, if there is some good way/advice to dynamically create the methods for the response of the buttons it would be great. I actually need to create a method for each button that uses the "k" counter.
To dynamically create a function which binds loop variables as locals, you need a factory function to generate them:
def callback_factory(num):
def new_callback(widget):
print(widget, num)
return new_callback
for k, row in enumerate(somelist):
button = Gtk.Button(label=str(k))
button.connect('clicked', callback_factory(k))
This avoids a common pitfall which is to create a method or lambda within the loop body causing the same thing to be printed for each button click. This is due to the environment the function is created in being bound to the generated function in which the k variable is mutating and shared between all callbacks. The pitfall can be observed with the following code which does not work as you might expect:
for k, row in enumerate(somelist):
def callback(widget):
print(k)
button = Gtk.Button(label=str(k))
button.connect('clicked', callback)
PyGObject also supports unique user data per-connect call which is passed into the callback:
def callback(widget, num):
print(widget, num)
for k, row in enumerate(somelist):
button = Gtk.Button(label=str(k))
button.connect('clicked', callback, k))
This allows using the same callback with a varying argument which can be cleaner in some cases.
Side note: It is probably not a good idea to mask the builtin "list" class by assigning it to your own list instance.

CCCallBlockN's alternative in Cocos2d v3.0

What's CCCallBlockN alternative for Cocos2d 3.0 ?
Here is my Cocos2d 2.0 Code:
id calBlock = [CCCallBlockN actionWithBlock:^(CCNode *node){
node.position = orign;
}];
The CCCallBlockN and CCCallBlockND variants have always been superfluous since blocks can reference objects in the local scope:
id someData = (some data however created or obtained);
CCNode* someNode = (some node however created or obtained);
id callBlock = [CCActionCallBlock actionWithBlock:^{
someNode.position = origin;
[someData quickDoSomething];
}];
[someNode runAction:callBlock];
You just need to have a reference like someNode in the outer scope of the block in order to use it inside the block.
You will usually have the desired node reference because after all you're going to run the action on the desired node after creating the action. Only in cases where you create the actions first and run them later would the passed-in node be useful, but I guess that's a rare situation and probably not good style anyway.