Source code for mascado.distortions.analysis


import numpy as np
import pandas as pd

from mascado.distortions.polynomials import PolyVectorField, Legendre
from mascado.distortions.polyfit import polyfit_svd


[docs]def analyze_residuals_over_order( positions, distortions, maxorder, minorder=0, poly=Legendre, distortionunits="arcseconds", maxcondition=1e2, info=' '): """Get RMS of residuals after nth order fit. Parameters ---------- positions : (N, 2)-shaped array Normalized positions. distortions : (N, 2)-shaped array Distortions. maxorder : int End of iteration. minorder : int Start of iteration. poly : :class:`mascado.distortions.polynomials.Polynomial` subclass Class of polynomials to use (not an instance). By default, Legendre polynomials are used. distortionunits : str Units of distortions. Used for console output. info : str or False Indent of console output. Set to ``False`` to suppress output. Returns ------- pandas.DataFrame DataFrame with two columns: ``order`` and ``resrms``. """ subinfo = info + ' ' if info is not None else None orders = list(range(minorder, maxorder+1)) rmsperorder = [] for order in orders: if info is not False: print("{:s}Fitting {:d}. order {:s} polynomial".format( info, order, poly.__name__)) vf = PolyVectorField(poly(order)) _, residuals, _ = polyfit_svd(vf, positions, distortions, maxcondition=maxcondition, info=subinfo) resrms = np.sqrt(np.sum(residuals**2)/residuals.size) rmsperorder.append(resrms) if info is not False: print("{:s}Residual RMS: {:.3g} {:s}".format( subinfo, resrms, distortionunits)) tab = pd.DataFrame([orders, rmsperorder], index=['order', 'resrms']).T return tab
[docs]def analyze_contributions_over_order( vf, minorder=0, maxorder=None, gridsize=100, units="arcseconds", info=' '): r"""Get contributions of the terms of a specific degree. The contribution is measured as RMS of the vector field over the normalized coordinates :math:`[-1,1]\times[-1,1]`. The model is evaluated on a regular grid to calculate the RMS value. The grid has to be well sampled for the result to be correct. For higher orders, a larger ``gridsize`` is needed. Parameters ---------- vf : :class:`mascado.distortions.polynomials.PolyVectorField` Vector field with internal parameters. minorder : int maxorder : int or None If None, the order of the vector field is used. gridsize : int Number of points along each axis in normalized coordinates. units : str Units of vector field. Used for console output. info : str or False Indent of console output. Set to ``False`` to suppress output. Returns ------- pandas.DataFrame DataFrame with two columns: ``order`` and ``modelrms``. """ if maxorder is None: maxorder = vf.get_degree() orders = list(range(minorder, maxorder+1)) gridside = np.linspace(-1, 1, gridsize) xx, yy = np.meshgrid(gridside, gridside, indexing='ij') grid = np.stack([xx.ravel(), yy.ravel()], axis=1) rmsperdegree = [] for order in orders: subvf = vf.make_single_degree_subpoly(order) model = subvf.model(grid) modelrms = np.sqrt(np.sum(model**2)/model.size) rmsperdegree.append(modelrms) if info is not False: print("{:s}{:8.3g} {:s} RMS distortions in {:d}. degree terms" "".format(info, modelrms, units, order)) tab = pd.DataFrame([orders, rmsperdegree], index=['order', 'modelrms']).T return tab