def test_all_to_value(): """test all_to_value""" x_m = np.arange(5) * u.m y_mm = np.arange(5) * 1000 * u.mm z_km = np.arange(5) * 1e-3 * u.km nono_deg = np.arange(5) * 1000 * u.deg # one argument x = all_to_value(x_m, unit=u.m) assert (x == np.arange(5)).all() # two arguments x, y = all_to_value(x_m, y_mm, unit=u.m) assert (x == np.arange(5)).all() assert (y == np.arange(5)).all() # three x, y, z = all_to_value(x_m, y_mm, z_km, unit=u.m) assert (x == np.arange(5)).all() assert (y == np.arange(5)).all() assert (z == np.arange(5)).all() # cannot be converted with pytest.raises(u.UnitConversionError): all_to_value(x_m, nono_deg, unit=x_m.unit)
def psf_likelihood_fit(x, y, weights): """ Do a likelihood fit using a ring with gaussian profile. Uses the kundu_chaudhuri_circle_fit for the initial guess Parameters ---------- x: array-like or astropy quantity x coordinates of the points y: array-like or astropy quantity y coordinates of the points weights: array-like weights of the points This will usually be x and y coordinates and pe charges of camera pixels Returns ------- radius: astropy-quantity radius of the ring center_x: astropy-quantity x coordinate of the ring center center_y: astropy-quantity y coordinate of the ring center std: astropy-quantity standard deviation of the gaussian profile (indictor for the ring width) """ unit = x.unit x, y = all_to_value(x, y, unit=unit) start_r, start_x, start_y = kundu_chaudhuri_circle_fit(x, y, weights) result = minimize( _psf_neg_log_likelihood, x0=(start_r, start_x, start_y, 5e-3), args=(x, y, weights), method="L-BFGS-B", bounds=[ (0, None), # radius should be positive (None, None), (None, None), (0, None), # std should be positive ], ) if not result.success: result.x = np.full_like(result.x, np.nan) return Quantity(result.x, unit)
def taubin_circle_fit(x, y, mask): """ reference : Barcelona_Muons_TPA_final.pdf (slide 6) Parameters ---------- x: array-like or astropy quantity x coordinates of the points y: array-like or astropy quantity y coordinates of the points mask: array-like boolean true for pixels surviving the cleaning """ original_unit = x.unit x, y = all_to_value(x, y, unit=original_unit) x_masked = x[mask] y_masked = y[mask] R = x.max() # x.max() just happens to be identical with R in many cases. taubin_r_initial = R / 2 taubin_error = R * 0.1 xc = 0 yc = 0 # minimization method fit = Minuit(make_taubin_loss_function(x_masked, y_masked), xc=xc, yc=yc, r=taubin_r_initial) fit.errordef = Minuit.LEAST_SQUARES fit.errors["xc"] = taubin_error fit.errors["yc"] = taubin_error fit.errors["r"] = taubin_error fit.limits["xc"] = (-2 * R, 2 * R) fit.limits["yc"] = (-2 * R, 2 * R) fit.limits["r"] = (0, R) fit.migrad() radius = Quantity(fit.values["r"], original_unit) center_x = Quantity(fit.values["xc"], original_unit) center_y = Quantity(fit.values["yc"], original_unit) return radius, center_x, center_y