From 821f23bcc058afef0bc83d3269ccb9a6eaac8ef9 Mon Sep 17 00:00:00 2001 From: Marshall Perrin Date: Fri, 3 May 2024 14:36:47 -0400 Subject: [PATCH] add model for the series of peaks within the cruciform --- stpsf/constants.py | 8 ++++++++ stpsf/detectors.py | 26 ++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/stpsf/constants.py b/stpsf/constants.py index 1ef44ea4..3bc62afa 100644 --- a/stpsf/constants.py +++ b/stpsf/constants.py @@ -407,3 +407,11 @@ 'NIRSPEC': {'sigma': 0.05}, 'MIRI': {'sigma': 0.05}, } + +# Various parameters to model the more complex parts of the cruciform +# There's a fair amount of ad-hoc tuning still needed here to match real data +MIRI_CRUCIFORM_PEAK_REFWAVE = 5.5 # # See Gaspar et al. sections 4.2 and 4.3 +MIRI_CRUCIFORM_PEAKS_LOC = [12/1.1, 16.5, 19.5, 23.5, 27.9, 33, 39.6] # pixels, at 5.5 microns, for the centered PSF; slightly tuned to in-flight ePSFs +MIRI_CRUCIFORM_PEAKS_AMP = [1.8e-4, 1.0e-4, 1.0e-4, 9e-5, 4e-5, 2e-5, 1e-5] # read off from fig 12 in Gaspar et al. Slightly tuned to in-flight ePSFs. +MIRI_CRUCIFORM_PEAKS_AMP_ADJUST = 20 # ad hoc scale factor, for units conversion from fig 12 to how it's normalized here +MIRI_CRUCIFORM_PEAKS_SIGMA = 1 # how wide are the peaks/bumps along the crucifor diff --git a/stpsf/detectors.py b/stpsf/detectors.py index d05d97f3..4ea40c8d 100644 --- a/stpsf/detectors.py +++ b/stpsf/detectors.py @@ -338,11 +338,33 @@ def _make_miri_scattering_kernel_2d(in_psf, kernel_amp, oversample=1, wavelength kernel_x[np.abs(x) < constants.MIRI_CRUCIFORM_INNER_RADIUS_PIX] *= 0.5 kernel_y[np.abs(y) < constants.MIRI_CRUCIFORM_INNER_RADIUS_PIX] *= 0.5 - # Add in the offset copies of the main 1d kernels + # add in the extra diffraction peaks into each 1d kernel, as seen in Gaspar et al. 2021 + # but first, save the total flux for normalization later + normfactor = kernel_x.sum() + # Empirically, the 'center' of the cruciform shifts inwards towards the center of the detector - # i.e. for the upper right corner, the cruciform shifts down and left a bit, etc. + # i.e. for the upper right corner, the cruciform shifts down and left a bit, etc. + # Turns out the centers of the peaks in each cruciform arm also seem to shift a bit, so + # let's use the same shifts to try to model those, with some scale factor yshift = cruciform_yshifts(detector_position[1]) xshift = cruciform_xshifts(detector_position[0]) + + for loc, amp in zip(constants.MIRI_CRUCIFORM_PEAKS_LOC, constants.MIRI_CRUCIFORM_PEAKS_AMP): + # Empirically, the locations of the peaks shift slightly around the FOV, in the opposite sign as the cruciform itself shifts + # we model this ad hoc based on comparisons iwth the ePSF data. + # The scale factors here are a bit of a handwave by eye, not yet a rigorous fit... + scaled_loc_x = loc * wavelength / constants.MIRI_CRUCIFORM_PEAK_REFWAVE * 1.1 + scaled_loc_y = loc * wavelength / constants.MIRI_CRUCIFORM_PEAK_REFWAVE * 1.1 + + scaled_amp = amp * constants.MIRI_CRUCIFORM_PEAKS_AMP_ADJUST # ad hoc, to make it work; basically a units scale factor from the plot in Andras' paper + peak_x = scaled_amp * np.exp(-(x-scaled_loc_x + xshift/2)**2) + scaled_amp * np.exp(-(x+scaled_loc_x + xshift/2)**2) + peak_y = scaled_amp * np.exp(-(y-scaled_loc_y + yshift/2)**2) + scaled_amp * np.exp(-(y+scaled_loc_y + yshift/2)**2) + kernel_x += peak_x + kernel_y += peak_y + kernel_x *= normfactor/kernel_x.sum() + kernel_y *= normfactor/kernel_y.sum() + + # Add in the offset copies of the main 1d kernels kernel_2d[cen + int(round(yshift * oversample))] = kernel_x kernel_2d[:, cen + int(round(xshift * oversample))] = kernel_y