Set Y labels from a text file - matplotlib - python

Using matplotlib, I have plotted the following graph from a text file. I have a series of values that are stored in another text file that I want to use the represent the Y axis on this graph.
The values will therefore be this:
Essentially, instead of displaying 0, 24, 40, ....., 16 it will show the frequencies represented in the text file, between 0, 1000, ....., 6000
Any help would be greatly thankful!

Related

Values on the X-axis shifting toward to zero

I generated a graph in which the values on the X-axis start from 0 and go to 1000, fifty by fifty, like 0, 50, 100, 150, ..., 900, 950, 1000. However, I want to divide the values on the X-axis by 10 (I want to convert the values on the x-axis into 0, 5, 10, 15, ..., 90, 95, 100).
Index_time is 1001
index_time = len(df.index)
ax.plot(np.arange(index_time), df["SoluteHBonds"], color="blue")
ranges=(np.arange(0,index_time,50))
ax.set_xticks(ranges)
When I divide the values on the X-axis via np.true_divide(ranges, 10), all the values on the X-axis shift toward 0
On the other hand, I tried to create a list first and then divide each element by 10 but the result is still the same.
lst_range=list(range(0,int((index_time-1)/10),5))
ax.set_xticks([time/10 for time in lst_range])
What could be the problem or what is the thing that I am missing in this case?
Thanks in advance!

Extracting data from a histogram with custom bins in Python

I have a data set of distances between two particles, and I want to bin these data in custom bins. For example, I want to see how many distance values lay in the interval from 1 to 2 micrometers, and so on. I wrote a code about it, and it seems to work. This is my code for this part:
#Custom binning of data
bins= [0,1,2,3,4,5,6,7,8,9,10]
fig, ax = plt.subplots(n,m,figsize = (30,10)) #using this because I actually have 5 histograms, but only posted one here
ax.hist(dist_from_spacer1, bins=bins, edgecolor="k")
ax.set_xlabel('Distance from spacer 1 [µm]')
ax.set_ylabel('counts')
plt.xticks(bins)
plt.show()
However, now I wish to extract those data values from the intervals, and store them into lists. I tried to use:
np.histogram(dist_from_spacer1, bins=bins)
However, this just gives how many data points are on each bin and the bin intervals, just like this:
(array([ 0, 0, 44, 567, 481, 279, 309, 202, 117, 0]),
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
How can I get the exact data that belong to each histogram bin?
Yes, np.histogram calculates what you need for a histogram, and hence the specific data points are not necessary, just bins' boundaries and count for each bin. However, the bins' boundaries is sufficient to acheive what you want by using np.digitizr
counts, bins = np.histogram(dist_from_spacer1)
indices = np.digitize(dist_from_spacer1, bins)
lists = [[] for _ in range(len(bins))]
[lists[i].append(x) for i, x in zip(indices, dist_from_spacer1)
In your case, the bins' boundaries are predefined, so you can use np.digitize directly

Altair Layer Chart Y Axis Not Resolving to Same Scale

I'm trying to plot data and compare it to a threshold set at a fixed value. When creating a layered chart, the y axis does not appear to hold for both layers. The same goes for hconcat.
I found this issue which mentions .resolve_scale(y='shared'), but that doesn't seem to work. When I specify the rule to be at 5, it appears above 15.
np.random.seed(42)
df = pd.DataFrame({
'x': np.linspace(0, 10, 500),
'y': np.random.randn(500).cumsum()
})
base = alt.Chart(df)
line = base.mark_line().encode(x='x', y='y')
rule = base.mark_rule().encode(y=alt.value(5))
alt.layer(line, rule).resolve_scale(y='shared')
To get the rule to appear at the value 5, I have to set it at 110.
rule = base.mark_rule().encode(y=alt.value(110))
alt.layer(line, rule).resolve_scale(y='shared')
How can I edit the chart so that the rule shows at the y-value specified?
Altair scales map a domain to a range. The domain describes the extent of the data values, while the range describes the extent of the visual features to which those values are mapped. For color encodings, the range might be "red", "blue", "green", etc. For positional encodings like x and y, the range is the pixel position of the mark on the chart.
When you use alt.value, you are specifying the range value, not the domain value. This is why you can use an encoding like color=alt.value('red'), to specify that you want the mark to appear as the color red. When you do y=alt.value(5), you are saying you want the mark to appear 5 pixels from the top of the y-axis.
Recent versions of Vega-Lite added the ability to specify the domain value via datum rather than value, but unfortunately Altair does not yet support this, and so the only way to make this work is to have a data field with the desired value. For example:
line = base.mark_line().encode(x='x', y='y')
rule = alt.Chart(pd.DataFrame({'y': [5]})).mark_rule().encode(y='y')
alt.layer(line, rule).resolve_scale(y='shared')

Matplotlib pyplot: plotting array mixes up y axis labels

I'm making a simple program in Python to plot two lists of integers, one data one the time axis.
The time list goes from 0 to 3 in increments of 1, while the data list consists of: 5,10, 3,12. I used print statements to verify that the lists do have the values mentioned above.
plt.plot(time_axis,data_array, 'ro')
plt.axis([0, 20, 0, 20])
plt.show()
However, as shown in the image, the plot y axis is labeled in the order that my data list is processed, not in ascending order: 5,10,3,12
Is there a way to make the y axis go in equal increasing increments upto 20?
EDIT: I noticed that this mixup only happens when i use the list as a parameter: eg,
plt.plot([0,1,2,3],[5,10,3,12],'bo') #gives the correct graph while
plt.plot(time_axis,data_array,'bo') #gives the incorrect graph,
Even though the two lists time_axis and data_array contain the same values.
Tracing back my error, I was importing my data values from a text file, and the parsing was done incorrectly, so the data values were not ints. The char values were in the format '5\n',etc so numplot was getting confused. Fixing that solved the issue!
I feel like you're omitting the code which is making this screwy, but here's what I did:
import matplotlib.pyplot as plt
time_axis = range(0,4)
data_array=[5,10,3,12]
plt.plot(time_axis,data_array, 'ro')
plt.axis([0, 20, 0, 20])
plt.show()
This produces the image:
which seems to be what you were aiming for.

Why normalized EXR renderings of surface Normals look different than PNG renderings?

I render surface Normals using Cycles and store the results in EXR format. The values in the EXR format are within the range of [-1, 1] meaning that I cannot directly store the values in a PNG file. Here's how I read the .exr files and store store the values in a numpy array:
import OpenEXR, array, Imath
exrFile = OpenEXR.InputFile('normal.exr')
FLOAT = Imath.PixelType(Imath.PixelType.FLOAT)
(RGB) = [array.array('f', exrFile.channel(Chan, FLOAT)).tolist() for Chan in ("R", "G", "B") ]
normalNPArray = np.array(RGB)
normalNPArray = normalNPArray.reshape((3, resolution, resolution))
I normalize the values as follow and store the surface Normal as a PNG image:
normalNPArray += 1
normalNPArray /= 2
normalNPArray *= 255
normalNPArray = normalNPArray.astype(np.uint8)
im = Image.fromarray(normalNPArray.transpose(1, 2, 0), mode='RGB')
im.save('temp.png')
Here's what I get after opening the stored image:
If I simply ignore the values below zero (remove/comment the first two lines) I get the following:
However, if I directly store the surface Normal as a PNG image instead of EXR I get the following:
I wonder, how can I get a visualization that looks like the PNG rendering? How does Blender normalize the values?
I have a friend that helps me with this i hope is useful to you:
When making normal maps for a renderer or shader the following needs to be considered :
The "space" in which the normals are defined. That can be world space, object space, or tangent space.
The ordering of the axes the renderer expects [ x, y, z ] vs [x , -y, z] ,etc.
The range can be [0,1] or [-1,1].
And possibly how Alphas are handled.
One can read about the format and figure it out. Or simply get an existing normal map the works and figure out the format visually. For example, if the working maps look light blue, they are most likely in tangent space whereas world space has more pure reds, greens, and blues.
Most people use tangent space normal maps because it allows for deformations. I believe Blender gives you the option for all three HERE
Note:
I check the image that you store (image 1) and the background is not 0. Should be zero if the original image has -1 background. So you are doing something wrong in the code. It would be pretty helpful if you post the EXR image so i can do some test.
As keltar mentioned in one of the comments, It turns out Numpy does not automatically set the negative values to 0 when casting the array type to uint8. For instance, suppose I have a numpy array as follow:
array([ 46.73017823, -250.31618571, -247.44416527, 97.52841554,
-204.92988386, 191.09452493, 103.15708521, -86.10470495,
46.211924 , -195.30653599, 240.44499889, -169.42729244,
210.44996545, -182.04892973, -166.20581924, -221.11524425,
164.79367242, -199.80888341, 94.1786936 , 43.45477102])
I was expecting that doing normalNPArray = normalNPArray.astype(np.uint8) will automatically set the negative values to 0 since uint8 does not naturally support negative values. However, casting the array as np.uint8 gives me the following:
array([ 46, 6, 9, 97, 52, 191, 103, 170, 46, 61, 240, 87, 210,
74, 90, 35, 164, 57, 94, 43], dtype=uint8)
Doing normalNPArray[normalNPArray < 0] = 0 and then casting the array to np.uint8 will resolve the issue.

Categories