Skip to main content

Robust laser and charged particle beam image analysis

Project description

BeamFit

This library contains methods to fit for the size of a beam in a noisy 2D image

Installation and Testing

Install through pip.

pip install beamfit

Fitting Quickstart

There's a couple of different options for fitting images which vary in how robust they are and how much information you need to feed them. The most simple fit only requires the image itself and is run with the following code. The beam we're fitting looks like this.

The beam

We'll also plot the residuals as a measure of goodness-of-fit. This should be done in an interactive environment like jupyter to see the plot.

# Load the image and run the fit
img = imageio.imread('beam.png')
h, C = beamfit.fit_supergaussian(img, image_weights=np.ones_like(img))

# The image and the fit
plt.subplot(1,2,1)
beamfit.plot_beam_contours(img, h)

# The residuals
plt.subplot(1,2,2)
beamfit.plot_residuals(img, h)

The fitting function should output the parameters of best fit (h) and an estimation of the variance-covariance matrix for the parameters (C). The fit looks like the following.

The fit

The fit looks good, notice that there is a nearly uniform pattern of noise in the residual and that the contours of the fit in the plot to the left are nicely centered on the beam. Sometimes the beam will be clipped on the edge of the screen. To fix this, add a mask to the image which defines the location of the screen. This image must be the same size as the beam images and should be black on the screen and white outside of the screen. The mask can easily be generated from one of the beam images using gimp or another image editting tool. Here is an example mask for this image.

Mask

Let's run a fit using the masked image.

# Load the image and mask
img = imageio.imread('beam.png')
mask = imageio.imread('mask.png')

# Mask the image and fit it
img_masked = np.ma.masked_array(data=img, mask=mask)
h, C = beamfit.fit_supergaussian(img_masked, image_weights=np.ones_like(img))

# The image and the fit
plt.subplot(1,2,1)
beamfit.plot_beam_contours(img_masked, h)

# The residuals
plt.subplot(1,2,2)
beamfit.plot_residuals(img_masked, h)

This will give the following fits

Masked fit

You can see that the beam is once again fit nicely and for beams close to the edge of the screen the mask can become important.

The final piece of information that can be used to improve the fit is a weighting of each pixel for how important it is for the least squares loss function. When you are averaging multiple beam images (say from an experiment where you take many images of the same beam) you can compute the weighting from the standard error of the mean of each pixel. Beamfit has a function that will do this for you already along with background subtraction.

# Load the beam images
img1 = imageio.imread('beam1.png')
img2 = imageio.imread('beam2.png')
img3 = imageio.imread('beam3.png')

# Load the background images
bak1 = imageio.imread('background1.png')
bak2 = imageio.imread('background2.png')
bak3 = imageio.imread('background3.png')

# Load the mask, compute the image and weights
mask = imageio.imread('mask.png')
img, w = beamfit.get_image_and_weight([img1, img2, img3], [bak1, bak2, bak3], mask)

# Perform the fit
h, C = beamfit.fit_supergaussian(img_masked, image_weights=np.ones_like(img))

I'm not going to show the fits here because they will be the same as before. For most applications you want the mean and variance of the fit distribution for interfacing with other code. Beamfit has functions built in to convert from the internal parameters of best fit to the mean and variance.

# Compute the mean and variance and their uncertainty
mu, sigma = beamfit.get_mu_sigma(h, 50e-6)
mu_std, sigma_std = beamfit.get_mu_sigma_std(h, C, 50e-6, 1e-9)

# Print the location and size for the user
beamfit.pretty_print_loc_and_size(h, C, 50e-6, 1e-9)

We also print the location for the user using the built in beamfit routine.

Compiled Supergaussian ufuncs

For performance reasons, the supergaussian and supergaussian derivative functions are implemented as numpy ufuncs in a compiled c extension. These ufuncs are exported in the extension beamfit.gaussufunc and compute the value and gradient of the function sgauss(r) = A*exp( ((r-mu)*C*(r-mu)^T)^n ) + O. The vector r is a 2D position r = [X, Y], A and O are the amplitude and offset of the distribution. The vector mu is the mean mu = [mux, muy] and CV is the variance-covariance matrix C = [[Vxx, Vxy], [Vxy, Vxx]]. The supergaussian parameter is n. The signature of the ufuncs are

# Supergaussian ufunc
beamfit.gaussufunc.supergaussian(X, Y, mux, muy, Vxx, Vxy, Vyy, n, A, O)

# Supergaussian gradient ufunc
beamfit.gaussufunc.supergaussian_grad(X, Y, mux, muy, Vxx, Vxy, Vyy, n, A, O)

Reference

fit_supergaussian(image, image_weights=None, prediction_func=None, sigma_threshold=3, sigma_threshold_guess=1)

The primary fitting routine. It will perform a contrained non-linear fit of 2D supergaussian to the provided image. This method by default will use a linear least squares fit to a regular 2D gaussian to form a prediction of the best fit parameters. It then uses scipy's implementation of Levenberg-Marquardt fitting on a bounded set of parameters to hone in on the final non-linear fit.

Parameters
  • image: array_like The image of the beam to fit. Must be a 2D numpy array and is compatible with numpy masked arrays as a means of specifying which pixels are not part of the beam.
  • image_weights: array_like The weight of each pixel in the least squares fit. When the variance of each pixel is known, the weights will be w = 1/V(pixels). Must be a 2D numpy array or None.
  • prediction_func: function A function that returns a prediction of the supergaussian parameters before the non-linear fit. Should accept an image (2D numpy array) and return the estimated parameters h (numpy array).
  • sigma_threshold: float Only part of the image is passed to the non-linear fit based on a threshold of the initially estimated gaussian. This parameter is the width of the region included in the threshold measured in the number of standard deviations of the distribution.
  • sigma_threshold_guess: float The same as sigma_threshold, but for the linear least squares prediction function.
Returns
  • h: array_like The parameters of best fit. It is a 1D numpy array with the elements h = np.array([mux, muy, Vxx, Vxy, Vyy, n, A, O]). These are the same parameters in the same order as in the numpy ufuncs.
  • C: array_like The estimated variance-covariance matrix of the fit parameters. A 2D numpy array where the rows/columns are labeled in the same order as h.
beamfit.get_image_and_weight(raw_images, dark_fields, mask)

Computes the mean background subtracted image and weights for use with beamfit.

Parameters
  • raw_images: list of array_like A list of 2D numpy arrays representing the beam images. Must be more than one image in the list.
  • dark_fields: list of array_like A list of 2D numpy arrays representing the background images. Should have the same size as the beam images
  • mask: array_like The mask as a 2D boolean numpy array. Should have the same dimensions as raw_images and dark_fields.
Returns
  • image: array_like The averaged and background subtracted beam image.
  • weights: array_like Weights compatible with beamfit computed from the variance of the images and backgrounds.
beamfit.gaussufunc.supergaussian(X, Y, mux, muy, Vxx, Vxy, Vyy, n, A, O)

Compiled version of the supergaussian function sgauss(r) = A*exp( ((r-mu)*C*(r-mu)^T)^n ) + O.

Parameters
  • X: array_like x coordinate of the position vector
  • Y: array_like y coordinate of the position vector Must have same dimension as X.
  • mux: float x coordinate of the mean of the gaussian
  • muy: float y coordinate of the mean of the supergaussian
  • Vxx: float Upper left element of variance-covariance matrix
  • Vxy: float Off diagonal elements of the variance-covariance matrix
  • Vyy: float Bottom right element of the variance-covariance matrix
  • n: float The supergaussian parameter
  • A: float Amplitude of the distribution
  • O: float Offset of the distribution
Returns
  • supergaussian: array_like The evaluated supergaussian.
beamfit.gaussufunc.supergaussian_grad(X, Y, mux, muy, Vxx, Vxy, Vyy, n, A, O)

Compiled version of the gradient of the supergaussian function sgauss(r) = A*exp( ((r-mu)*C*(r-mu)^T)^n ) + O.

Parameters
  • X: array_like x coordinate of the position vector
  • Y: array_like y coordinate of the position vector Must have same dimension as X.
  • mux: float x coordinate of the mean of the gaussian
  • muy: float y coordinate of the mean of the supergaussian
  • Vxx: float Upper left element of variance-covariance matrix
  • Vxy: float Off diagonal elements of the variance-covariance matrix
  • Vyy: float Bottom right element of the variance-covariance matrix
  • n: float The supergaussian parameter
  • A: float Amplitude of the distribution
  • O: float Offset of the distribution
Returns
  • supergaussian_grad: tuple of array_like The gradient of the supergaussian. Each element of the tuple is one element of the gradient where they are in the same order as the parameters to this function.
beamfit.get_mu_sigma(h, pixel_size)

Converts the parameters of best fit to the mean and variance of the distribution.

Parameters
  • h: array_like The paremeters of best fit
  • pixel_size: float A scaling factor for the pixels in units of meters.
Returns
  • mu: array_like The mean of the distribution in meters
  • sigma: array_like The variance of the distribution in meters^2
