cetin
11 months ago
6 changed files with 625 additions and 44 deletions
-
5.vscode/settings.json
-
65B_tasks.ipynb
-
250B_updown.ipynb
-
9Projektpraktikum.code-workspace
-
BINmethods/__pycache__/adashof.cpython-310.pyc
-
340methods/adashof.py
@ -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, |
|||
} |
65
B_tasks.ipynb
File diff suppressed because one or more lines are too long
View File
File diff suppressed because one or more lines are too long
View File
250
B_updown.ipynb
File diff suppressed because one or more lines are too long
View File
File diff suppressed because one or more lines are too long
View File
@ -1,10 +1,13 @@ |
|||
{ |
|||
"folders": [ |
|||
{ |
|||
"path": "./", |
|||
} |
|||
"path": "./" |
|||
}, |
|||
], |
|||
"settings": { |
|||
"python.analysis.completeFunctionParens": true |
|||
"python.analysis.completeFunctionParens": true, |
|||
"python.analysis.enablePytestExtra": false, |
|||
|
|||
"python.languageServer": "Pylance", |
|||
} |
|||
} |
Binary file not shown.
@ -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) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue