From 4123c026d99ad4387991dde4a43c7403dfe64700 Mon Sep 17 00:00:00 2001 From: Marshall Perrin Date: Mon, 1 Apr 2024 11:34:39 -0400 Subject: [PATCH] cache loaded SIAF to avoid repeated slow loads of the SIAF --- webbpsf/distortion.py | 3 ++- webbpsf/opds.py | 2 +- webbpsf/optics.py | 3 ++- webbpsf/webbpsf_core.py | 10 +++++++++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/webbpsf/distortion.py b/webbpsf/distortion.py index 831da386..06c88f1e 100644 --- a/webbpsf/distortion.py +++ b/webbpsf/distortion.py @@ -7,6 +7,7 @@ from scipy.ndimage import rotate from soc_roman_tools.siaf.siaf import RomanSiaf +import webbpsf.webbpsf_core def _get_default_siaf(instrument, aper_name): """ @@ -39,7 +40,7 @@ def _get_default_siaf(instrument, aper_name): siaf = RomanSiaf() aper = siaf[aper_name] else: - siaf = pysiaf.Siaf(siaf_name) + siaf = webbpsf.webbpsf_core.get_siaf_with_caching(siaf_name) aper = siaf.apertures[aper_name] return aper diff --git a/webbpsf/opds.py b/webbpsf/opds.py index 24686322..bccdd001 100644 --- a/webbpsf/opds.py +++ b/webbpsf/opds.py @@ -1226,7 +1226,7 @@ def __init__(self, name='Unnamed OPD', opd=None, opd_index=0, transmission=None, elif 'nrs' in control_point_detector: control_point_instr = 'nirspec' - self.ote_control_point = pysiaf.Siaf(control_point_instr)[self.control_point_fieldpoint.upper()].reference_point('tel')*u.arcsec + self.ote_control_point = webbpsf.webbpsf_core.get_siaf_with_caching(control_point_instr)[self.control_point_fieldpoint.upper()].reference_point('tel')*u.arcsec if zero: self.zero() diff --git a/webbpsf/optics.py b/webbpsf/optics.py index 6e09131d..8d39a593 100644 --- a/webbpsf/optics.py +++ b/webbpsf/optics.py @@ -12,6 +12,7 @@ from scipy.interpolate import griddata, RegularGridInterpolator from scipy.ndimage import rotate +from . import webbpsf_core from . import utils from . import constants @@ -735,7 +736,7 @@ def __init__(self, name="unnamed BLC", kind='nircamcircular', module='A', nd_squ raise NotImplementedError("invalid name for NIRCam occulter: " + self.name) # EDIT: updated on 8 Dec 2021 to grab offsets directly from pySIAF - self.siaf = pysiaf.Siaf('NIRCAM') + self.siaf = webbpsf_core.get_siaf_with_caching('NIRCAM') self.offset_swb = {filt: self.get_bar_offset_from_siaf(filt, channel='SW') for filt in ["F182M", "F187N", "F210M", "F212N", "F200W", 'narrow']} self.offset_lwb = {filt: self.get_bar_offset_from_siaf(filt, channel='LW') diff --git a/webbpsf/webbpsf_core.py b/webbpsf/webbpsf_core.py index 57d3e2fa..47ade809 100644 --- a/webbpsf/webbpsf_core.py +++ b/webbpsf/webbpsf_core.py @@ -22,6 +22,7 @@ import os import glob from collections import namedtuple, OrderedDict +import functools import numpy as np import scipy.interpolate, scipy.ndimage @@ -753,7 +754,7 @@ class JWInstrument(SpaceTelescopeInstrument): def __init__(self, *args, **kwargs): super(JWInstrument, self).__init__(*args, **kwargs) - self.siaf = pysiaf.Siaf(self.name) + self.siaf = get_siaf_with_caching(self.name) opd_path = os.path.join(self._datapath, 'OPD') self.opd_list = [] @@ -2912,6 +2913,13 @@ def calc_or_load_PSF(filename, inst, overwrite=False, **kwargs): ######################### +@functools.lru_cache +def get_siaf_with_caching(instrname): + """ Parsing and loading the SIAF information is particularly time consuming, + (can be >0.1 s per call, so multiple invokations can be a large overhead) + Therefore avoid unnecessarily reloading it by caching results. + This is a small speed optimization. """ + return pysiaf.Siaf(instrname) class DetectorGeometry(object): """ Utility class for converting between detector coordinates