beamfit.get_mu_sigma_std(h, C, pixel_size, pixel_size_std)

Converts the parameters of best fit into the uncertainty of the mean and variance of the distribution.

Parameters
  • h: array_like The paremeters of best fit
  • C: array_like The variance-covariance matrix of the parameters
  • pixel_size: float A scaling factor for the pixels in units of meters.
  • pixel_size_std: float An estimate of the uncertainty in the pixel scale factor
Returns
  • mu_std: array_like The uncertainty of the mean of the distribution in meters
  • sigma_std: array_like The uncertainty of the variance of the distribution in meters^2
beamfit.pretty_print_loc_and_size(h, C, pixel_size, pixel_size_std)

Prints a nice version of the mean and variance of the distribution.

Parameters
  • h: array_like The paremeters of best fit
  • C: array_like The variance-covariance matrix of the parameters
  • pixel_size: float A scaling factor for the pixels in units of meters.
  • pixel_size_std: float An estimate of the uncertainty in the pixel scale factor
Returns

No return

beamfit.plot_residuals(image, h, sigma_threshold=2)

Plots the residuals of the fit using matplotlib. Compatible with other matplotlib plotting functions through their stateful interface.

Parameters
  • image: array_like
  • h: array_like The paremeters of best fit
  • sigma_threshold: float
Returns

No return

beamfit.plot_beam_contours(image, h)

Plots the beam image and a countour plot of the fit supergaussian on top of it using matplotlib functions. Compatible with the matplotlib stateful interface.

Parameters
  • image: array_like
  • h: array_like The paremeters of best fit
Returns

No return

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

beamfit-1.13.tar.gz (25.1 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

beamfit-1.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (43.5 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

beamfit-1.13-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (43.2 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64manylinux: glibc 2.5+ x86-64

beamfit-1.13-cp312-cp312-macosx_11_0_arm64.whl (31.6 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

beamfit-1.13-cp312-cp312-macosx_10_13_x86_64.whl (31.5 kB view details)

Uploaded CPython 3.12macOS 10.13+ x86-64

beamfit-1.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (43.0 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ ARM64

beamfit-1.13-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (42.7 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64manylinux: glibc 2.5+ x86-64

beamfit-1.13-cp311-cp311-macosx_11_0_arm64.whl (31.6 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

beamfit-1.13-cp311-cp311-macosx_10_9_x86_64.whl (31.5 kB view details)

Uploaded CPython 3.11macOS 10.9+ x86-64

beamfit-1.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (42.9 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ ARM64

beamfit-1.13-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (42.6 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64manylinux: glibc 2.5+ x86-64

beamfit-1.13-cp310-cp310-macosx_11_0_arm64.whl (31.6 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

beamfit-1.13-cp310-cp310-macosx_10_9_x86_64.whl (31.5 kB view details)

Uploaded CPython 3.10macOS 10.9+ x86-64

beamfit-1.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (42.9 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ ARM64

beamfit-1.13-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (42.6 kB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64manylinux: glibc 2.5+ x86-64

beamfit-1.13-cp39-cp39-macosx_11_0_arm64.whl (31.6 kB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

beamfit-1.13-cp39-cp39-macosx_10_9_x86_64.whl (31.5 kB view details)

Uploaded CPython 3.9macOS 10.9+ x86-64

File details

Details for the file beamfit-1.13.tar.gz.

File metadata

  • Download URL: beamfit-1.13.tar.gz
  • Upload date:
  • Size: 25.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for beamfit-1.13.tar.gz
Algorithm Hash digest
SHA256 6e6a023e52507ba44dd93eb21267c9484ee995d2a397f91eb6a929b5bbbd313c
MD5 95d3888b8500737e0d9f06df73229590
BLAKE2b-256 a17fc97b82df5ca5364644c177577b84ab264be513faf52bba19bb664b9ef1e5

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 259d3d8728518717b11b9ce106fff408b74bdbd55b08480dbbe369cdad4c60aa
MD5 0c5009acc2f522fc1229a8707256c68a
BLAKE2b-256 33ea2122c449a5114690c0f9b9242df9959af6fe54042df05536d51973f201a8

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6855d0c3c29a8538827fad859db6f814474211bf32e68060600b5ab323804d58
MD5 d9e0821ecb52aa7baac1fddf99d73d4c
BLAKE2b-256 c64f67cf6bb0ba5c16f120e46633405559ef19e23914d6d43155962c2715b1db

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7b0469ab768dfff7b1cb58d6cb38fe54507de5c23d7f12175756828f59c3b2cc
MD5 71e67850dd23e7142fa8a07be191fc16
BLAKE2b-256 4fbef9bbcc05346e1d25edb007a5972bef9a060452d80735a13f9dd1586ea142

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp312-cp312-macosx_10_13_x86_64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp312-cp312-macosx_10_13_x86_64.whl
Algorithm Hash digest
SHA256 cbdb0ec3dad11fc6ecbdb554099e450b4e073c3ac2674a18cc01c80e3e0a103f
MD5 e97c7a52ec39f42389317f91542341ac
BLAKE2b-256 5b8ac889aa7b88f345888938725041ae9662a0bf0c8cc8d66bdde7add06cc954

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4dcb82c0496f2295ae884f0cfefb130e46b76a0b2a8a42b64e255eef7aed7628
MD5 8f58aa2da5465ae80fe4002d52cbf837
BLAKE2b-256 7453447b3e44aeb1f4af8820e8c7933d42c367310d1c711c4f46b3e489931502

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 657ca3fead81db719456a5ba682e8684f441bf5a3e29bc43b8f703f0f3e83d0a
MD5 96a6b87e395c1e0e22a04fc98555472a
BLAKE2b-256 448b3270cea8af62fd687e9bb06cee5bfc7b5b5c252645cd836db4b68e142322

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ea5e452c1b0a91b12e84fdf92d1f243b4888a87569974dbb2159c4b38371b02f
MD5 a37f8cf8e1c64988c84920ece90ef490
BLAKE2b-256 283258b88f017cb15c895f43b85167a89f56690394b68293557d9b7bfbc8f73a

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 b66dac5e9deb9a54952af6bebcd1f3dd34607b8b2f57fd22ee22b8a16e69644a
MD5 ba218cfe5e3039f3f25c3ee9e502bdef
BLAKE2b-256 ac0543436e228ed4b87abab07c75c281bd44dcec5459af37ebc9538934389bcb

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 42abacf9745ad3f7c88d27759d36346be93ffa5c3ae938d3b3e2c782681e4eb6
MD5 2689c0d6da441f5c10db3e62da751df8
BLAKE2b-256 dcd86d0d996e862ad1d179e43e8c70f4d73a8c4ab0a13768b37eb8c60d9cbcde

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d13818de16861f3ca8b6574f1c84017bb5f4324ef1772384ce0137b177cd2b75
MD5 845472d274a725411f2c3ebab32770af
BLAKE2b-256 3314874ac1068ba1d2d2182016af2ecf1abd85f755e978634c11b5fababcff83

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3a08442b6c88803e1c1024b6a0c907651b03d898f13340480f30e44c9a956168
MD5 73ef2938ac80a36d773b390528b35689
BLAKE2b-256 6fb3308a83473437a0fa7e8aedc2d6e7ccdd5d75334f82fc78dead46704318f1

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 4ffbdce39cfc295f02be911382a337001125cb19341ab6e204bfeeb631f3aefb
MD5 9d18b8554441105a3f09882820586ca0
BLAKE2b-256 3a56f9f02e3014748eae8d0adb2436ca1b60d132a69f4e41e48808e4295498b1

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 174d4f3437e10faae6d44e5e49775e555f0ae34c0a3e69a37b36185732ab70fd
MD5 cb45a6104f98771c0ccba80ee9e20a50
BLAKE2b-256 582c1d7cb1fd1a20ebe207307be766c5b5d2d16d95e08dde1a5be114a14c0560

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 55acb2a096b83bb7314c891bf9ce391ac10b96583ee831d71c4b7596db9c49dc
MD5 34294fc740510f13786ad2b7e15d46ce
BLAKE2b-256 ca29dc3ae3d75a487cc837ed6750b6c33ec5c3ae20386777a184199b21911f11

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 292446445a94d1be7c49539d4d9d2a499bbdf75579c96fb7955c4b605786bb28
MD5 3b88f4e61a5addcfdec1358c0c366cf9
BLAKE2b-256 eed99e1706f652fcf1a489bc656004d4b855af9ff4df8ac1747aa35c233b4451

See more details on using hashes here.

File details

Details for the file beamfit-1.13-cp39-cp39-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for beamfit-1.13-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 63513cc2a924226a4b2c283cc1612a0b22739d88e76095d7ca4e4340aa55c562
MD5 4702c2c3ae3ad47bc63a93527be2b209
BLAKE2b-256 75b475ce73389cd366f08cb6031bff8ecd9184cf01ea544d356ce3932b180c5a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page