Open Peacemoose10 opened 2 years ago
import ternary
import numpy as np
i = [1, 0.7, 0.5, 0.3, 0, 0.7, 0.5, 0.3, 0.4, 0.3, 0.3, 0]
j = [0, 0.3, 0.5, 0.7, 1, 0, 0 , 0, 0.3, 0.3, 0.4, 0.7]
k = [0, 0, 0, 0, 0, 0.3, 0.5, 0.7, 0.3, 0.4, 0.3, 0.3]
Z = np.linspace(0,1,12)
data_dictionary2 = {(i[a], j[a], k[a]) for a in range(len(Z))}
fontsize = 18
#------------------------ Original plot ---------------------------------------
offset = 0.25
fig, tax = ternary.figure(scale=1)
tax.scatter(data_dictionary2)
tax.ticks(axis='lbr', multiple=.1, linewidth=1, offset=0.025, tick_formats="%.1f", fontsize=fontsize)
tax.get_axes().axis('off')
tax.clear_matplotlib_ticks()
tax.boundary(linewidth=2.0)
tax.left_axis_label("Left label $\\alpha^2$", fontsize=fontsize, offset=offset)
tax.right_axis_label("Right label $\\beta^2$", fontsize=fontsize, offset=offset)
tax.bottom_axis_label("Bottom label $\\Gamma - \\Omega$", fontsize=fontsize, offset=offset)
tax.show()
#==============================================================================
#----------------------- After cut --------------------------------------------
ycut = 0.5 # y-axis cut in ternary scale at 0.5
ycut_cart = np.sqrt(3)/2 * ycut # y-axis cut in cartesian coordinate at sqrt(3)/2 * ycut
fig, tax = ternary.figure(scale=1)
tax.scatter(data_dictionary2)
tax.ticks(axis='lbr', multiple=.1, linewidth=1, offset=0.025, tick_formats="%.1f",fontsize=fontsize)
tax.get_axes().axis('off')
tax.clear_matplotlib_ticks()
tax.boundary(linewidth=2.0)
ax = tax.get_axes()
# Note: ymin is not 0.0 but there is an extra lower limit (-0.1) in y-axis to fit
# the canvas perfectly. Check resize_drawing_canvas() in plotting.py script.
# Calculation: Ternary y-scale maximum 1 == Cartesian y-scale sqrt(3)/2
# Ternary y-scale maximum ycut == Cartesian y-scale sqrt(3)/2 * ycut
ax.set_ylim(ymax=ycut_cart) # this ymax should be in cartesian coordinate scale.
# Need to increase the offset for left and right labels. Because _redraw_labels()
# will redraw the labels according to the new limits. As in this example the
# bottom ylim was not changed, so one doesn't need to change the bottom_axis_label()
# offset value.
# Note: tax.show() already calls the tax._redraw_labels().
tax.left_axis_label("Left label $\\alpha^2$", fontsize=fontsize, offset=offset+0.05)
tax.right_axis_label("Right label $\\beta^2$", fontsize=fontsize, offset=offset+0.05)
tax.bottom_axis_label("Bottom label $\\Gamma - \\Omega$", fontsize=fontsize, offset=offset)
# Resize the figure aspect ratio to avoid the streching.
import matplotlib
# height = ycut + 0.1 # 0.1 is the extra ymin used to fit canvas in vertical direction
# width = xlimit(=1) + 2*0.05 # In horizontal axis extra 0.05 was used in both left
# right to fit the canvas. Check resize_drawing_canvas() in ternary/plotting.py script.
# ratio = height/width
fig_aspect_ratio = (ycut+0.1)/(1+0.1)
w, h = matplotlib.figure.figaspect(fig_aspect_ratio)
fig.set_size_inches(w, h)
#tax._redraw_labels()
tax.show()
# fig.savefig('/home/test.png',format='png',dpi=300)
#==============================================================================
#---------------------- Alternative way to set figure aspect ratio ------------
import matplotlib
# Resize the figure aspect ratio to avoid the streching.
w, h = matplotlib.figure.figaspect(fig_aspect_ratio)
fig, ax = matplotlib.pyplot.subplots(figsize=(w,h))
tax = ternary.TernaryAxesSubplot(ax=ax, scale = 1)
tax.scatter(data_dictionary2)
tax.ticks(axis='lbr', multiple=.1, linewidth=1, offset=0.025, tick_formats="%.1f",fontsize=fontsize)
tax.get_axes().axis('off')
tax.clear_matplotlib_ticks()
tax.boundary(linewidth=2.0)
ax.set_ylim(ymax=ycut_cart)
tax.left_axis_label("Left label $\\alpha^2$", fontsize=fontsize, offset=offset+0.05)
tax.right_axis_label("Right label $\\beta^2$", fontsize=fontsize, offset=offset+0.05)
tax.bottom_axis_label("Bottom label $\\Gamma - \\Omega$", fontsize=fontsize, offset=offset)
tax.show()
Thank you very much! The last example using subplots is exactly what I needed!
Actually, so sorry - I am still struggling to get the numbers above the cut off to disappear. I want to make a figure that has two rows, but when I do that, the ternary numbers above the cutoff bleed into the next plot. I can't figure out how to make them disappear or plot under the top row (I've tried using zorder but that doesn't seem to make a difference). Thank you for your help!
Quick and dirty: Add clip_on=True
in the ax.text calls inside ternary/lines.py
script.
ax.text(x, y, s, horizontalalignment="center", color=axes_colors['l'], fontsize=fontsize,clip_on=True)
A better solution:
import ternary
import numpy as np
from matplotlib import pyplot, gridspec
#-------------------- Function definition for manual tick settings ------------
def ManualTicks(tax, limits):
'''
This function creates the ticks. Similar to set_custom_ticks() function in
ternary/ternary_axes_subplot.py .
Parameters
----------
tax : axis
Ternary axis.
limits : dictionary
Dictionary containing limits. b, l, r == bottom, left, right
Returns
-------
None.
'''
for k in ['b', 'r', 'l']:
minimum, maximum, step = limits[k]
myticks = np.arange(minimum, maximum, step)
mylocations = np.copy(myticks) - min(myticks) if k=='l' else myticks
tax.ticks(ticks=list(myticks), locations=list(mylocations), axis=k,
linewidth=1, offset=0.025, fontsize=fontsize)
#--------------------------Create random data----------------------------------
pointsx = np.random.randint(1,50,size=100)
pointsy = np.random.randint(1,50,size=100)
data_dictionary = {(pointsx[a], pointsy[a]) for a in range(len(pointsx))}
fontsize = 18
offset = 0.25
# If you need to cut the ylimit at different positions
# for different subplots you can make a array of cut limits here and
# call accordingly later.
ycut_cart = np.sqrt(3)/2* 50
limits = {'b':(10,110,10), 'r':(0,60,10), 'l':(50,110,10)} # limits = {which_axis:(minimum_limit, maximum_limit, step_size)}
#-------------------------- Plotting -----------------------------------------
pyplot.figure(figsize=(12,8))
nrows = 2; ncols = 2
gs = gridspec.GridSpec(nrows,ncols)
pyplot.subplots_adjust(wspace=0.3,hspace=0.5)
LeftAxisLabels = ['$\\alpha_1^2$', '$\\alpha_2^2$', '$\\alpha_3^2$', '$\\alpha_4^2$']
RightAxisLabels = ['$\\beta_1^2$','$\\beta_2^2$','$\\beta_3^2$','$\\beta_4^2$']
BottomAxisLabels = ['$\\Gamma_1$','$\\Gamma_2$','$\\Gamma_3$','$\\Gamma_4$']
n = 0
for i in range(nrows):
for j in range(ncols):
ax = pyplot.subplot(gs[i, j])
figure, tax = ternary.figure(ax=ax, scale = 100)
tax.scatter(data_dictionary)
tax.boundary(linewidth=1.0)
tax.set_title(f"Scatter Plot {i,j}", fontsize=fontsize, pad=30)
tax.left_axis_label(LeftAxisLabels[n], fontsize=fontsize, offset=0.28)
tax.right_axis_label(RightAxisLabels[n], fontsize=fontsize, offset=0.3)
tax.bottom_axis_label(BottomAxisLabels[n], fontsize=fontsize, offset=0.25)
tax._redraw_labels()
tax.get_axes().set_ylim(ymax=ycut_cart)
tax.get_axes().axis('off')
tax.clear_matplotlib_ticks()
# Lets create the ticks manually
ManualTicks(tax, limits)
n+=1
Hello!
First, thank you so much for making this package - it's so helpful! I am a geologist, and we often use ternary diagrams with the top cut off, such as the plot below (purely an example I got from the internet).
I am struggling to replicate this with your packages. I am using subplots, so I can control the height of the axes using ax.set_ylim, but this just stretches the ternary (example below), and leaves some of the ternary tick marks stretched out above the plot. Is there a way to plot only part of a ternary axis?
Basically, I guess I want to do something like the last part of the solution to #190 but without the free floating ticks.
Thank you! M