Skip to content

Instantly share code, notes, and snippets.

@dkirkby
dkirkby / add_top_axis.py
Created November 26, 2019 17:49
Add a top axis to a matplotlib graph
def add_top_axis(ax, bottom_grid, top_grid, ticks, fmt='%s', title=None, color='k',
grid=False, gridopts=dict(ls=':', alpha=0.25)):
scale = ax.get_xscale()
if scale not in ('linear', 'log'):
raise RuntimeError('xscale "{0}" not yet supported.'.format(scale))
top = ax.twiny()
sign = -1 if top_grid[-1] < top_grid[0] else +1
tick_bottom_coord = np.interp(ticks, top_grid[::sign], bottom_grid[::sign])
if scale == 'linear':
tick_loc = (tick_bottom_coord - bottom_grid[0]) / (bottom_grid[-1] - bottom_grid[0])
@dkirkby
dkirkby / grade.py
Last active December 21, 2020 23:44
import collections
def grade(file, offset,
breaks=collections.OrderedDict(
{'A+': 96.5, 'A': 93.5, 'A-': 90.0,
'B+': 86.5, 'B': 83.5, 'B-': 80.0,
'C+': 76.5, 'C': 73.5, 'C-': 70.0,
'D+': 66.5, 'D': 63.5, 'D-': 60.0, 'F': 0})):
stats = collections.OrderedDict({k: 0 for k in breaks})
values = []
def animate(files, save='animation.gif', interval=500, dpi=64):
images = []
fig, ax = None, None
for f in files:
imgdata = plt.imread(f)
if fig is None:
ny, nx = imgdata.shape[:2]
fig = plt.figure(figsize=(nx / dpi, ny / dpi), dpi=dpi, frameon=False)
ax = plt.axes((0, 0, 1, 1))
ax.axis('off')
@dkirkby
dkirkby / .bashrc
Last active November 14, 2022 23:57
Login environment shell customizations
# Add these to ~/.bash_aliases, creating the file (if necessary)
# then add these lines to your ~/.bashrc (if necessary)
#
# if [ -f ~/.bash_aliases ]; then
# . ~/.bash_aliases
# fi
# OS X 12 uses zsh so these go into .zshrc instead
alias last='history | fgrep'
@dkirkby
dkirkby / unshuffle.py
Last active May 19, 2020 21:13
Unshuffle
# Calculate the indexing of B that equals A, assuming that A is a shuffle of B and all elements are unique.
def unshuffle(A, B):
assert (A.shape == B.shape) and np.array_equal(np.unique(A), np.unique(B))
sorter = np.argsort(B)
return sorter[np.searchsorted(B, A, sorter=sorter)]
N = 10
A = np.random.uniform(size=N)
B = np.random.choice(A, N, replace=False)
assert np.array_equal(A, B[unshuffle(A, B)])
@dkirkby
dkirkby / chisq_calc.py
Last active May 21, 2020 15:23
Chi-square probability calculations
import scipy.stats
def nsigmas_to_CL(nsigmas=1., D=1):
return scipy.stats.chi2.cdf(x=nsigmas ** 2, df=D)
def CL_to_nsigmas(CL=0.95, D=1):
return np.sqrt(scipy.stats.chi2.ppf(q=CL, df=D))
# A "1-sigma" error bar contains ~68% of a 1D Gaussian, but only ~39% in 2D.
nsigmas_to_CL(nsigmas=1, D=[1, 2])
@dkirkby
dkirkby / numpy_where.py
Last active April 15, 2021 15:13
Select rows from structured numpy array using a condition expression
import io
import tokenize
def select(data, condition, as_mask=False):
"""Return rows in the structured numpy array (or astropy table) that satisfy a condition.
The condition is a string expression using column names to represent column values.
"""
# Get the valid identifiers.
names = data.dtype.names
@dkirkby
dkirkby / histogram_equalize.py
Created June 30, 2020 20:10
Perform histogram equalization on numpy array data
def equalize(A, clip_percent=5):
"""Equalize the values of an array.
The returned array has values between 0-1 such that clip_percent
of the values are clipped symmetrically at 0 and 1, and the
histogram of values between 0 and 1 is flat. This is a non-linear
transformation and primarily useful for showing small variations
over a large dynamic range.
"""
A_flat = A.reshape(-1)
n = len(A_flat)
@dkirkby
dkirkby / plot_pixels.py
Last active July 2, 2020 15:00
Plot an image without any pixel resampling
def plot_pixels(D, zoom=1, dpi=64, x0=0, y0=0, **args):
ny, nx = D.shape
width, height = zoom * nx, zoom * ny
fig = plt.figure(figsize=(width / dpi, height / dpi), dpi=dpi, frameon=False)
ax = plt.axes((0, 0, 1, zoom * ny / height))
extent = [x0 - 0.5, x0 + nx - 0.5, y0 - 0.5, y0 + ny - 0.5]
ax.imshow(D, extent=extent, **args)
ax.axis('off')
return fig, ax
@dkirkby
dkirkby / plotGradient.py
Last active July 31, 2020 14:29
Plot a rectangle with a gradient using matplotlib
def plotGradient(ax, xy, width, height, color='r', cmap=None, gradient=lambda x, y: x, alpha=lambda x,y: x ** 2):
"""
Args (xy), width, height as the same as for plt.Rectangle.
The axis must already have something drawn so that its coordinate system is defined.
The gradient is calculated per pixel at the time this is called. This will no longer be true
if there are later changes to the axis limits, but the gradient should still be visually ok.
However, for the best quality, do not change the axis limits after drawing gradients.
"""
# Convert the plot dimensions from data coords to pixels.
xy = np.asarray(xy)