I have several arrays for which I calculate the Frobenius norm. Then I simply draw a graph of these calculated norms vs the index of their corresponding arrays. The problem is that when the plot window pops out, there is no graph on it. But, when I add a styling for my plot, it shows the graph. I also tried to use save figure, but the saved figure just shows a window without any graph on it. The last thing that I tried was to print out the array of the calculated norms, defining it as a numpy array and draw it vs the array of the corresponding indices and it shows me the graph! So, my question is why I cannot draw the graph with pylot plot function.
This is what I get when I print out the array of calculated norms:
FrobNorm=[[ -3.27415727e-01 2.83421670e+00 -2.59669415e+00 -3.83713705e+00
-1.11064367e+00 -9.83842479e+00 9.64202990e+00 -3.66747069e+00
9.49022713e+00 -3.58659316e+00 4.28355911e+00 -4.58104577e+00
-4.26765959e+00 -6.54306600e-01 4.31816208e+00 1.08043604e+01
3.36647201e+01 -9.47369163e+00 1.41183067e+01 1.75464238e+00
6.84732164e+00 -1.13034176e+01 -1.83641151e+01 -6.07528575e+01
-2.11765783e+01 -3.46253416e+01 -3.50911001e+01 -1.78855570e+01
2.00630855e+01 1.90068192e+01 3.33858144e-01 -1.75526132e+01
-1.34355117e+01 -8.39318642e+00 -1.96338714e+01 -5.80396650e+01
-1.52712614e+01 -7.95109842e+00 -1.14383666e+01 -4.29497153e+00
-1.97874688e+01 -1.32635215e+01 3.10595354e+00 3.30488466e-01
1.24957569e+00 2.32608957e+01 -5.12962561e-01 3.23879652e+00
1.80536181e+01 1.64091731e+01 2.46815567e+01 2.01190758e+01
2.25210602e+01 1.92789009e+01 4.32809711e+01 1.24060317e+02
5.11700004e+00 2.56249967e+00 3.27317719e+01 3.01294858e+01
2.96865339e+01 2.01666494e+01 -1.75473758e+00 -9.73091969e+00
-1.51961382e+01 8.11369952e+00 -1.74469244e+01 5.94097932e+00
-5.43142631e+00 -4.40072150e+00 -1.51168549e+01 -5.58957352e+00
-2.34872324e+04 9.19836593e+02 6.76833045e+03 7.59304882e+03
1.77573454e+03 9.71109062e+02 1.63742243e+03 3.70221807e+02
1.01405251e+03 4.06811235e+02 1.45049823e+02 1.43212472e+02
8.88928849e+01 3.10859242e+02 4.79435420e+01 6.86347162e+01
2.14372829e+01 5.43555421e+01 1.39810283e+01 9.51714116e+00
4.98563968e+01 4.02058896e+01 1.61359027e+02 7.91939932e+00
1.73949723e+01 5.19412047e+01 1.89645369e+01 2.25526021e+01
1.36734416e+01 3.13646035e+01 2.02633125e+01 5.16259077e+01
7.34024536e+01 2.01376746e+01 8.50796026e+00 1.76689397e+01
5.32159344e+01 1.75182361e+01 2.38797434e+01 2.21623152e+01
2.15496171e+01 1.56287225e+01 7.12160153e+01 1.20319418e+01
-2.14376043e-01 -2.16844613e+00 7.31383577e+00 9.60358643e+00
1.53346738e+01 -1.75376507e+01 -4.23607412e+01 -1.34004685e+01
-5.74096286e+01 -1.88056408e+01 1.24411854e+00 -2.20228598e+00
-1.44691587e+01 -4.02906454e+00 -7.06859151e+00 -9.28329296e-01
3.97785623e+00 -1.17290825e+01 5.30538782e+00 -1.30573008e+00
2.57332085e-01 -5.03652416e+00 -8.01889243e+00 -4.21210481e+00
7.97575488e+00 1.33063141e+01 1.94559898e+01 1.30643051e+01
1.39963350e+00 1.31746057e+01 4.87291463e-01 7.62221548e+00
1.90832548e+00 -9.17783469e+00 -6.74190235e+00 -5.18322407e+00
2.08694160e+00 -8.32251763e+00 -3.41052019e+01 -4.07077413e+00
-5.35572194e+00 -1.00300755e+01 -1.85180723e+00 -2.85137343e+00
-2.92087149e+00 5.82955457e+00 4.00575111e+00 1.17418771e+01
2.13152055e+01 6.74130687e+00 2.89890044e+00 9.56403257e+00
9.49920338e+00 -4.90698086e+00 -4.31125932e-01 7.43422603e+00
-1.36522668e+00 6.71239870e+00 2.97819245e+01 2.70232682e+00
1.43525496e+01 7.69774164e-01 6.11231825e+00 1.48208154e+00
-2.23136432e+00 4.61075719e+00 -3.59137897e+01 -1.62455157e+01
-6.07367620e+01 -2.62556836e+00 -1.64717047e-01 -1.33588774e+01
-8.23873116e+00 -4.69412397e+00 -8.64679071e+00 -7.05601974e+00
9.42962930e+00 -1.08717341e+01 -5.27810809e+01 -8.69225245e+00
-4.99076301e+00]]
When I plot the graph vs its indices array, I only get the window with no graph:
plt.plot(numVec,FrobNorm)
plt.show()
But, when I use a styling for the plot it shows the graph (something like scatter plot, which I am not interested in):
plt.plot(numVec,FrobNorm,'ro')
plt.show()
Now, I print the array of calculated norms. comma separate it, and define a numpy array with its elements and simply draw the graph of this numpy array and the corresponding array of indices and I get:
I want to get the same thing in the first place. My question is why I cannot get any graph when I plot the calculated norms. As, I said I am not looking for the scatter graph, like in the second figure, which surprisingly is something that I can get only by changing the styling of the figure.
I think I got it. I used squeeze and it works. So, the plot line should be changed like this:
plt.plot(np.squeeze(NumVec),np.squeeze(FrobNorm))
I still don't understand why, but this is what I guess; I think somehow the format of the numpy arrays that were produced, was in the way that plot function could only see the range of the values without having access to every single element of the arrays. When I didn't use the squeeze function, I got the window without the plot, but the range of the x and y axis were the same as when I could draw the plot in the second and third figures. This is only a guess, I hope someone could help me with the real reason. Thank you for all the feedback!
Related
I am using data from cdasws to plot dynamic spectra. I am following the example found here https://cdaweb.gsfc.nasa.gov/WebServices/REST/jupyter/CdasWsExample.html
This is my code which I have modified to obtain a dynamic spectra for STEREO.
from cdasws import CdasWs
from cdasws.datarepresentation import DataRepresentation
import matplotlib.pyplot as plt
cdas = CdasWs()
import numpy as np
datasets = cdas.get_datasets(observatoryGroup='STEREO')
for index, dataset in enumerate(datasets):
print(dataset['Id'], dataset['Label'])
variables = cdas.get_variables('STEREO_LEVEL2_SWAVES')
for variable_1 in variables:
print(variable_1['Name'], variable_1['LongDescription'])
data = cdas.get_data('STEREO_LEVEL2_SWAVES', ['avg_intens_ahead'],
'2020-07-11T02:00:00Z', '2020-07-11T03:00:00Z',
dataRepresentation = DataRepresentation.XARRAY)[1]
print(data)
plt.figure(figsize = (15,7))
# plt.ylim(100,1000)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.yscale('log')
sorted_data.transpose().plot()
plt.xlabel("Time",size=18)
plt.ylabel("Frequency (kHz)",size=18)
plt.show()
Using this code gives a plot that looks something like this,
My question is, is there anyway of plotting this spectrum only for a particular frequency? For example, I want to plot just the intensity values at 636 kHz, is there any way I can do that?
Any help is greatly appreciated, I dont understand xarray, I have never worked with it before.
Edit -
Using the command,
data_stereo.avg_intens_ahead.loc[:,625].plot()
generates a plot that looks like,
While this is useful, what I needed is;
for the dynamic spectrum, if i choose a particular frequency like 600khz, can it display something like this (i have just added white boxes to clarify what i mean) -
If you still want the plot to be 2D, but to include a subset of your data along one of the dimensions, you can provide an array of indices or a slice object. For example:
data_stereo.avg_intens_ahead.sel(
frequency=[625]
).plot()
Or
# include a 10% band on either side
data_stereo.avg_intens_ahead.sel(
frequency=slice(625*0.9, 625*1.1)
).plot()
Alternatively, if you would actually like your plot to show white space outside this selected area, you could mask your data with where:
data_stereo.avg_intens_ahead.where(
data_stereo.frequency==625
).plot()
Here is a sample of my data:
Time,Value,Name,Type
0,6.9,A,start
40,6.9,A,start
60,6.9,A,start
0,0.01,B,start
40,0.01,B,start
60,0.01,B,start
0,1.0,C,start
40,1.0,C,start
60,1.0,C,start
0,0.08,D,start
40,0.08,D,start
60,0.08,D,start
0,0.000131,E,End
40,0.00032,E,End
60,0.99209,E,End
0,0.002754,F,End
40,0.00392,F,End
60,0.01857,F,End
0,0.003,G,End
40,0.00516,G,End
60,0.00746,G,End
0,0.00426,H,End
40,0.0043,H,End
60,0.0095,H,End
0,0,I,End
40,0.0017,I,End
60,0.0183,I,End
And my code below:
import plotly.express as px
import pandas as pd
df=pd.read_csv('tohistogram.csv')
fig_bar = px.histogram(df,x='Name',y='Value',animation_frame='Time',color='Name',facet_row='Type')
fig_bar.update_layout(yaxis_title="value")
fig_bar.update_xaxes(matches=None)
fig_bar.for_each_xaxis(lambda xaxis: xaxis.update(showticklabels=True))
fig_bar.show()
`
Fig1:
Fig2:
With the data point listed above, I wanted 2 histogram separated by type (start,end) in one frame with one animation_frame
Tried the above code, as one can see from the image I could partial achieve but from Fig1: second histogram has (A,B,C,D),excepted just E to I.
2. Figure 2 was when I played the run button and auto scaled then I see A-D are gone and only E-I,
This is what I wanted to achieve in the first place itself, before running 2 histogram should sort as per 'Type'
A. Is it possible I tried couple of things like removed color
fig_bar = px.histogram(df,x='Name',y='Value',animation_frame='Time',facet_row='Type')
histogram sorts as per 'Type' of course no color but no label in second x-axis.
B.fig_bar = px.histogram(df,x='Name',y='Value',color='Name',facet_row='Type')
It sorts but no animation
What I am trying is it possible?
need 2 histogram with in the same frame sorted by 'Type',color and animation_frame?
C. Only if possible then, how to label y-axis of the first histogram from sumofValues to user-defined axis name and also have its own axis range.
D.I didn't come across any example but on the histogram, on mouse hover can I show another simple line graph image instead of text or value?
Thank you
I am trying to create a 2D histogram with square bins (instead of hex elements) and I'm using quad to do so.
First, I create a 2D histogram using numpy (not shown for brevity).
Then I plot it using the quad glyph:
def plotHist2D(self,name):
"""
Creates a 2D histogram figure in Bokeh.
Parameters
----------
name : string
The name of one of the column data sources in self.files.
Returns
-------
A bokeh plot object.
"""
cds = ColumnDataSource(self.makeHist2D(name))
plot_cmap = linear_cmap('tops','Turbo256',0,1,)
bar_cmap = LinearColorMapper(palette='Turbo256',low=0,high=1)
p = figure(plot_height=350,plot_width=350,
title='kW/mm^2', x_axis_label='x (m)',
y_axis_label='y (m)',
x_range=(-0.05,0.05),
y_range=(-0.05,0.05),
output_backend="webgl",
toolbar_location="above")
p.quad(top='yrights',bottom='ylefts',left='xlefts',right='xrights',
fill_color=plot_cmap,line_color=plot_cmap,
line_width=0.1,line_alpha=1.0,
alpha=1.0,source=cds)
color_bar = ColorBar(color_mapper=bar_cmap,width=8,
border_line_color=None,location=(0,0))
p.add_layout(color_bar,'right')
return p
This functions, in that it creates a figure, but the figure has unpleasant lines at the border between the quad elements.
I cannot find any combination of settings for the parameters line_width, line_color, and line_alpha that will get rid of these lines. Is there any combination of settings that will eliminate those lines entirely?
If not, how should I be creating this 2D histogram with square bins?
The trick to this is to use line_color with the same color mapper and not set line_width too small.
The following call to quad works.
p.quad(top='yrights',bottom='ylefts',left='xlefts',right='xrights',
fill_color=plot_cmap,
line_color=plot_cmap,
line_width=1.0,line_alpha=1.0,
alpha=1.0,source=cds)
The desired plot:
I thought I had tried every permutation before asking this question. I'm not sure why a smaller line_width makes the lines more visible. As #EugenePakhomov suggests you can also just leave out the line_width entirely. Presumably this is because the default setting is large enough not to cause the "meshing."
I am plotting a 2D histogram to show, for example, the concentration of lightnings (given by their position registered in longitude and latitude). The number of data points is not too large (53) and the result is too coarse. Here is a picture of the result:
For this reason, I am trying to find a way to weight in data from surrounding bins. For example, there is a bin at longitude = 130 and latitude = 34.395 with 0 lightning registered, but with several around it. I would want this bin to reflect somehow the concentration around it. In other words, I want to smooth the data by having overlapping bins (so that a data point can be counted more than once, by different contiguous bins).
I understand that hist2d has the input option for "weights", but this would only work to make a data point more "important" within its bin.
The simplified code is below and I can clarify anything needed.
import numpy as np
import matplotlib.pyplot as plt
# Here are the data, to experiment if needed
longitude = np.array([119.165, 115.828, 110.354, 117.124, 119.16 , 107.068, 108.628, 126.914, 125.685, 116.608, 122.455, 116.278, 123.43, 128.84, 128.603, 130.192, 124.508, 121.916, 133.245, 125.088, 126.641, 127.224, 113.686, 129.376, 127.312, 121.353, 117.834, 125.219, 138.077, 153.299, 135.66 , 128.391, 118.011, 117.313, 119.986, 118.619, 119.178, 120.295, 121.991, 123.519, 135.948, 132.224, 129.317, 135.334, 132.923, 129.828, 139.006, 140.813, 116.207, 139.254, 120.922, 112.171, 143.508])
latitude = np.array([34.381, 34.351, 34.359, 34.357, 34.364, 34.339, 34.351, 34.38, 34.381, 34.366, 34.373, 34.366, 34.369, 34.387, 34.39 , 34.39 , 34.386, 34.371, 34.394, 34.386, 34.384, 34.387, 34.369, 34.4 , 34.396, 34.37 , 34.374, 34.383, 34.403, 34.429, 34.405, 34.385, 34.367, 34.36 , 34.367, 34.364, 34.363, 34.367, 34.367, 34.369, 34.399, 34.396, 34.382, 34.401, 34.396, 34.392, 34.401, 34.401, 34.362, 34.404, 34.382, 34.346, 34.406])
# Number of bins
Nbins = 15
# Plot histogram of the positions
plt.hist2d(longitude,latitude, bins=Nbins)
plt.plot(longitude,latitude,'o',markersize = 8, color = 'k')
plt.plot(longitude,latitude,'o',markersize = 6, color = 'w')
plt.colorbar()
plt.show()
Perhaps you're getting confused with the concept of 2D-histogram, or histogram. Besides the fact a histogram is a bar plot groupping data into plot, it is also a dicretized estimation of a probability funtion. In your case, the presence probability. For this reason, I would not try to overlap histograms.
Moreover, because the histogram is 'discrete', it will be necessarily coarse. Actually, the resolution of a histogram is an important parameter regarding the desired visualization.
Going back to your question, if you want to disminish the coarse effect, you may to simply want to play on Nbins.
Perhaps, other graph type would suit better your usage: see this gallery and the 2D-density plot with shading.
This question seems to have been asked a few times already, but for some reason it doesn't work for me.
I am making a plt.errorbar plot from the arrays of points results['logF'], results['R'] which are in a pandas DataFrame. I want to scale the colour of the points with a third variable results['M']. I've tried various things but I always get some kind of error, I'm clearly doing something wrong but I can't find any place that explains exactly what is required.
So firstly, results['M'] are a bunch of floats in the range 0 - 13. So as I understand it, I need to normalise them, which I did with matplotlib.colors.Normalise(vmin=0.0, vmax=13.0).
When I try plotting with the following code:
results = get_param_results(totP)
colormap = mlb.colors.Normalize(vmin=0.0, vmax=13.0)
mass_color = np.array(colormap(results['M']))
#import pdb; pdb.set_trace()
plt.errorbar(results['logF'], results['R'], marker='x',
mew=1.2, ms=3.5, capsize=2, c=mass_color,
yerr=[results['logF_l'], results['logF_u']],
xerr=[results['R_l'], results['R_u']],
elinewidth=1.2)
I get an error ValueError: Color array must be two-dimensional. Not sure why it should be two dimensional. In other stackoverflow threads, they pass one dimensional arrays and it's fine.
Using a different form (basically just copying the style from another stackoverflow thread), I write:
results = get_param_results(totP)
colormap = mlb.colors.Normalize(vmin=0.0, vmax=13.0)
#import pdb; pdb.set_trace()
plt.errorbar(results['logF'], results['R'], marker='x',
mew=1.2, ms=3.5, capsize=2, c=results['M'], cmap=mlb.cm.jet, norm=colormap
yerr=[results['logF_l'], results['logF_u']],
xerr=[results['R_l'], results['R_u']],
elinewidth=1.2)
I get a different error, TypeError: There is no Line2D property "cmap"
I don't understand this either (it also doesn't recognise norm), scatter should definitely have the norm and cmap arguments.
Basically, I can't find any great explanations or tutorials on how to get the color scale with an errorbar plot. Can someone help?
Thanks.
EDIT:
Been asked to post the data I'm using. This is the .head() table of the results DataFrame (the full one has 257 rows).
R R_l R_u F F_l F_u \
0 1.486045 0.068775 0.068508 2.999561e+06 488301.994185 496244.025108
1 0.992957 0.062303 0.062664 4.583829e+04 6652.971755 6636.980813
2 1.422328 0.029163 0.029323 2.068257e+06 186692.732530 187685.738474
3 1.326820 0.094840 0.093995 1.049490e+06 185012.117516 184290.913875
4 0.887831 0.013825 0.013939 5.883107e+05 52537.237452 52492.326206
M M_l M_u logF logF_l logF_u
0 1.030471 0.122698 0.123368 6.471041 0.071150 0.072506
1 2.753916 0.157837 0.160584 4.656550 0.063427 0.063404
2 2.344767 0.340987 0.345171 6.313780 0.039261 0.039548
3 0.918979 0.069931 0.069984 6.014049 0.077296 0.077189
4 1.310289 0.076565 0.076805 5.767830 0.038848 0.038895
So basically:
results['M'] = array([ 1.03047146, 2.75391626, 2.34476658, 0.91897949, 1.31028926])
results['logF'] = array([ 6.47104102, 4.65655021, 6.31377955, 6.01404944, 5.76782953])
results['R'] = array([ 1.48604489, 0.99295713, 1.42232837, 1.3268205 , 0.88783067])
and etc... (for the error bars, just use an array([1,1,1,1,1]) to save time or something).
I reran the code, by replacing results with the above, and it still gives me ValueError: Color array must be two-dimensional
I'm not sure what the second dimension should be. Is there something obvious that I'm doing wrong when I'm calling the errorbar plot function?