Hi Ben,
  thank you for your comments. Looks I will have a bad sleep tonight. :( Some 
quick
answers below.

Benjamin Root wrote:
> 
> 
> 
> On Thu, Oct 10, 2013 at 10:21 AM, Michael Droettboom <md...@stsci.edu 
> <mailto:md...@stsci.edu>> wrote:
> 
>     Thanks.  This is much more helpful.
> 
>     What we need, however, is a "self contained, standalone example".  The 
> code below calls functions that are not present.  See http://sscce.org/ for 
> why this is so important.  Again, I would have to guess what those functions 
> do -- it may be relevant, it may not.  If I have something that I can *just 
> run* then I can use various introspection tools to see what is going wrong.
> 
>     Mike
> 
> 
> That being said, I do see a number of anti-patterns here that could be 
> significant. For example:
> 
>         for _x, _y, _c in izip(mydata_x, mydata_y, colors):
>             # _Line2D = _ax1.plot(_x, _y) # returns Line2D object
>             _my_PathCollection = _ax1.scatter(_x, _y, color=_c, s=objsize) # 
> , label=_l) # returns PathCollection object
>             _series.append(_my_PathCollection)
> 
> Could be more concisely written as:
> 
>         _series = [_ax1.scatter(_x, _y, color=_c, s=objsize) for _x, _y, _c 
> in izip(mydata_x, mydata_y, colors)]
> 
> Python can then more intelligently handle memory management by intelligently 
> allocating the memory for _series. You can then use _series.extend() for when 
> you are doing the scatter plots for _ax2 with a similar list comprehension 
> (or even a generator statement).

You are right the .append() is ugly, maybe is a the real source of troubles. I 
somehow
do not understand myself right now why under the "if legends:" use ax1 instead 
of ax2.
Weird. I actually stopped using legends with this function because that was my 
first guess
that they cause the memory issues. Seems the culprit is elsewhere so I should 
add them
back and likely fix the ax2 vs. ax1 copy/paste (most likely) error.

As you could have seen, I used in the past label=_l but for some reason I 
switched away
to the current ugly code. Will try to find out why I did that.

Hmm, I don't know what you mean with _series.extend() at the moment, will read 
some
python Intro on using lists. :(


> 
> I would also question the need to store _series in the first place. You use 
> it for the call to legend, but you could have simply passed a label to each 
> call of scatter as well.

As I said, I used that in the past but somehow that did not work. Maybe time to 
re-try that.

> 
> Some other things of note:
> 
> 1) The clear() call here is completely useless as the figure is already clear.
>         _figure = pylab.figure()
>         _figure.clear()

Right, I was just trying to ensure everything is cleared. I somewhat suspect 
python
garbage collector does not recycle too often, and therefore added more and more 
del()
and gc.collect() calls.

> 
> 2) When limits are set on an axis, autoscaling for that axis is automatically 
> turned off anyway, so no need to turn if off yourself (also not sure why you 
> are calling out to an external function here):
>         _ax1.set_autoscale_on(False)
>         set_limits(_ax1, xmin, xmax, ymin, ymax)

The set_limits() is called because I got unstable coordinates in every figure.
Sometimes, matplotlib used wider offset from the axes line while sometimes not.
So, I basically force same layout for expected layouts.

> 
> 3) Finally, some discussion on the end of your function here:
>         if legends:
>             _figure.savefig(filename, dpi=100) #, bbox_inches='tight')
>             del(_my_PathCollection)
>             del(_ax2)
>         else:
>             _figure.savefig(filename, dpi=100)
> 
>         del(_series)
>         del(_ax1)
>         _figure.clear()
>         del(_figure)
>         pylab.clf()
>         pylab.close()
> first, as discussed, you can easily eliminate the need for _my_PathCollection 
> and possibly even _series. Second, when calling _figure.clear(), all of its 
> axes objects are deleted for you, so you don't need to delete them yourself. 
> Third, you delete the _figure object, but then call "pylab.clf()". I haven't 
> double-checked exactly what would happen, but I think you might run the risk 
> of accidentially clearing some other existing figure by doing that. Lastly, 
> you then call pylab.close(), which I point out the same caveat as before. 
> Really, all you needed was pylab.close() and you can eliminate the 5 
> preceding lines and the other two del()'s. All del() really does is remove 
> the variable out of scope. Once that object is out of everybody's scope, then 
> the gc can clean it up. Since the function was ending anyway, there is no 
> point in deleting the variable.

Right, but I suspect that garbage collector  does not recycle quickly enough 
unused objects
after the function is left. If I generate many figure sin a loop, one after 
another, it
appeared to me helpful to interleave the function calls with the gc.collect() 
calls.

> 
> I don't know if this would fix your problem, and there are a bunch of other 
> style issues here (particularly, pylab really shouldn't be used this way), 
> but hopefully this gives some food for thought.

I think I will start tomorrow finishing up the broken testcase so that we can 
be sure
where was the culprit. Then should improve the function as you proposed. I am 
not sure
some places what you really mean but will resolve it hopefully.

I was thinking about submitting several other functions like this one for 
discussion and
improvement, so that so that such wrapper functions could be included in 
matplotlib. I am
sure you would not like the many function argument and would prefer kwargs 
instead, but
something have same API would be helpful if I want to switch easily between 
scatter,
histplot, piechart. Actually, the hist2d substring in this function name is a 
remnant of
my attempts to do 2d charts but I did not take that route in the end. Just in 
case you were
puzzled by the function name. ;)

Thank you,
Martin

> 
> Cheers!
> Ben Root

------------------------------------------------------------------------------
October Webinars: Code for Performance
Free Intel webinars can help you accelerate application performance.
Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from 
the latest Intel processors and coprocessors. See abstracts and register >
http://pubads.g.doubleclick.net/gampad/clk?id=60134071&iu=/4140/ostg.clktrk
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Reply via email to