pypeit.containers.bspline module

FITS-serializable wrappers for the BSpline and BSpline2D classes.

Each container inherits from both DataContainer (for FITS I/O) and its respective algorithmic base class (for all fitting and evaluation methods). The dual inheritance requires a specific construction order: __init__ must run first to establish the attribute-enforcement mechanism, after which the base-class constructor runs against the already-prepared __dict__.

Note

The breakpoints property defined on BSpline is a read-only data descriptor that delegates to self.knots.breakpoints. Using breakpoints as a datamodel key would create an irresolvable naming conflict (the property intercepts all attribute-level reads, making the stored value invisible). The breakpoint array is therefore stored under the distinct key bkpt_full, and the property continues to serve all algorithmic code via self.knots.

class pypeit.containers.bspline.BSpline2DContainer(x=None, knots=None, nord=4)[source]

Bases: DataContainer, BSpline2D

FITS-serializable wrapper for BSpline2D.

Inherits all fitting and evaluation methods from BSpline2D and adds FITS I/O via DataContainer. Instances can be used wherever a plain BSpline2D is expected.

The datamodel attributes are:

Version: 2.0.0

Attribute

Type

Array Type

Description

basis

numpy.ndarray

numpy.floating

Polynomial basis matrix, shape (N, npoly); stored only when fit was called with a numpy array basis (funcname is None).

bkpt_full

numpy.ndarray

numpy.floating

Full padded knot vector stored for serialization.

bkpt_gpm

numpy.ndarray

numpy.bool

Active-breakpoint mask; True where a breakpoint participates in the fit.

coeff

numpy.ndarray

numpy.floating

Fitted 2D B-spline coefficients, shape (nc, npoly).

funcname

str

Polynomial family name (e.g. legendre); None when fit was called with an array basis.

icoeff

numpy.ndarray

numpy.floating

Inverse-covariance diagonal, shape (nc, npoly).

nord

int

Order of the B-spline.

npoly

int

Number of polynomial basis functions in the second dimension.

xmax

float

Upper normalisation bound for the polynomial basis coordinate.

xmin

float

Lower normalisation bound for the polynomial basis coordinate.

The basis datamodel field is populated only when fit() was called with a numpy.ndarray basis argument (i.e., when funcname is None after fitting). Storing the basis enables evaluation via value() without re-supplying it after loading from a file. When the fit was performed with a string basis (e.g. 'legendre'), basis is None and the caller must supply basis_x to value().

Parameters:
  • x (numpy.ndarray, optional) – Independent variable used to build the initial breakpoint grid.

  • knots (Knots or numpy.ndarray or None, optional) – Knot specification.

  • nord (int, optional) – Order of the B-spline (default 4).

_bundle()[source]

Overrides the base class method used to bundle the datamodel for FITS serialization.

Captures any in-place changes to knots.breakpoints in bkpt_full and, for array-basis fits (funcname is None), copies P to basis so that the polynomial basis matrix can be recovered on load via _validate().

Beyond that, the method uses the base class method and sets the FITS extension name to 'BSPLINE2D'.

_validate()[source]

Overrides the base class validation method called during instantiation.

Specifically, this method rebuilds knots from bkpt_full and restore P from basis when they are not set by the constructor.

This extends the BSplineContainer logic with an additional step for array-basis fits: when basis is populated but P is None, P is restored from basis so that value() can be called immediately after any dict-based instantiation (e.g. from_file(), from_bspline2d()) without re-supplying the basis array.

copy()[source]

Return a deep copy as a new BSpline2DContainer.

The design-matrix cache is not copied (the copy starts with a cold cache). The polynomial basis P is copied when it exists: for array-basis fits (funcname is None) it is already restored from basis by _validate(); for string-basis fits it is copied explicitly.

Return type:

BSpline2DContainer

datamodel = {'basis': {'atype': <class 'numpy.floating'>, 'descr': 'Polynomial basis matrix, shape (N, npoly); stored only when fit was called with a numpy array basis (funcname is None).', 'otype': <class 'numpy.ndarray'>}, 'bkpt_full': {'atype': <class 'numpy.floating'>, 'descr': 'Full padded knot vector stored for serialization.', 'otype': <class 'numpy.ndarray'>}, 'bkpt_gpm': {'atype': <class 'numpy.bool'>, 'descr': 'Active-breakpoint mask; True where a breakpoint participates in the fit.', 'otype': <class 'numpy.ndarray'>}, 'coeff': {'atype': <class 'numpy.floating'>, 'descr': 'Fitted 2D B-spline coefficients, shape (nc, npoly).', 'otype': <class 'numpy.ndarray'>}, 'funcname': {'descr': 'Polynomial family name (e.g. ``legendre``); None when fit was called with an array basis.', 'otype': <class 'str'>}, 'icoeff': {'atype': <class 'numpy.floating'>, 'descr': 'Inverse-covariance diagonal, shape (nc, npoly).', 'otype': <class 'numpy.ndarray'>}, 'nord': {'descr': 'Order of the B-spline.', 'otype': <class 'int'>}, 'npoly': {'descr': 'Number of polynomial basis functions in the second dimension.', 'otype': <class 'int'>}, 'xmax': {'descr': 'Upper normalisation bound for the polynomial basis coordinate.', 'otype': <class 'float'>}, 'xmin': {'descr': 'Lower normalisation bound for the polynomial basis coordinate.', 'otype': <class 'float'>}}

Provides the class data model. This is undefined in the abstract class and should be overwritten in the derived classes.

The format of the datamodel needed for each implementation of a DataContainer derived class is as follows.

The datamodel itself is a class attribute (i.e., it is a member of the class, not just of an instance of the class). The datamodel is a dictionary of dictionaries: Each key of the datamodel dictionary provides the name of a given datamodel element, and the associated item (dictionary) for the datamodel element provides the type and description information for that datamodel element. For each datamodel element, the dictionary item must provide:

  • otype: This is the type of the object for this datamodel item. E.g., for a float or a numpy.ndarray, you would set otype=float and otype=np.ndarray, respectively.

  • descr: This provides a text description of the datamodel element. This is used to construct the datamodel tables in the pypeit documentation.

If the object type is a numpy.ndarray, you should also provide the atype keyword that sets the type of the data contained within the array. E.g., for a floating point array containing an image, your datamodel could be simply:

datamodel = {'image' : dict(otype=np.ndarray, atype=float, descr='My image')}

More advanced examples are given in the top-level module documentation.

Currently, datamodel components are restricted to have otype that are tuple, int, float, numpy.integer, numpy.floating, numpy.ndarray, or astropy.table.Table objects. E.g., datamodel values for otype cannot be dict.

fit(x, y, ivar=None, basis='legendre', npoly=1, basis_x=None, xmin=None, xmax=None, reset_knots=False)[source]

Fit a weighted least-squares 2D B-spline.

This delegates entirely to fit(), but updates bkpt_full, as necessary. See documentation for fit().

classmethod from_bspline2d(spl)[source]

Construct a BSpline2DContainer from an existing BSpline2D.

Parameters:

spl (BSpline2D) – Source B-spline. Its breakpoints must not be None.

Returns:

A new container wrapping a copy of the spline state. The basis datamodel field is populated only when spl.funcname is None and spl.P is not None (array-basis fit); otherwise it is None.

Return type:

BSpline2DContainer

internals = ['knots', 'x', 'yfit', '_cached_design', 'P', 'basis_x']

A list of strings identifying a set of internal attributes that are not part of the datamodel.

version = '2.0.0'

Provides the string representation of the class version.

This is currently put to minimal use so far, but will used for I/O verification in the future.

Each derived class should provide a version to guard against data model changes during development.

class pypeit.containers.bspline.BSplineContainer(x=None, knots=None, nord=4)[source]

Bases: DataContainer, BSpline

FITS-serializable wrapper for BSpline.

Inherits all fitting and evaluation methods from BSpline and adds FITS I/O via DataContainer. Instances can be used wherever a plain BSpline is expected.

The datamodel attributes are:

Version: 2.0.0

Attribute

Type

Array Type

Description

bkpt_full

numpy.ndarray

numpy.floating

Full padded knot vector stored for serialization.

bkpt_gpm

numpy.ndarray

numpy.bool

Active-breakpoint mask; True where a breakpoint participates in the fit.

coeff

numpy.ndarray

numpy.floating

Fitted B-spline coefficients, shape (nc,).

icoeff

numpy.ndarray

numpy.floating

Inverse-covariance diagonal, shape (nc,).

nord

int

Order of the B-spline.

Parameters:
  • x (numpy.ndarray, optional) – Independent variable used to build the initial breakpoint grid. Passed directly to BSpline.

  • knots (Knots or numpy.ndarray or None, optional) – Knot specification. Passed directly to BSpline.

  • nord (int, optional) – Order of the B-spline (default 4).

_bundle()[source]

Overrides the base class method used to bundle the datamodel for FITS serialization.

The method ensures any in-place changes to knots.breakpoints (e.g. from a fit() call with reset_knots=True) are captured in bkpt_full before the datamodel attributes are packaged for writing.

Beyond that, the method uses the base class method and sets the FITS extension name to 'BSPLINE'.

_validate()[source]

Overrides the base class validation method called during instantiation.

Specifically, this method rebuilds knots from bkpt_full when knots were not set by the constructor.

knots is an internal (not stored in the datamodel), so it is None after any dict-based instantiation (e.g. from_file(), from_bspline()). This override rebuilds it from the stored bkpt_full array so that all fitting and evaluation methods work without further intervention. bkpt_gpm is initialized to all-True when it is absent from the source data.

copy()[source]

Return a deep copy as a new BSplineContainer.

The design-matrix cache is not copied (the copy starts with a cold cache), matching the behavior of pypeit.core.bspline.BSpline.copy().

Return type:

BSplineContainer

datamodel = {'bkpt_full': {'atype': <class 'numpy.floating'>, 'descr': 'Full padded knot vector stored for serialization.', 'otype': <class 'numpy.ndarray'>}, 'bkpt_gpm': {'atype': <class 'numpy.bool'>, 'descr': 'Active-breakpoint mask; True where a breakpoint participates in the fit.', 'otype': <class 'numpy.ndarray'>}, 'coeff': {'atype': <class 'numpy.floating'>, 'descr': 'Fitted B-spline coefficients, shape (nc,).', 'otype': <class 'numpy.ndarray'>}, 'icoeff': {'atype': <class 'numpy.floating'>, 'descr': 'Inverse-covariance diagonal, shape (nc,).', 'otype': <class 'numpy.ndarray'>}, 'nord': {'descr': 'Order of the B-spline.', 'otype': <class 'int'>}}

Provides the class data model. This is undefined in the abstract class and should be overwritten in the derived classes.

The format of the datamodel needed for each implementation of a DataContainer derived class is as follows.

The datamodel itself is a class attribute (i.e., it is a member of the class, not just of an instance of the class). The datamodel is a dictionary of dictionaries: Each key of the datamodel dictionary provides the name of a given datamodel element, and the associated item (dictionary) for the datamodel element provides the type and description information for that datamodel element. For each datamodel element, the dictionary item must provide:

  • otype: This is the type of the object for this datamodel item. E.g., for a float or a numpy.ndarray, you would set otype=float and otype=np.ndarray, respectively.

  • descr: This provides a text description of the datamodel element. This is used to construct the datamodel tables in the pypeit documentation.

If the object type is a numpy.ndarray, you should also provide the atype keyword that sets the type of the data contained within the array. E.g., for a floating point array containing an image, your datamodel could be simply:

datamodel = {'image' : dict(otype=np.ndarray, atype=float, descr='My image')}

More advanced examples are given in the top-level module documentation.

Currently, datamodel components are restricted to have otype that are tuple, int, float, numpy.integer, numpy.floating, numpy.ndarray, or astropy.table.Table objects. E.g., datamodel values for otype cannot be dict.

fit(x, y, ivar=None, reset_knots=False)[source]

Fit a weighted least-squares B-spline.

This delegates entirely to fit(), but updates bkpt_full, as necessary. See documentation for fit().

classmethod from_bspline(spl)[source]

Construct a BSplineContainer from an existing BSpline.

Parameters:

spl (BSpline) – Source B-spline. Its breakpoints must not be None.

Returns:

A new container wrapping a copy of the spline state. The transient internals x and yfit are not copied; call fit() or use copy() if those are needed.

Return type:

BSplineContainer

internals = ['knots', 'x', 'yfit', '_cached_design']

A list of strings identifying a set of internal attributes that are not part of the datamodel.

version = '2.0.0'

Provides the string representation of the class version.

This is currently put to minimal use so far, but will used for I/O verification in the future.

Each derived class should provide a version to guard against data model changes during development.