v2.7.0
The nearest root in ParabolicSag.intercept (#224)
The intercept chose between the two roots of the quadratic by sign(f * uz),
which returns the far crossing for a ray starting on the surface — the
opposite side of the paraboloid — and optika.systems.SequentialSystem starts
rays there. It now takes the root with the smaller |d|, the crossing nearest
the ray, as AbstractConicSag.intercept already did for every other conic.
This moves any raytrace through a parabolic surface. Measured on the ESIS
model, whose primary mirror is one: the effective area moves between −0.20%
and +0.38% across the passband, and the peak relative illumination by 0.58%.
The mean illumination is pinned by its own normalization and does not move, so
the change is in the shape of the field rather than its level.
AnnularAperture (#225)
A new aperture. Additive.
The object is the frame the system moves in (#221)
transformation was composed onto the whole system, object included, and the
input rays were carried in from the global frame by its inverse. Moving
everything rigidly is a relabeling, so the one thing the attribute looks like
it should say — put the optics here relative to the source — was the one
thing it could not.
It is now composed onto the optics alone and the object is left fixed, so
setting it repositions the optics against the source.
This changes what transformation means, and no signature changed to say
so. Anything read in the object's frame moves with it: where the field of
view falls, and plots drawn in global coordinates. Anything computed in the
system's own normalized field and pupil coordinates does not, because those
are derived from the stops and the stops travel with the optics. On the ESIS
as-built model, whose system transformation is a 22.5° roll, the vignetting
model and the effective area are unchanged to every digit.
Both plots take axes to draw on (#223)
PolynomialVignettingModel.plot(), .plot_residual(), and
PolynomialDistortionModel.plot_residual() each built a figure of their own,
so two of them could not be put in one, and two figures do not share axes:
the panels of one did not line up with the panels of the other, and each
carried its own copy of the labels.
All three take an ax now. Given one, the figure comes from the axes and
figsize is ignored; given none, nothing changes. Axes not distributed along
axis_wavelength are refused, since one wavelength is drawn in each.
Putting the two side by side turned up that they disagreed. The distortion
residual already dropped the calibration points the fit was never constrained
by, and took its default upper limit with nanmax so that dropping them meant
something. The vignetting residual did neither, so for a model with a field
stop the points outside it — where no ray survives and the residual is the
prediction subtracted from nothing — were the largest values in the plot and
set the color scale for everything else. It now does what the distortion
residual does, which changes that plot for any model whose where is not
all true.