Matplotlib in wxpython-plotting aborts - python

I'm using matplotlib in my wx.Frame to draw some arrows and text at a certain position. The number and position of the arrows is based on previously created data.
I do some calculations but basically it's like this:
arrow = primer
for each primer:
draw one arrow at position y - 0.05 to the previos arrow (primer_y - 0.05).
The x position of the arrow comes from the data, which is calculated and scaled (not so important know, it's just to now where the arrow should be at primer_x).
Everything works fine until I have many arrows to draw. E.g. in my code example the data contain 62 arrows, where 18 are drawn correctly, the next 3 are missing but the text is there and the rest is completly missing.
Does anyone knows what could be the problem? I tried allready to change the FigureSize but it's only stretch the arrows.
Here's a quick and dirty working example, data is included in the code:
http://pastebin.com/7mQmZm2c
Any help is highly appreciated!
Thanks in advance!
Stefanie

Stick
print((primer_x+0.06, primer_y))
inside the loop. You'll find that the arrows cease to be drawn when
primer_y becomes negative.
Don't draw the arrows with self.axes.annotate while labeling the
arrow with self.fig.text. The axis and the figure use different
coordinate systems. Changing self.fig.text to self.axes.text
will allow you to use the same coordinate system, which will make it
easier for you to position the text under the arrows.
There are far too many
hard-coded numbers ("magic numbers") in your code. It makes it very
hard to fix because when one number changes, the rest to do not change
in a logical way along with it. If you can use formulas to define
the relationship between some of those magic numbers, your life will
be a lot easier.
For example, if you change the for-loop to
for primer,primer_y in zip(data,np.linspace(0.95,0.0,len(data))):
instead of decrementing primer_y by a fixed amount with each pass through the loop, then primer_y will automatically space itself between 0.95 down to 0.0 no matter how many items there are in data.
If you find the arrows are squished (vertically), you can expand the
figure by changing the figsize on this line:
self.fig = matplotlib.figure.Figure(figsize=(20, 30), facecolor='white')

Related

how can I set a dot / bar on specific section of a line plot in pyqtgraph?

I've started playing with pyqtgraph plotting line charts.
I have the need to draw specific dots in some section of the lines.
I found that in order for dots to appear on the line,
I need to use symbolBrush when plotting E.g
curve3 = p1.plot(pen=(2,5) , name="trade" , symbolBrush=2)
But the thing is it shows dots on the entire line,
and I can't seem to find a way to draw a dot for specific points / sections.
Assistance would be appreciated
Edit:
For example, In the attached image, assume I only want to draw a dot where marked (1,1) without dots being drawn on the other line breaks.
So, here is an example of what you are looking for. It's a bit "dodgy" in that I'm accessing something inside a PlotDataItem that probably shouldn't be directly accessed, so there is a risk that this code may become non-functional with future updates to pyqtgraph.
That said, I think the risk is reasonably low, it would be easy to update my example to work with whatever changes are made to pyqtgraph, and the example may spark an idea in you that leads to a path that achieves the same thing, without needing to abuse the internals of pyqtgraph.
pw = pg.PlotWidget()
x = np.arange(8)
y = [1,6,2,4,3,5,6,8]
p = pw.plot(x=x, y=y, symbolSize=25)
p.scatter.setData(x=[x[2]],y=[y[2]])
pw.show()

use numpy/matplotlib to draw a histogram with range of bottom/top/infinite

I don't think the title is precise enouth. If anyone will modify it, please help me.
I used to use numpy and matplotlib to draw a distribution diagram. As far as I know, np.histogram can only set the range with a bottom and a top value. But I'd like to make it three values, which are bottom, top and infinite.
For example
MW=[121,131,...,976,1400] # hundreds of out-of-order items
b,bins = np.histogram(MW,bins=10,range=(0,1000))
ax.bar(bins[:-1]+50,b,align='center',facecolor='grey',alpha=0.5,width=100,)
with these codes, I can draw a distribution diagram in which ten bins locates (0-100,100-200,...900-1000). But there are a few numbers higher than 1000. I want to put them in "(1000 - +∞)". So it seems like to make the parameter of range become (0,1000,infinite/or a number big enough), but it is not available.
A awful way to do is using some tricks such as:
MW=[x if x <1000 else 1001 for x in MW]
b,bins = np.histogram(MW,bins=11,range=(0,1100))
And change the xlabel of the plot.
Is there any better way to implement it?
If trick is the only way, is it possible to quickly change the xlabel?

Python: how to plot points with little overlapping

I am using python to plot points. The plot shows relationship between area and the # of points of interest (POIs) in this area. I have 3000 area values and 3000 # of POI values.
Now the plot looks like this:
The problem is that, at lower left side, points are severely overlapping each other so it is hard to get enough information. Most areas are not that big and they don't have many POIs.
I want to make a plot with little overlapping. I am wondering whether I can use unevenly distributed axis or use histogram to make a beautiful plot. Can anyone help me?
I would suggest using a logarithmic scale for the y axis. You can either use pyplot.semilogy(...) or pyplot.yscale('log') (http://matplotlib.org/api/pyplot_api.html).
Note that points where area <= 0 will not be rendered.
I think we have two major choices here. First adjusting this plot, and second choosing to display your data in another type of plot.
In the first option, I would suggest clipping the boundries. You have plenty of space around the borders. If you limit the plot to the boundries, your data would scale better. On top of it, you may choose to plot the points with smaller dots, so that they would seem less overlapping.
Second option would be to choose displaying data in a different view, such as histograms. This might give a better insight in terms of distribution of your data among different bins. But this would be completely different type of view, in regards to the former plot.
I would suggest trying to adjust the plot by limiting the boundries of the plot to the data points, so that the plot area would have enough space to scale the data and try using histograms later. But as I mentioned, these are two different things and would give different insights about your data.
For adjusting you might try this:
x1,x2,y1,y2 = plt.axis()
plt.axis((x1,x2,y1,y2))
You would probably need to make minor adjustments to the axis variables. Note that there should definetly be better options instead of this, but this was the first thing that came to my mind.

Need to add a "legend" to an arrow/contour plot

I am plotting some scalar data as a contour plot with matplotlib.contourf. On top of it, I am plotting some vector data with matplotlib.arrow. The basic plot has come along OK, but now I need to put a box on the plot with a default-size arrow plus the data value to which it corresponds, so the viewer will know what kind of scale he is looking at. For instance, I need a box with a horizontal arrow of some length and, below that, some text like "10 cm/sec".
First, if anyone can give me a simple approach to this, I would be grateful.
Second, the approach I have tried is to do the contour plot, then plot the arrows, then add a rectangle to the plot like so:
rect=pl.Rectangle((300,70),15,15,fc='white')
pl.gca().add_patch(rect)
and then, finally, put my scale arrow and text on top of this rectangle.
This isn't working because the rectangle patch covers up the contour, but it doesn't cover up the arrows in the plot. Is there a way to move the patch completely "to the front" of everything else?
Got it. Using pylab.quiver and pylab.quiverkey functions. quiver produces a nice vector field with just a few lines of code, and quiverkey makes it easy to produce a scaling vector with text. And, for some reason, the arrows plotted with quiver are indeed covered by my rectangle, so it is easy to make the scaling arrow very visible. There are still some mysteries in all of this for me. If anyone wants to try to clear them up, would be much obliged. But I have a way now to do what I need in this instance.

On adjusting margins in matplotlib

I am trying to minimize margins around a 1X2 figure, a figure which are two stacked subplots. I searched a lot and came up with commands like:
self.figure.subplots_adjust(left=0.01, bottom=0.01, top=0.99, right=0.99)
Which leaves a large gap on top and between the subplots. Playing with these parameters, much less understanding them was tough (things like ValueError: bottom cannot be >= top)
My questions :
What is the command to completely minimize the margins?
What do these numbers mean, and what coordinate system does this follow (the non-standard percent thing and origin point of this coordinate system)? What are the special rules on top of this coordinate system?
Where is the exact point this command needs to be called? From experiment, I figured out it works after you create subplots. What if you need to call it repeatedly after you resize a window and need to resize the figure to fit inside?
What are the other methods of adjusting layouts, especially for a single subplot?
They're in figure coordinates: http://matplotlib.sourceforge.net/users/transforms_tutorial.html
To remove gaps between subplots, use the wspace and hspace keywords to subplots_adjust.
If you want to have things adjusted automatically, have a look at tight_layout
Gridspec: http://matplotlib.sourceforge.net/users/gridspec.html

Categories