I am plotting some data from the cdasws.datarepresentation. I have plotted the plots using matlabplotlib but i cannot figure out how to flip the axes and i couldnt find it in the documentation.
here is the code
%pip install xarray
%pip install cdflib
%pip install cdasws
from cdasws import CdasWs
from cdasws.datarepresentation import DataRepresentation
import matplotlib.pyplot as plt
cdas = CdasWs()
datasets = cdas.get_datasets(observatoryGroup='Wind')
for index, dataset in enumerate(datasets):
print(dataset['Id'], dataset['Label'])
if index == 5:
break
variables = cdas.get_variables('WI_H1_WAV')
for variable_1 in variables:
print(variable_1['Name'], variable_1['LongDescription'])
data_1 = cdas.get_data('WI_H1_WAV', ['E_VOLTAGE_RAD1'],
'2020-07-11T02:00:00Z', '2020-07-11T03:00:00Z',
dataRepresentation = DataRepresentation.XARRAY)[1]
print(data_1)
### this is a bit of code to obtain the first part of the lower frequency data
print(data_1.E_VOLTAGE_RAD1)
data_1['E_VOLTAGE_RAD1'].plot()
The plot looks like this.
Is there a way to flip the axes?
I tried
plt.gca().invert_xaxis()
but that didnt help
when you plot a 2-dimensional array, the default plotting handler is xr.DataArray.plot.pcolormesh, so arguments will be handled by that function. To see the full set of available plotting methods and the default handler for 1, 2, and 3 dimensions, see xr.DataArray.plot and the Plotting section of the user guide.
The first two (optional) arguments to DataArray.plot.pcolormesh are the dims that get interpreted as the plot's x and y axes. From the API documentation:
x (str, optional) – Coordinate for x axis. If None, use darray.dims[1].
y (str, optional) – Coordinate for y axis. If None, use darray.dims[0].
So in your case, just provide the dimension names. I'm not sure what they're called in your data, but it should be something like this:
data_1['E_VOLTAGE_RAD1'].plot(x='epoch', y='frequency')
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()
I am having difficulties accessing (the right) data when using holoviews/bokeh, either for connected plots showing a different aspect of the dataset, or just customising a plot with dynamic access to the data as plotted (say a tooltip).
TLDR: How to add a projection plot of my dataset (different set of dimensions and linked to main plot, like a marginal distribution but, you know, not restricted to histogram or distribution) and probably with a similar solution a related question I asked here on SO
Let me exemplify (straight from a ipynb, should be quite reproducible):
import numpy as np
import random, pandas as pd
import bokeh
import datashader as ds
import holoviews as hv
from holoviews import opts
from holoviews.operation.datashader import datashade, shade, dynspread, spread, rasterize
hv.extension('bokeh')
With imports set up, let's create a dataset (N target 10e12 ;) to use with datashader. Beside the key dimensions, I really need some value dimensions (here z and z2).
import numpy as np
import pandas as pd
N = int(10e6)
x_r = (0,100)
y_r = (100,2000)
z_r = (0,10e8)
x = np.random.randint(x_r[0]*1000,x_r[1]*1000,size=(N, 1))
y = np.random.randint(y_r[0]*1000,y_r[1]*1000,size=(N, 1))
z = np.random.randint(z_r[0]*1000,z_r[1]*1000,size=(N, 1))
z2 = np.ones((N,1)).astype(int)
df = pd.DataFrame(np.column_stack([x,y,z,z2]), columns=['x','y','z','z2'])
df[['x','y','z']] = df[['x','y','z']].div(1000, axis=0)
df
Now I plot the data, rasterised, and also activate the tooltip to see the defaults. Sure, x/y is trivial, but as I said, I care about the value dimensions. It shows z2 as x_y z2. I have a question related to tooltips with the same sort of data here on SO for value dimension access for the tooltips.
from matplotlib.cm import get_cmap
palette = get_cmap('viridis')
# palette_inv = palette.reversed()
p=hv.Points(df,['x','y'], ['z','z2'])
P=rasterize(p, aggregator=ds.sum("z2"),x_range=(0,100)).opts(cmap=palette)
P.opts(tools=["hover"]).opts(height=500, width=500,xlim=(0,100),ylim=(100,2000))
Now I can add a histogram or a marginal distribution which is pretty close to what I want, but there are issues with this soon past the trivial defaults. (E.g.: P << hv.Distribution(p, kdims=['y']) or P.hist(dimension='y',weight_dimension='x_y z',num_bins = 2000,normed=True))
Both are close approaches, but do not give me the other value dimension I'd like visualise. If I try to access the other value dimension ('x_y z') this fails. Also, the 'x_y z2' way seems very clumsy, is there a better way?
When I do something like this, my browser/notebook-extension blows up, of course.
transformed = p.transform(x=hv.dim('z'))
P << hv.Curve(transformed)
So how do I access all my data in the right way?
Plotting a discrete xarray DataArray variable in a Dataset with xr.plot.scatter() yields a legend in which the discrete values are ordered arbitrarily, corresponding to unpredictable colour assignment to each level. Would it be possible to specify a specific colour or position for a given discrete value?
A simple reproducible example:
import xarray as xr
# get a predefined dataset
uvz = xr.tutorial.open_dataset("eraint_uvz")
# select a 2-D subset of the data
uvzr = uvz.isel(level=0, month=0, latitude=slice(150, 242),
longitude=slice(240, 300))
# define a discrete variable based on levels of a continuous variable
uvzr['zone'] = 'A'
uvzr['zone'] = uvzr.zone.where(uvzr.u > 30, other='C')
uvzr['zone'] = uvzr.zone.where(uvzr.u > 10, other='B')
# do the plot
xr.plot.scatter(uvzr, x='longitude', y='latitude', hue='zone')
Is there a way to ensure that the legend entries are arranged 'A', 'B', 'C' from top to bottom, say? Or ensure that A is assigned to blue, and B to orange, for example?
I know I can reset the values of the matplotlib color cycler, but for that to be useful I first need to know which order the discrete values will be plotted in.
I'm using xarray v2022.3.0 on python 3.8.6. With an earlier version of xarray (I think 0.16) the levels were arranged alphabetically.
I found an ugly workaround using xarray.Dataset.stack and xr.where(..., drop=True), in case anyone else is stuck with a similar problem.
import numpy as np # for unique, to cycle through values
import matplotlib.pyplot as plt # to get a legend
# instead of np.unique you could pass an iterable of your choice
# specifying the order
for value in np.unique(uvzr.zone):
# convert to a 1-D dataframe with a co-ordinate including all
# unique combinations of latitude-longitude values
uvzr_stacked = uvzr.stack({'location':('longitude', 'latitude')})
# now select only those grid points in zone value
uvzr_stacked = uvzr_stacked.where(uvzr_stacked.zone == value,
drop=True)
# the plotting function can't see the original dims any more;
# a new name is required, however
uvzr_stacked['lat'] = uvzr_stacked.latitude
uvzr_stacked['lon'] = uvzr_stacked.longitude
# plot!
xr.plot.scatter(uvzr_stacked, x='lon', y='lat', hue='zone',
add_guide=False)
plt.legend(title='zone')
I have a .dat file whose structure is given by three columns that I suppose to refer to be x, y and z = f(x,y), respectively.
I want to make a density plot out of this data. While looking for some example that could help me out, I came across the following posts:
How to plot a density map in python?
matplotlib plot X Y Z data from csv as pcolormesh
What I have tried so far is the following:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
x, y, z = np.loadtxt('data.dat', unpack=True, delimiter='\t')
N = int(len(z)**.5)
z = z.reshape(N, N)
plt.imshow(z, extent=(np.amin(x), np.amax(x), np.amin(y), np.amax(y)),cmap=cm.hot)
plt.colorbar()
plt.show()
The file data can be accessed here: data.dat.
When I run the script above, it returns me the following error message:
cannot reshape array of size 42485 into shape (206,206)
Can someone help me to understand what I have done wrong and how to fix it?
The reason is that your data is not exactly 260*260, but your z is larger.
One option is to slice the z, but you are missing data when you are doing that.
And if that is what you want you are no longer using your x,y values.
z = z[:N**2].reshape(N,N)
In the link you posted I saw this statement:
I assume here that your data can be transformed into a 2d array by a simple reshape. If this is not the case than you need to work a bit harder on getting the data in this form.
The assumption does not hold for your data.
I'm using openturns to find the best fit distribution for my data. I got to plot it alright, but the X limit is far bigger than I'd like. My code is:
import statsmodels.api as sm
import openturns as ot
import openturns.viewer as otv
data = in_seconds
sample = ot.Sample(data, 1)
tested_factories = ot.DistributionFactory.GetContinuousUniVariateFactories()
best_model, best_bic = ot.FittingTest.BestModelBIC(sample, tested_factories)
print(best_model)
graph = ot.HistogramFactory().build(sample).drawPDF()
bestPDF = best_model.drawPDF()
bestPDF.setColors(["blue"])
graph.add(bestPDF)
name = best_model.getImplementation().getClassName()
graph.setLegends(["Histogram",name])
graph.setXTitle("Latências (segundos)")
graph.setYTitle("Frequência")
otv.View(graph)
I'd like to set X limits as something like "graph.setXLim", as we'd do in matplotlib, but I'm stuck with it as I'm new to OpenTurns.
Thanks in advance.
Any OpenTURNS graph has a getBoundingBox method which returns the bounding box as a dimension 2 Interval. We can get/set the lower and upper bounds of this interval with getLowerBound and getUpperBound. Each of these bounds is a Point with dimension 2. Hence, we can set the bounds of the graphics prior to the use of the View class.
In the following example, I create a simple graph containing the PDF of the gaussian distribution.
import openturns as ot
import openturns.viewer as otv
n = ot.Normal()
graph = n.drawPDF()
_ = otv.View(graph)
Suppose that I want to set the lower X axis to -1.
The script:
boundingBox = graph.getBoundingBox()
lb = boundingBox.getLowerBound()
print(lb)
produces:
[-4.10428,-0.0195499]
The first value in the Point is the X lower bound and the second is the Y lower bound. The following script sets the first component of the lower bound to -1, wraps the lower bound into the bounding box and sets the bounding box into the graph.
lb[0] = -1.0
boundingBox.setLowerBound(lb)
graph.setBoundingBox(boundingBox)
_ = otv.View(graph)
This produces the following graph.
The advantage of these methods is that they configure the graphics from the library, before the rendering is done by Matplotlib. The drawback is that they are a little more verbose than the Matplotlib counterpart.
Here is a minimal example adapted from openTURNS examples (see http://openturns.github.io/openturns/latest/examples/graphs/graphs_basics.html) to set the x range (initially from [-4,4] to [-2,2]) :
import openturns as ot
import openturns.viewer as viewer
from matplotlib import pylab as plt
n = ot.Normal()
# To configure the look of the plot, we can first observe the type
# of graphics returned by the `drawPDF` method returns: it is a `Graph`.
graph = n.drawPDF()
# The `Graph` class provides several methods to configure the legends,
# the title and the colors. Since a graphics can contain several sub-graphics,
# the `setColors` takes a list of colors as inputs argument: each item of
# the list corresponds to the sub-graphics.
graph.setXTitle("N")
graph.setYTitle("PDF")
graph.setTitle("Probability density function of the standard gaussian distribution")
graph.setLegends(["N"])
graph.setColors(["blue"])
# Combine several graphics
# In order to combine several graphics, we can use the `add` method.
# Let us create an empirical histogram from a sample.
sample = n.getSample(100)
histo = ot.HistogramFactory().build(sample).drawPDF()
# Then we add the histogram to the `graph` with the `add` method.
# The `graph` then contains two plots.
graph.add(histo)
# Using openturns.viewer
view = viewer.View(graph)
# Get the matplotlib.axes.Axes member with getAxes()
# Similarly, there is a getFigure() method as well
axes = view.getAxes() # axes is a matplotlib object
_ = axes[0].set_xlim(-2.0, 2.0)
plt.show()
You can read the definition of the View object here :
https://github.com/openturns/openturns/blob/master/python/src/viewer.py
As you will see, the View class contains matplotlib objects such as axes and figure. Once accessed by the getAxes (or getFigure) you can use the matplotlib methods.