added methods
This commit is contained in:
parent
2462802389
commit
c184e6f12e
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -1,3 +1,6 @@
|
||||
{
|
||||
"python.envFile": "/auto/work/cetin/LHCb/reco_tuner/env/tuner_env/envs/",
|
||||
// "python.envFile": "/auto/work/cetin/LHCb/reco_tuner/env/tuner_env/envs/",
|
||||
"python.analysis.completeFunctionParens": true,
|
||||
"python.analysis.enablePytestExtra": false,
|
||||
"python.analysis.extraCommitChars": true,
|
||||
}
|
File diff suppressed because one or more lines are too long
250
B_updown.ipynb
250
B_updown.ipynb
File diff suppressed because one or more lines are too long
@ -1,10 +1,13 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "./",
|
||||
}
|
||||
"path": "./"
|
||||
},
|
||||
],
|
||||
"settings": {
|
||||
"python.analysis.completeFunctionParens": true
|
||||
"python.analysis.completeFunctionParens": true,
|
||||
"python.analysis.enablePytestExtra": false,
|
||||
|
||||
"python.languageServer": "Pylance",
|
||||
}
|
||||
}
|
BIN
methods/__pycache__/adashof.cpython-310.pyc
Normal file
BIN
methods/__pycache__/adashof.cpython-310.pyc
Normal file
Binary file not shown.
340
methods/adashof.py
Normal file
340
methods/adashof.py
Normal file
@ -0,0 +1,340 @@
|
||||
|
||||
# coding: utf-8
|
||||
# flake8: noqa
|
||||
|
||||
# # `adashof`: Functions used in the notebooks of the blog
|
||||
#
|
||||
# [Blog](http://werthmuller.org/blog)
|
||||
# [Repo](http://github.com/prisae/blog-notebooks)
|
||||
#
|
||||
# - circle : Create circle on figure with axes of different sizes.
|
||||
# - move_sn_y : Move scientific notation exponent from top to the side.
|
||||
# - fillgrid : Fill rectangular grid with colours or a colour and transparency.
|
||||
# - checksize : Check size of pdf figure, and adjust if required.
|
||||
# - cm2in : Convert centimetres to inches
|
||||
|
||||
# In[1]:
|
||||
|
||||
import numpy as np
|
||||
import matplotlib as mpl
|
||||
from matplotlib import cm
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
# In[2]:
|
||||
|
||||
def circle(xy, radius, kwargs=None):
|
||||
"""Create circle on figure with axes of different sizes.
|
||||
|
||||
Plots a circle on the current axes using `plt.Circle`, taking into account
|
||||
the figure size and the axes units.
|
||||
|
||||
It is done by plotting in the figure coordinate system, taking the aspect
|
||||
ratio into account. In this way, the data dimensions do not matter.
|
||||
However, if you adjust `xlim` or `ylim` after plotting `circle`, it will
|
||||
screw them up; set `plt.axis` before calling `circle`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xy, radius, kwars :
|
||||
As required for `plt.Circle`.
|
||||
"""
|
||||
|
||||
# Get current figure and axis
|
||||
fig = mpl.pyplot.gcf()
|
||||
ax = fig.gca()
|
||||
|
||||
# Calculate figure dimension ratio width/height
|
||||
pr = fig.get_figwidth()/fig.get_figheight()
|
||||
|
||||
# Get the transScale (important if one of the axis is in log-scale)
|
||||
tscale = ax.transScale + (ax.transLimits + ax.transAxes)
|
||||
ctscale = tscale.transform_point(xy)
|
||||
cfig = fig.transFigure.inverted().transform(ctscale)
|
||||
|
||||
# Create circle
|
||||
if kwargs == None:
|
||||
circ = mpl.patches.Ellipse(cfig, radius, radius*pr,
|
||||
transform=fig.transFigure)
|
||||
else:
|
||||
circ = mpl.patches.Ellipse(cfig, radius, radius*pr,
|
||||
transform=fig.transFigure, **kwargs)
|
||||
|
||||
# Draw circle
|
||||
ax.add_artist(circ)
|
||||
|
||||
|
||||
# In[3]:
|
||||
|
||||
def move_sn_y(offs=0, dig=0, side='left', omit_last=False):
|
||||
"""Move scientific notation exponent from top to the side.
|
||||
|
||||
Additionally, one can set the number of digits after the comma
|
||||
for the y-ticks, hence if it should state 1, 1.0, 1.00 and so forth.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
offs : float, optional; <0>
|
||||
Horizontal movement additional to default.
|
||||
dig : int, optional; <0>
|
||||
Number of decimals after the comma.
|
||||
side : string, optional; {<'left'>, 'right'}
|
||||
To choose the side of the y-axis notation.
|
||||
omit_last : bool, optional; <False>
|
||||
If True, the top y-axis-label is omitted.
|
||||
|
||||
Returns
|
||||
-------
|
||||
locs : list
|
||||
List of y-tick locations.
|
||||
|
||||
Note
|
||||
----
|
||||
This is kind of a non-satisfying hack, which should be handled more
|
||||
properly. But it works. Functions to look at for a better implementation:
|
||||
ax.ticklabel_format
|
||||
ax.yaxis.major.formatter.set_offset_string
|
||||
"""
|
||||
|
||||
# Get the ticks
|
||||
locs, _ = mpl.pyplot.yticks()
|
||||
|
||||
# Put the last entry into a string, ensuring it is in scientific notation
|
||||
# E.g: 123456789 => '1.235e+08'
|
||||
llocs = '%.3e' % locs[-1]
|
||||
|
||||
# Get the magnitude, hence the number after the 'e'
|
||||
# E.g: '1.235e+08' => 8
|
||||
yoff = int(str(llocs).split('e')[1])
|
||||
|
||||
# If omit_last, remove last entry
|
||||
if omit_last:
|
||||
slocs = locs[:-1]
|
||||
else:
|
||||
slocs = locs
|
||||
|
||||
# Set ticks to the requested precision
|
||||
form = r'$%.'+str(dig)+'f$'
|
||||
mpl.pyplot.yticks(locs, list(map(lambda x: form % x, slocs/(10**yoff))))
|
||||
|
||||
# Define offset depending on the side
|
||||
if side == 'left':
|
||||
offs = -.18 - offs # Default left: -0.18
|
||||
elif side == 'right':
|
||||
offs = 1 + offs # Default right: 1.0
|
||||
|
||||
# Plot the exponent
|
||||
mpl.pyplot.text(offs, .98, r'$\times10^{%i}$' % yoff, transform =
|
||||
mpl.pyplot.gca().transAxes, verticalalignment='top')
|
||||
|
||||
# Return the locs
|
||||
return locs
|
||||
|
||||
|
||||
# In[4]:
|
||||
|
||||
def fillgrid(xval, yval, values, style='colour', cmap=cm.Spectral,
|
||||
unicol='#000000', lc='k', lw=0.5):
|
||||
"""Fill rectangular grid with colours or a colour and transparency.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xval, yval : array
|
||||
Grid-points in x- and in y-direction.
|
||||
values : array, dimension: (x-1)-by-(y-1)
|
||||
Values between 0 and 1
|
||||
style : string, optional; {<'colour'>, 'alpha'}
|
||||
Defines if values represent colour or alpha.
|
||||
cmap : mpl.cm-element, optional
|
||||
`Colormap` colours are chosen from; only used if style='colour'
|
||||
unicol : HEX-colour
|
||||
Colour used with transparency; only used if style='alpha'
|
||||
lc, lw : optional
|
||||
Line colour and width, as in standard plots.
|
||||
|
||||
Returns
|
||||
-------
|
||||
rct : list
|
||||
List of plotted polygon patches.
|
||||
"""
|
||||
|
||||
# Ravel values, and set NaN's to zero
|
||||
rval = values.ravel()
|
||||
rvalnan = np.isnan(rval)
|
||||
rval[rvalnan] = 0
|
||||
|
||||
# Define colour depending on style
|
||||
if style == 'alpha':
|
||||
# Create RGB from HEX
|
||||
unicol = mpl.colors.colorConverter.to_rgb(unicol)
|
||||
# Repeat colour for all values,
|
||||
# filling the value into the transparency column
|
||||
colour = np.vstack((np.repeat(unicol, len(rval)).reshape(3, -1),
|
||||
rval)).transpose()
|
||||
else:
|
||||
# Split cmap into 101 points from 0 to 1
|
||||
cmcol = cmap(np.linspace(0, 1, 101))
|
||||
# Map the values onto these
|
||||
colour = cmcol[list(map(int, 100*rval))]
|
||||
# Set transparency to 0 for NaN's
|
||||
colour[rvalnan, -1] = 0
|
||||
|
||||
# Draw all rectangles at once
|
||||
xxval = np.array([xval[:-1], xval[:-1], xval[1:], xval[1:]]).repeat(
|
||||
len(yval)-1, axis=1).reshape(4, -1)
|
||||
yyval = np.array([yval[:-1], yval[1:], yval[1:], yval[:-1]]).repeat(
|
||||
len(xval)-1, axis=0).reshape(4, -1)
|
||||
rct = mpl.pyplot.gca().fill(xxval, yyval, lw=lw, ec=lc)
|
||||
|
||||
# Map the colour onto a list
|
||||
cls = list(map(mpl.colors.rgb2hex, colour))
|
||||
|
||||
# Adjust colour and transparency for all cells
|
||||
for ind in range(len(rct)):
|
||||
rct[ind].set_facecolor(cls[ind])
|
||||
rct[ind].set_alpha(colour[ind, -1])
|
||||
|
||||
return rct
|
||||
|
||||
|
||||
# In[5]:
|
||||
|
||||
def checksize(fhndl, name, dsize, precision=0.01, extent=0.05, kwargs={}, _cf=False):
|
||||
"""Print figure with 'name.pdf', check size, compare with dsize, and adjust if required
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fhndl : figure-handle
|
||||
Figure handle of the figure to be saved.
|
||||
name : string
|
||||
Figure name.
|
||||
dsize : list of two floats
|
||||
Desired size of pdf in cm.
|
||||
precision : float, optional; <0.01>
|
||||
Desired precision in cm of the dimension, defaults to 1 mm.
|
||||
extent : float or list of floats, optional; <0.01>
|
||||
- If float, then bbox_inches is set to tight, and pad_inches=extent.
|
||||
- If it is an array of two numbers it sets the percentaged extent-width,
|
||||
`Bbox.expanded`.
|
||||
- If it is an array of four numbers it sets [x0, y0, x1, y1] of Bbox.
|
||||
kwargs : dict
|
||||
Other input arguments that will be passed on to `plt.savefig`; e.g. dpi or facecolor.
|
||||
_cf : Internal parameter for recursion and adjustment.
|
||||
"""
|
||||
|
||||
# Import PyPDF2
|
||||
from PyPDF2 import PdfFileReader
|
||||
|
||||
# Check `extent` input and set bbox_inches and pad_inches accordingly
|
||||
if np.size(extent) == 1:
|
||||
bbox_inches = 'tight'
|
||||
pad_inches = extent
|
||||
else:
|
||||
fext = fhndl.gca().get_window_extent().transformed(
|
||||
fhndl.dpi_scale_trans.inverted())
|
||||
if np.size(extent) == 2:
|
||||
bbox_inches = fext.expanded(extent[0], extent[1])
|
||||
elif np.size(extent) == 4:
|
||||
fext.x0, fext.y0, fext.x1, fext.y1 = extent
|
||||
extent = [1, 1] # set extent to [1, 1] for recursion
|
||||
bbox_inches = fext
|
||||
pad_inches=0
|
||||
|
||||
# Save the figure
|
||||
fhndl.savefig(name+'.pdf', bbox_inches=bbox_inches, pad_inches=pad_inches, **kwargs)
|
||||
|
||||
# Get pdf-dimensions in cm
|
||||
pdffile = PdfFileReader(open(name+'.pdf', mode='rb'))
|
||||
pdfsize = np.array([float(pdffile.getPage(0).mediaBox[2]),
|
||||
float(pdffile.getPage(0).mediaBox[3])])
|
||||
pdfdim = pdfsize*2.54/72. # points to cm
|
||||
|
||||
# Define `print`-precision on desired precision
|
||||
pprec = abs(int(('%.1e' % precision).split('e')[1]))+1
|
||||
|
||||
# Get difference btw desired and actual size
|
||||
diff = dsize-pdfdim
|
||||
|
||||
# If diff>precision, adjust, else finish
|
||||
if np.any(abs(diff) > precision):
|
||||
if not _cf:
|
||||
_cf = [1, 1]
|
||||
|
||||
# Be verbose
|
||||
print(' resize...')
|
||||
|
||||
# Adjust width
|
||||
if (abs(diff[0]) > precision):
|
||||
print(' X-diff:', np.round(diff[0], pprec), 'cm')
|
||||
|
||||
# Set new factor to old factor times (desired size)/(actual size)
|
||||
_cf[0] = _cf[0]*dsize[0]/pdfdim[0]
|
||||
|
||||
# Set new figure width
|
||||
fhndl.set_figwidth(_cf[0]*dsize[0]/2.54) # cm2in
|
||||
|
||||
# Adjust height
|
||||
if (abs(diff[1]) > precision):
|
||||
print(' Y-diff:', np.round(diff[1], pprec), 'cm')
|
||||
|
||||
# Set new factor to old factor times (desired size)/(actual size)
|
||||
_cf[1] = _cf[1]*dsize[1]/pdfdim[1]
|
||||
|
||||
# Set new figure height
|
||||
fhndl.set_figheight(_cf[1]*dsize[1]/2.54) #cm2in
|
||||
|
||||
# Call the function again, with new factor _cf
|
||||
figsize = checksize(fhndl, name, dsize, precision, extent, kwargs, _cf)
|
||||
|
||||
return figsize
|
||||
|
||||
else: # Print some info if the desired dimensions are reached
|
||||
|
||||
# Print figure name and pdf dimensions
|
||||
print('Figure saved to '+name +'.pdf;',
|
||||
np.round(pdfdim[0], pprec), 'x',
|
||||
np.round(pdfdim[1], pprec), 'cm.')
|
||||
|
||||
# Print the new figsize if it had to be adjusted
|
||||
if _cf:
|
||||
print(' => NEW FIG-SIZE: figsize=('+
|
||||
str(np.round(fhndl.get_size_inches()[0], 2*pprec))+', '+
|
||||
str(np.round(fhndl.get_size_inches()[1], 2*pprec))+')')
|
||||
|
||||
# Return figsize
|
||||
return fhndl.get_size_inches()
|
||||
|
||||
|
||||
# In[6]:
|
||||
|
||||
def cm2in(length, decimals=2):
|
||||
"""Convert cm to inch.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
length : scalar or vector
|
||||
Numbers to be converted.
|
||||
decimals : int, optional; <2>
|
||||
As in np.round, used to round the result.
|
||||
|
||||
Returns
|
||||
-------
|
||||
cm2in : scalar or vector
|
||||
Converted numbers.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> from adashof import cm2in
|
||||
>>> cm2in(5)
|
||||
1.97
|
||||
|
||||
"""
|
||||
|
||||
# Test input
|
||||
try:
|
||||
length = np.array(length, dtype='float')
|
||||
decimals = int(decimals)
|
||||
except ValueError:
|
||||
print("{length} must be a number, {decimals} an integer")
|
||||
|
||||
return np.round(length/2.54, decimals)
|
Loading…
Reference in New Issue
Block a user