Which Function can make a Graph like this? - python

I'm new to Python and I want to know what this kind of graph is called.
I particularly want to know how to generate those white lines. Those white lines should go up to infinite (the maximum of the Y-axis). The white lines represent a roadblock, as it were.
Anyway, I don't know the name for these white lines, or for the graph in general!
I have scipy suite of software.

Solved it. Simply add another x and y axis which used the '--' line type. And my function was like this in the end:
x1.append(stepid)
y1.append(danger)
x2.append(stepid)
y2.append(dlimit)
x3.append(stepid)
y3.append(dlimit)

Related

Black make function arguments formatting without new lines around barackets

I'd like to format function argumetns in a way similar to the PyCharm default formatting - see image. Meaning no new line after '(' and before ) so it does NOT look like in the second image. It looks cleaner to me when function name is more visible.
I want this:
I do NOT want this:
Black is a highly opinionated formatter with the stated goal of making diffs shorter and consistent.
This is what you get.
The only thing you can configure for Black, at the time of writing, is the line length.

How to easily place/accommodate text annotations at the edge of a plot?

I am plotting some points on a line in python using matplotlib, and whenever the point is at/near the boundaries of the plot the annotated text is hard to read due to overlapping axes labels and such (see screenshot below):
I'm currently using code like this to place my point annotations manually:
# add value text to x, y point
jt = x_points_to_plot # a single x-value, in this case
f = ys_func(x_points_to_plot) # a single y-value, in this case
ax.annotate(
'({}C, {:0.0f}%)'.format(jt, f), # the string text to add
xy=(jt + 1, f + 5), # offset the text from the point manually
ha='center')
Usually my points are in the middle and look acceptable, like this:
But I don't want to manually adjust the text for every point, because I have a lot of changing data and it's not where I want to spend my time; instead, I'd love to find a way to accommodate the text so it it easily readable on the plot. Maybe I could expand the plot to contain the new text, or I could move the text to a different place depending on a set of conditions about what might be near the text? I'm not sure...
I think the best answer will be one I can reuse for other projects, robust to points anywhere on the plot, and relatively easy to implement (least amount of custom functions or "hacks" that I would have to recreate for every project). Thanks a ton in advance!

Why is Python randint() generating bizarre grid effect when used in script to transform image?

I am playing around with images and the random number generator in Python, and I would like to understand the strange output picture my script is generating.
The larger script iterates through each pixel (left to right, then next row down) and changes the color. I used the following function to offset the given input red, green, and blue values by a randomly determined integer between 0 and 150 (so this formula is invoked 3 times for R, G, and B in each iteration):
def colCh(cVal):
random.seed()
rnd = random.randint(0,150)
newVal = max(min(cVal - 75 + rnd,255),0)
return newVal
My understanding is that random.seed() without arguments uses the system clock as the seed value. Given that it is invoked prior to the calculation of each offset value, I would have expected a fairly random output.
When reviewing the numerical output, it does appear to be quite random:
Scatter plot of every 100th R value as x and R' as y:
However, the picture this script generates has a very peculiar grid effect:
Output picture with grid effect hopefully noticeable:
Furthermore, fwiw, this grid effect seems to appear or disappear at different zoom levels.
I will be experimenting with new methods of creating seed values, but I can't just let this go without trying to get an answer.
Can anybody explain why this is happening? THANKS!!!
Update: Per Dan's comment about possible issues from JPEG compression, the input file format is .jpg and the output file format is .png. I would assume only the output file format would potentially create the issue he describes, but I admittedly do not understand how JPEG compression works at all. In order to try and isolate JPEG compression as the culprit, I changed the script so that the colCh function that creates the randomness is excluded. Instead, it merely reads the original R,G,B values and writes those exact values as the new R,G,B values. As one would expect, this outputs the exact same picture as the input picture. Even when, say, multiplying each R,G,B value by 1.2, I am not seeing the grid effect. Therefore, I am fairly confident this is being caused by the colCh function (i.e. the randomness).
Update 2: I have updated my code to incorporate Sascha's suggestions. First, I moved random.seed() outside of the function so that it is not reseeding based on the system time in every iteration. Second, while I am not quite sure I understand how there is bias in my original function, I am now sampling from a positive/negative distribution. Unfortunately, I am still seeing the grid effect. Here is my new code:
random.seed()
def colCh(cVal):
rnd = random.uniform(-75,75)
newVal = int(max(min(cVal + rnd,255),0))
return newVal
Any more ideas?
As imgur is down for me right now, some guessing:
Your usage of PRNGs is a bit scary. Don't use time-based seeds in very frequently called loops. It's very much possible, that the same seeds are generated and of course this will generate patterns. (granularity of time + number of random-bits used matter here)
So: seed your PRNG once! Don't do this every time, don't do this for every channel. Seed one global PRNG and use it for all operations.
There should be no pattern then.
(If there is: also check the effect of interpolation = image-size change)
Edit: As imgur is on now, i recognized the macro-block like patterns, like Dan mentioned in the comments. Please change your PRNG-usage first before further analysis. And maybe show more complete code.
It may be possible, that you recompressed the output and JPEG-compression emphasized the effects observed before.
Another thing is:
newVal = max(min(cVal - 75 + rnd,255),0)
There is a bit of a bias here (better approach: sample from symmetric negative/positive distribution and clip between 0,255), which can also emphasize some effect (what looked those macroblocks before?).

Colorbar based legend in python matplotlib

In the graphic below, I want to put in a legend for the calendar plot. The calendar plot was made using ax.plot(...,label='a') and drawing rectangles in a 52x7 grid (52 weeks, 7 days per week).
The legend is currently made using:
plt.gca().legend(loc="upper right")
How do I correct this legend to something more like a colorbar? Also, the colorbar should be placed at the bottom of the plot.
EDIT:
Uploaded code and data for reproducing this here:
https://www.dropbox.com/sh/8xgyxybev3441go/AACKDiNFBqpsP1ZttsZLqIC4a?dl=0
Aside - existing bugs
The code you put on the dropbox doesn't work "out of the box". In particular - you're trying to divide a datetime.timedelta by a numpy.timedelta64 in two places and that fails.
You do your own normalisation and colour mapping (calling into color_list based on an int() conversion of your normalised value). You subtract 1 from this and you don't need to - you already floor the value by using int(). The result of doing this is that you can get an index of -1 which means your very smallest values are incorrectly mapped to the colour for the maximum value. This is most obvious if you plot column 'BIOM'.
I've hacked this by adding a tiny value (0.00001) to the total range of the values that you divide by. It's a hack - I'm not sure that this method of mapping is at all the best use of matplotlib, but that's a different question entirely.
Solution adapting your code
With those bugs fixed, and adding a last suplot below all the existing ones (i.e. replacing 3 with 4 on all your calls to subplot2grid(), you can do the following:
Replace your
plt.gca().legend(loc="upper right")
with
# plot an overall colorbar type legend
# Grab the new axes object to plot the colorbar on
ax_colorbar = plt.subplot2grid((4,num_yrs), (3,0),rowspan=1,colspan=num_yrs)
mappableObject = matplotlib.cm.ScalarMappable(cmap = palettable.colorbrewer.sequential.BuPu_9.mpl_colormap)
mappableObject.set_array(numpy.array(df[col_name]))
col_bar = fig.colorbar(mappableObject, cax = ax_colorbar, orientation = 'horizontal', boundaries = numpy.arange(min_val,max_val,(max_val-min_val)/10))
# You can change the boundaries kwarg to either make the scale look less boxy (increase 10)
# or to get different values on the tick marks, or even omit it altogether to let
col_bar.set_label(col_name)
ax_colorbar.set_title(col_name + ' color mapping')
I tested this with two of your columns ('NMN' and 'BIOM') and on Python 2.7 (I assume you're using Python 2.x given the print statement syntax)
The finalised code that works directly with your data file is in a gist here
You get
How does it work?
It creates a ScalarMappable object that matplotlib can use to map values to colors. It set the array to base this map on to all the values in the column you are dealing with. It then used Figure.colorbar() to add the colorbar - passing in the mappable object so that the labels are correct. I've added boundaries so that the minimum value is shown explicitly - you can omit that if you want matplotlib to sort that out for itself.
P.S. I've set the colormap to palettable.colorbrewer.sequential.BuPu_9.mpl_colormap, matching your get_colors() function which gets these colours as a 9 member list. I strongly recommend importing the colormap you want to use as a nice name to make the use of mpl_colors and mpl_colormap more easy to understand e.g.
import palettable.colorbrewer.sequential.BuPu_9 as color_scale
Then access it as
color_scale.mpl_colormap
That way, you can keep your code DRY and change the colors with only one change.
Layout (in response to comments)
The colorbar may be a little big (certainly tall) for aesthetic ideal. There are a few possible options to do that. I'll point you to two:
The "right" way to do it is probably to use a Gridspec
You could use your existing approach, but increase the number of rows and have the colorbar still in one row, while the other elements span more rows than they do currently.
I've implemented that with 9 rows, an extra column (so that the month labels don't get lost) and the colorbar on the bottom row, spanning 2 less columns than the main figure. I've also used tight_layout with w_pad=0.0 to avoid label clashes. You can play with this to get your exact preferred size. New code here.
This gives:
:
There are functions to do this in matplotlib.colorbar. With some specific code from your example, I could give you a better answer, but you'll use something like:
myColorbar = matplotlib.colorbar.ColorbarBase(myAxes, cmap=myColorMap,
norm=myNorm,
orientation='vertical')

Plotting two functions simultaneously with matplotlib

basically I want to graph two functions
g1 = x*cos(x*pi)
g2 = 1 - 0.6x^2
and then plot the intersection, I already have a module that takes inputs close to the two lines intersections, and then converges to those points (there's four of them)
but I want to graph these two functions and their intersections using matplotlib but have no clue how. I've only graphed basic functions. Any help is greatly appreciated
Assuming you can get as far as plotting one function, with x and g1 as numpy arrays,
pylab.plot(x,g1)
just call plot again (and again) to draw any number of separate curves:
pylab.plot(x,g2)
finally display or save to a file:
pylab.show()
To indicate a special point such as an intersection, just pass in scalars for x, y and ask for a marker such 'x' or 'o' or whatever else you like.
pylab.plot(x_intersect, y_intersect, 'x', color="#80C0FF")
Alternatively, I often mark a special place along x with a vertical segment by plotting a quick little two-point data set:
pylab.plot( [x_special, x_special], [0.5, 1.9], '-b' )
I may hardcode the y values to look good on a plot for my current project, but obviously this is not reusable for other projects. Note that plot() can take ordinary python lists; no need to convert to numpy arrays.
If you can't get as far as plotting one function (just g1) then you need a basic tutorial in matplot lib, which wouldn't make a good answer here but please go visit http://matplotlib.org/ and google "matplotlib tutorial" or "matplotlib introduction".

Categories

Resources