ive got problem with label names, at pic below i will show you what im mean.
e.g cacatua_moluccensis
Im using Phylo.draw() function to draw a phylogenetic tree and everything is fine, but one thing is unaesthetic for me, label lines didnt show out of axes at fig field but i dont know why label names did (look at cacatua_moluccensis at pic). Here is code i used:
from Bio import Phylo
import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure(frameon=False)
ax=plt.gca()
tree = Phylo.read("simple1.dnd", "newick")
tree.rooted = True
Phylo.draw(tree, show_confidence=True, axes=ax)
I was able to change some things in axes, so i think change displaying of label names its possible.
Related
I am working with relatively large datasets (approximately 10x20.000.000 data point), for which Datashader is a useful visualisation tool. To give more information in these visualisations, I would like to add lines showing averages/standarddeviations on top of this datashade figure. Does anyone know how this would be possible?
My current code:
from bokeh.plotting import figure
from bokeh.io import show
x = 'xcol'
y= 'ycol'
data = dataframe
fig = figure(x_axis_label=x, y_axis_label=y)
points = hv.Points(data[[x, y]], label=('Title'))
hd.datashade(points, cmap='crest')
What I would like to do is for example add the following line to the figure generated with the code above:
fig.line([1,10,20], [0, 1000,2000], line_width=4)
Thanks in advance.
how can I create one legend to control multiple bokeh figures? Or how can I customize an exported html file created with bokeh to add legend with similar functionality?
Here is the scenario. I create an html file with 4 different figures. Each figure has a legend with labels/names for individual lines that are shown in the particular figure. Each of the four legend is clickable to toggle the lines separately in each figure.
Even though each of the four figures has one legend, the lines are related, so they each line describes one thing.
I now want to create a legend for all figures combined in one, to toggle each line in all four figures.
Maybe there is a way to add this kind of functionality to the exported html file in some way?
I thought someone with more experience has an idea how to achieve that.
Thanks in advance!
Kind regards
Legends are not (yet?) 'standalone' bokeh models, they need to be attached to a figure. For now to have an external legend for multiple figures, and place it wherever in a layout, some workaround is needed.
I typically do it like below, with an 'invisible' figure that holds the shared legend. You then have to define the legend items manually and assign to each their label and list of renderers.
from bokeh.io import show
from bokeh.plotting import figure
from bokeh.models import LegendItem, Legend
from numpy.random import random, choice
from bokeh.layouts import gridplot
from webcolors import html4_names_to_hex
del html4_names_to_hex['white']
palette = list(html4_names_to_hex.keys())
fig_list = [figure(plot_width=300,plot_height=300) for i in range(4)]
renderer_list = []
color_list = []
for fig in fig_list:
for i in range(5):
color = choice(palette)
renderer = fig.line(range(10),random(10),line_width=2,color=color)
renderer_list += [renderer]
color_list += [color]
# Lines with the same color will share a same legend item
legend_items = [LegendItem(label=color,renderers=[renderer for renderer in renderer_list if renderer.glyph.line_color==color]) for color in set(color_list)]
## Use a dummy figure for the LEGEND
dum_fig = figure(plot_width=300,plot_height=600,outline_line_alpha=0,toolbar_location=None)
# set the components of the figure invisible
for fig_component in [dum_fig.grid[0],dum_fig.ygrid[0],dum_fig.xaxis[0],dum_fig.yaxis[0]]:
fig_component.visible = False
# The glyphs referred by the legend need to be present in the figure that holds the legend, so we must add them to the figure renderers
dum_fig.renderers += renderer_list
# set the figure range outside of the range of all glyphs
dum_fig.x_range.end = 1005
dum_fig.x_range.start = 1000
# add the legend
dum_fig.add_layout( Legend(click_policy='hide',location='top_left',border_line_alpha=0,items=legend_items) )
figrid = gridplot(fig_list,ncols=2,toolbar_location='left')
final = gridplot([[figrid,dum_fig]],toolbar_location=None)
show(final)
I created a figure which has 2 axes, how can I plot specific axes(eg,ax[0]) rather than plot both axes? When I input fig in the end both axes will appear together. What code should I write if I just want ax[0] be displayed for example?
fig,ax=plt.subplots(2)
x=np.linspace(1,10,100)
ax[0].plot(x,np.sin(x))
ax[1].plot(x,np.cos(x))
fig
I interprete that you are using Jupyter notebook. You may then use the fact that invisble axes parts of a figure will be cropped with the matplotlib inline backend.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
fig,ax=plt.subplots(2);
x=np.linspace(1,10,100)
ax[0].plot(x,np.sin(x))
ax[1].plot(x,np.cos(x))
Now to only show the second subplot, you can set the first invisible,
ax[0].set_visible(False)
fig
If you then want to only show the first subplot, you need to set it visible again and the second one invisible
ax[0].set_visible(True)
ax[1].set_visible(False)
fig
This seems like it's going to be something simple that will fix my code but I think I've just looked at the code too much at the moment and need to get some fresh eyes on it. I'm simply trying to bring in a Grib2 file that I've downloaded from NCEP for the HRRR model. According to their information the grid type is Lambert Conformal with the extents of (21.13812, 21.14055, 47.84219, 47.83862) for the latitudes of the corners and (-122.7195, -72.28972, -60.91719, -134.0955) for the longitudes of the corners for the models domain.
Before even trying to zoom into my area of interest I just wanted to simply display an image in the appropriate CRS however when I try to do this for the domain of the model I get the borders and coastlines to fall within that extent but the actual image produced from the Grib2 file is just zoomed into. I've tried to use extent=[my domain extent] but it always seems to crash the notebook I'm testing it in. Here is my code and the associated image that I get from it.
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy
from mpl_toolkits.basemap import Basemap
from osgeo import gdal
gdal.SetConfigOption('GRIB_NORMALIZE_UNITS', 'NO')
plt.figure()
filename='C:\\Users\\Public\\Documents\\GRIB\\hrrr.t18z.wrfsfcf00.grib2'
grib = gdal.Open(filename, gdal.GA_ReadOnly)
z00 = grib.GetRasterBand(47)
meta00 = z00.GetMetadata()
band_description = z00.GetDescription()
bz00 = z00.ReadAsArray()
latitude_south = 21.13812 #38.5
latitude_north = 47.84219 #50
longitude_west = -134.0955 #-91
longitude_east = -60.91719 #-69
fig = plt.figure(figsize=(20, 20))
title= meta00['GRIB_COMMENT']+' at '+meta00['GRIB_SHORT_NAME']
fig.set_facecolor('white')
ax = plt.axes(projection=ccrs.LambertConformal())
ax.add_feature(cartopy.feature.BORDERS, linestyle=':')
ax.coastlines(resolution='110m')
ax.imshow(bz00,origin='upper',transform=ccrs.LambertConformal())
plt.title(title)
plt.show()
Returns Just Grib File
If I change:
ax = plt.axes(projection=ccrs.LambertConformal()
to
ax = plt.axes(projection=ccrs.LambertConformal(central_longitude=-95.5,
central_latitude=38.5,cutoff=21.13)
I get my borders but my actual data is not aligned and it creates what I'm dubbing a Batman plot.
Batman Plot
A similar issue occurs even when I do zoom into the domain and still have my borders present. The underlying data from the Grib file doesn't change to correspond to what I'm trying to get.
So as I've already said this is probably something that is an easy fix that I'm just missing but if not, it would be nice to know what step or what process I'm screwing up that I can learn from so that I don't do it in the future!
Updated 1:
I've added and changed some code and am back to getting only the image to show without the borders and coastlines showing up.
test_extent = [longitude_west,longitude_east,latitude_south,latitude_north]
ax.imshow(bz00,origin='upper',extent=test_extent)
This gives me the following image.
Looks exactly like image 1.
The other thing that I'm noticing which maybe the root cause of all of this is that when I'm printing out the value for plt.gca().get_ylim() and plt.gca().get_xlim() I'm getting hugely different values depending on what is being displayed.
It seems that my problem arises from the fact that the Grib file regardless of whether or not it can be displayed properly in other programs just doesn't play nicely with Matplotlib and Cartopy out of the box. Or at the very least does not with the Grib files that I was using. Which for sake of this perhaps helping others in the future are from the NCEP HRRR model that you can get here or here.
Everything seems to work nicely if you convert the file from Grib2 format to NetCDF format and I was able to get what I wanted with the borders, coastlines, etc. on the map. I've attached the code and the output below to show how it worked. Also I hand picked a single dataset that I wanted to display to test versus my previous code so incase you want to look at the rest of datasets available in the file you'll need to utilize ncdump or something similar to view the information on the datasets.
import numpy as np
from netCDF4 import Dataset
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy
import cartopy.feature as cfeature
from osgeo import gdal
gdal.SetConfigOption('GRIB_NORMALIZE_UNITS', 'NO')
nc_f = 'C:\\Users\\Public\\Documents\\GRIB\\test.nc' # Your filename
nc_fid = Dataset(nc_f, 'r') # Dataset is the class behavior to open the
# file and create an instance of the ncCDF4
# class
# Extract data from NetCDF file
lats = nc_fid.variables['gridlat_0'][:]
lons = nc_fid.variables['gridlon_0'][:]
temp = nc_fid.variables['TMP_P0_L1_GLC0'][:]
fig = plt.figure(figsize=(20, 20))
states_provinces = cfeature.NaturalEarthFeature(category='cultural', \
name='admin_1_states_provinces_lines',scale='50m', facecolor='none')
proj = ccrs.LambertConformal()
ax = plt.axes(projection=proj)
plt.pcolormesh(lons, lats, temp, transform=ccrs.PlateCarree(),
cmap='RdYlBu_r', zorder=1)
ax.add_feature(cartopy.feature.BORDERS, linestyle=':', zorder=2)
ax.add_feature(states_provinces, edgecolor='black')
ax.coastlines()
plt.show()
Final Preview of Map
I'm trying to do a correlation plot using python, so I'm starting with this basic example
import numpy as np
import matplotlib.pyplot as plt
image=np.random.rand(10,10)
plt.imshow(image)
plt.colorbar()
plt.show()
ok, this script give to me an image like this
so the next step is to put my dataset and not a random matrix, i know it, but I want to put some axis or text in this plot, and to get something like this image
It is a very pretty image using paint (lol), but someone can say me what way I need to follow to do something like thik please (how to search it in google).
Before to post it I think in labels, but also I think that I can assign only one label to each axis
cheers
As #tcaswell said in the comments, the function you want to use is annotate, and the documentation can be found here.
I've given an example below using your code above:
import numpy as np
import matplotlib.pyplot as plt
def annotate_axes(x1,y1,x2,y2,x3,y3,text):
ax.annotate('', xy=(x1, y1),xytext=(x2,y2), #draws an arrow from one set of coordinates to the other
arrowprops=dict(arrowstyle='<->'), #sets style of arrow
annotation_clip=False) #This enables the arrow to be outside of the plot
ax.annotate(text,xy=(0,0),xytext=(x3,y3), #Adds another annotation for the text
annotation_clip=False)
fig, ax = plt.subplots()
image=np.random.rand(10,10)
plt.imshow(image)
plt.colorbar()
#annotate x-axis
annotate_axes(-0.5,10,4.5,10,2.5,10.5,'A') # changing these changes the position of the arrow and the text
annotate_axes(5,10,9.5,10,7.5,10.5,'B')
#annotate y-axis
annotate_axes(-1,0,-1,4,-1.5,2,'A')
annotate_axes(-1,4.5,-1,9.5,-1.5,7.5,'B')
plt.show()
This give the image shown below: