diff --git a/.github/workflows/ci_workflows.yml b/.github/workflows/ci_workflows.yml index 46c806c..3c2451b 100644 --- a/.github/workflows/ci_workflows.yml +++ b/.github/workflows/ci_workflows.yml @@ -14,27 +14,28 @@ jobs: matrix: include: - - name: Python 3.8 + - name: Python 3.10 os: ubuntu-latest - python: 3.8 + python: "3.10" - - name: Python 3.9 + - name: Python 3.11 os: ubuntu-latest - python: 3.9 + python: 3.11 - - name: Python 3.9 Mac + - name: Python 3.11 Mac os: macos-latest - python: 3.9 + python: 3.11 - name: Python Long os: ubuntu-latest - python: 3.9 + python: 3.11 steps: - name: Checkout code uses: actions/checkout@v2 with: fetch-depth: 0 + - name: Set up environment uses: conda-incubator/setup-miniconda@v2 with: @@ -42,11 +43,14 @@ jobs: environment-file: environment.yml python-version: ${{ matrix.python }} auto-activate-base: false + miniconda-version: "latest" # Ensure Miniconda is installed if not found + - name: Test with tox shell: bash -l {0} if: ${{ matrix.name != 'Python Long' }} run: | tox -e test + - name: Test slow tests with pytest shell: bash -l {0} if: ${{ matrix.name == 'Python Long' }} @@ -57,17 +61,20 @@ jobs: name: "docs_test" runs-on: ubuntu-latest steps: + - name: Checkout code uses: actions/checkout@v2 with: fetch-depth: 0 + - name: Set up environment uses: conda-incubator/setup-miniconda@v2 with: activate-environment: stips environment-file: environment.yml - python-version: 3.9 + python-version: 3.11 auto-activate-base: false + - name: Build Docs shell: bash -l {0} run: | diff --git a/CHANGES.rst b/CHANGES.rst index 2561a1f..b107841 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,14 @@ Release Notes Version History and Change Log ------------------------------ +Version 2.2.0 +============= +- Added a functionality to allow for faster simulations of extended sources. +- Fixed a bug related to the simulation of extended sources. +- Fixed a bug related to the WCS. +- Updated pandeia to version 3.1 and its corresponding reference files. +- Changed the minimum required Python version to 3.10 + Version 2.1.0 ============= - Updated the Flux PHOTFNU values to match Pandeia diff --git a/docs/basic_tutorial.rst b/docs/basic_tutorial.rst index 1725fd4..10d6248 100644 --- a/docs/basic_tutorial.rst +++ b/docs/basic_tutorial.rst @@ -173,7 +173,7 @@ We will use a single offset with: * No centering (if an offset is centered, then, for a multi-detector observation, each detector is centered on the offset co-coordinates individually rather than the instrument - as a whole beinf centered there) + as a whole being centered there) * No change in RA, DEC, or PA from the center of the observation @@ -237,7 +237,7 @@ Observing the Created Scene In order to observe the scene, we must add the scene catalogues created above to it, add in error residuals, and finalize the observation. In so doing, we create output catalogues which are taken from the input catalogues, but only contain the sources visible to the -detectors, and convert source brightness into unites of counts/s for the detectors. +detectors, and convert source brightness into units of counts/s for the detectors. .. code-block:: python @@ -267,16 +267,15 @@ We use ``matplotlib`` to plot the resulting simulated image. .. code-block:: python import matplotlib - from matplotlib import style + import matplotlib.pyplot as plt + from astropy.io import fits matplotlib.rcParams['axes.grid'] = False matplotlib.rcParams['image.origin'] = 'lower' - import matplotlib.pyplot as plot - from astropy.io import fits with fits.open(fits_file) as result_file: result_data = result_file[1].data - fig1 = plot.figure() - im = plot.matshow(result_data) + fig1 = plt.figure() + im = plt.matshow(result_data) Alternatively, you can open the final ``.fits`` file in your preferred imaging software. diff --git a/docs/examples.rst b/docs/examples.rst index b022356..b1a2586 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -65,5 +65,38 @@ scene with the Roman WFI F129 filter offset by 0.5 degrees in RA and rotated by fits_file, mosaic_file, params = obm.finalize(mosaic=False) -In this case, the output catalog(s) will show the actual applied count rates. Whether there -is only one output catalog or two depends on the input catalog format. +In this case, the output catalog(s) will show the actual applied count rates. +Whether there is only one output catalog or two depends on the input catalog format. + + +Fast Extended Sources +---------------------- + +As of version 2.2, STIPS includes an option to inject extended sources in scenes +using a Sersic-profile approximation. This approximation is ~8 times faster than +the current implementation, but it is also less accurate. + +To activate this feature, users must turn on the ``fast_galaxy`` flag. This is how the syntax +looks, starting from the examples listed in the :doc:`STIPS Basic Tutorial `. + +.. code-block:: python + + observation_parameters = { + 'instrument': 'WFI', + 'filters': ['F129'], + 'detectors': 1, + 'distortion': False, + 'background': 0.15, + 'fast_galaxy': True, + 'observations_id': 1, + 'exptime': 1000, + 'offsets': [offset] + } + +.. note:: + + We caution however that while this method is a useful approximation, the resulting + integrated flux measurements can be off by a factor of ~2. Furthermore, the central + pixel at the core of the galaxy should not be trusted, since this can be off by + multiple orders of magnitude. + diff --git a/docs/index.rst b/docs/index.rst index 276556c..1bef558 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,37 +3,36 @@ Documentation .. note:: - STIPS 2.0 no longer supports HST or JWST. STIPS 1.0.8 is the most recent version to - offer support for those telescopes and instruments. + As of version 2.0, STIPS no longer offers support for HST or JWST. Overview -------- -STIPS is the Space Telescope Imaging Product Simulator. It is designed to create -simulations of full-detector post-pipeline astronomical scenes for the Nancy Grace Roman -Space Telescope's Wide-Field Instrument (WFI). STIPS has the ability to add +STIPS is the Space Telescope Imaging Product Simulator. It is designed to create +simulations of full-detector post-pipeline astronomical scenes for the Nancy Grace Roman +Space Telescope's Wide-Field Instrument (WFI). STIPS has the ability to add instrumental distortion (if available) as well as calibration residuals from flatfields, dark currents, and cosmic rays. It automatically includes Poisson noise and readout noise. It does not include instrument saturation effects. Why use STIPS? -------------- -STIPS is intended to produce quick simulations of Level 2 (L2) images, and is provided for +STIPS is intended to produce quick simulations of Level 2 (L2) images, and is provided for cases where `Pandeia `_ does not provide a large enough simulation area (e.g., full-detector or multiple-detector observations). STIPS obtains its Roman instrument and filter values from Pandeia, so it should produce output within 10% of output produced by Pandeia. -STIPS does not start with Level 1 (L1) images and propagate instrumental calibrations +STIPS does not start with Level 1 (L1) images and propagate instrumental calibrations through the simulations. While it does have the ability to add error residuals (representing -the remaining uncertainty after pipeline calibration), these residuals are not validated -against actual pipeline calibrations of L1 images. STIPS is not the ideal choice if -extremely good instrumental accuracy is needed. Pandeia is the preferred tool for +the remaining uncertainty after pipeline calibration), these residuals are not validated +against actual pipeline calibrations of L1 images. STIPS is not the ideal choice if +extremely good instrumental accuracy is needed. Pandeia is the preferred tool for high-accuracy observations. Developed by Brian York (`@york-stsci `_), -Robel Geda (`@robelgeda `_), -and O. Justin Otor (`@ojustino `_). -Python ePSF code developed by +Robel Geda (`@robelgeda `_), +and O. Justin Otor (`@ojustino `_). +Python ePSF code developed by Sebastian Gomez (`@gmzsebastian `_) based on Fortran code developed by Andrea Bellini (`@AndreaBellini `_). diff --git a/docs/installation.rst b/docs/installation.rst index 33f82ba..07c4d65 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -9,7 +9,7 @@ in this section along with instructions. STIPS Requirements ################## -* ``pandeia>=3.0``: Exposure time calculator. +* ``pandeia>=3.1``: Exposure time calculator. * ``webbpsf==1.1.1``: Nancy Grace Roman PSF calculator. STIPS also requires that ``poppy``, a support package used by WebbPSF, have version ``>=1.0.3``. @@ -80,9 +80,9 @@ Installing as a User conda activate stips - * Or, to install to or update an existing and currently active Conda environment:: + * Or, to install to or update an existing Conda environment:: - conda env update --file environment.yml + conda env update --name EXISTING-ENV --file environment.yml Installing as a Developer ************************* @@ -126,8 +126,8 @@ Testing Installation To test if all the required files have been installed, please import STIPS in Python:: bash-3.2$ python - Python 3.7.3 | packaged by conda-forge | (default, Dec 6 2019, 08:36:57) - [Clang 9.0.0 (tags/RELEASE_900/final)] :: Anaconda, Inc. on darwin + Python 3.11.9 | packaged by conda-forge | (main, Apr 19 2024, 18:45:13) + [Clang 16.0.6 ] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import stips diff --git a/docs/using_stips/psf_grid.rst b/docs/using_stips/psf_grid.rst index 448c567..7bbf076 100644 --- a/docs/using_stips/psf_grid.rst +++ b/docs/using_stips/psf_grid.rst @@ -4,24 +4,24 @@ The STIPS PSF Grid Overview -------- -Starting with STIPS 2.0.0, STIPS uses WebbPSF PSF grids to implement an ePSF. The ePSF -uses a 3x3 grid of PSFs to handle PSF variation across the detector, and an oversample of +As of version 2.0.0, STIPS uses WebbPSF PSF grids to implement an ePSF. The ePSF +uses a 3x3 grid of PSFs to handle PSF variation across the detector, and an oversample of 4x4 to handle sub-pixel positioning. Each point source has its PSF calculated individually as it is added to the detector. Internal Image Size ------------------- -The size of the STIPS pre-convolution image is set by the size of the detector. In -addition, the image is padded by half of the PSF size on each side in order to include +The size of the STIPS pre-convolution image is set by the size of the detector. In +addition, the image is padded by half of the PSF size on each side in order to include sources that fall off the detector, but whose PSF may land on the detector. PSF Image Size -------------- -The size of the STIPS generated PSF image depends on the source brightness. For most -sources, a 45x45-pixel PSF is created via an ePSF oversampled to a factor of 4. For bright -sources (magnitude < the bright limit, default 14), a 91x91-pixel PSF is created to -provide flux from the extended wings. For extra-bright sources -(magnitude < the extra-bright limit, default 3), a 181x181-pixel PSF is created to provide +The size of the STIPS generated PSF image depends on the source brightness. For most +sources, a 45x45-pixel PSF is created via an ePSF oversampled to a factor of 4. For bright +sources (magnitude < the bright limit, default 14), a 91x91-pixel PSF is created to +provide flux from the extended wings. For extra-bright sources +(magnitude < the extra-bright limit, default 3), a 181x181-pixel PSF is created to provide even more wing flux to the model. diff --git a/environment.yml b/environment.yml index 216ea1a..35558f8 100644 --- a/environment.yml +++ b/environment.yml @@ -1,4 +1,4 @@ -# This file describes a conda environment that can be to install STIPS +# This file describes a conda environment that can be used to install STIPS # # Run the following command to set up this environment: # $ conda env create -f environment.yml @@ -25,7 +25,7 @@ channels: dependencies: # Base dependencies - pip - - python>=3.8 + - python>=3.10 - jupyter - Cython - esutil # installed from conda because you need the pre-compiled binaries. @@ -36,7 +36,7 @@ dependencies: # Core Modules - webbpsf==1.1.1 - - pandeia.engine==3.0 + - pandeia.engine==3.1 - synphot==1.1.1 - stsynphot==1.1.0 - soc_roman_tools diff --git a/environment_dev.yml b/environment_dev.yml index 809f8a2..5e94022 100644 --- a/environment_dev.yml +++ b/environment_dev.yml @@ -1,5 +1,5 @@ -# This file describes a conda environment that can be to install STIPS for development and -# testing purposes. Note that this environment set-up installs the STIPS module in +# This file describes a conda environment that can be used to install STIPS for development and +# testing purposes. Note that this environment setup installs the STIPS module in # editable mode, so any changes you make to the STIPS source will be reflected the next # time you run python. # @@ -28,7 +28,7 @@ channels: dependencies: # Base dependencies - pip - - python>=3.8 + - python>=3.10 - jupyter - Cython - esutil # installed from conda because you need the pre-compiled binaries. @@ -45,7 +45,7 @@ dependencies: # Core Modules - webbpsf==1.1.1 - - pandeia.engine==3.0 + - pandeia.engine==3.1 - synphot==1.1.1 - stsynphot==1.1.0 - soc_roman_tools diff --git a/setup.cfg b/setup.cfg index 5ea99b0..5688f7e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,7 @@ [metadata] name = stips # version should be PEP440 compatible (https://www.python.org/dev/peps/pep-0440/) -version = 2.1.0 +version = 2.2.0 author = Space Telescope Science Institute author_email = york@stsci.edu description = STIPS is the Space Telescope Imaging Product Simulator. @@ -24,7 +24,7 @@ install_requires = synphot==1.1.1 stsynphot==1.1.0 webbpsf==1.1.1 - pandeia.engine==3.0 + pandeia.engine==3.1 montage-wrapper pyyaml soc_roman_tools diff --git a/stips/astro_image/astro_image.py b/stips/astro_image/astro_image.py index db48bd8..e0c836c 100755 --- a/stips/astro_image/astro_image.py +++ b/stips/astro_image/astro_image.py @@ -65,6 +65,8 @@ def __init__(self, **kwargs): self.out_path = self.parent.out_path self.prefix = self.parent.prefix self.seed = self.parent.seed + self.fast_galaxy = self.parent.fast_galaxy + self.convolve_galaxy = self.parent.convolve_galaxy self.telescope = self.parent.TELESCOPE.lower() self.instrument = self.parent.PSF_INSTRUMENT self.filter = self.parent.filter @@ -93,6 +95,8 @@ def __init__(self, **kwargs): self.out_path = SelectParameter('out_path', kwargs) self.bright_limit = SelectParameter('psf_bright_limit', kwargs) self.xbright_limit = SelectParameter('psf_xbright_limit', kwargs) + self.fast_galaxy = SelectParameter('fast_galaxy', kwargs) + self.convolve_galaxy = SelectParameter('convolve_galaxy', kwargs) self.shape = kwargs.get('shape', default['shape']) self._scale = kwargs.get('scale', np.array(default['scale'])) self.prefix = kwargs.get('prefix', '') @@ -354,7 +358,7 @@ def imageHdu(self): hdu.header['CDELT2'] = self.scale[0]/3600. # Apparently astropy refuses to add the identity matrix to a header if ('PA1_1' not in hdu.header) and ('CD1_1' not in hdu.header): - hdu.header['CD1_1'] = -self.scale[0]/3600. + hdu.header['CD1_1'] = self.scale[0]/3600. hdu.header['CD1_2'] = 0. hdu.header['CD2_1'] = 0. hdu.header['CD2_2'] = self.scale[0]/3600. @@ -391,7 +395,7 @@ def addHistory(self, v): """Adds an entry to the header history list.""" self.history.append(v) - def addTable(self, t, dist=False, *args, **kwargs): + def addTable(self, t, dist=False, fast_galaxy=False, convolve_galaxy=True, *args, **kwargs): """ Add a catalogue table to the Image. The Table must have the following columns: RA: RA of source @@ -460,7 +464,10 @@ def addTable(self, t, dist=False, *args, **kwargs): for (x, y, flux, n, re, phi, ratio, id) in zip(gxs, gys, gfluxes, gns, gres, gphis, gratios, gids): item_index = np.where(ids == id)[0][0] self._log("info", "Index is {}".format(item_index)) - central_flux = self.addSersicProfile(x, y, flux, n, re, phi, ratio, *args, **kwargs) + if fast_galaxy: + central_flux = self.oldSersicProfile(x, y, flux, n, re, phi, ratio, convolve_galaxy, *args, **kwargs) + else: + central_flux = self.addSersicProfile(x, y, flux, n, re, phi, ratio, *args, **kwargs) fluxes_observed[item_index] = central_flux notes[item_index] = "{}: surface brightness {:.3f} yielded flux {:.3f}".format(notes[item_index], flux, central_flux) self._log("info", "Finished Galaxy {} of {}".format(counter, total)) @@ -510,7 +517,7 @@ def addCatalogue(self, cat, dist=False, *args, **kwargs): current_chunk = in_data.read_chunk() while current_chunk is not None: table_length = len(current_chunk['id']) - out_chunk = self.addTable(current_chunk, dist, *args, **kwargs) + out_chunk = self.addTable(current_chunk, dist, fast_galaxy = self.fast_galaxy, *args, **kwargs) if out_chunk is not None: out_data.write_chunk(out_chunk) counter += table_length @@ -716,50 +723,31 @@ def cropToBaseSize(self): self.shape = self.base_shape self.has_psf = False - def addSersicProfile(self, posX, posY, flux, n, re, phi, axialRatio, *args, **kwargs): + def addSersicProfile(self, posX, posY, flux, n, re, phi, axialRatio, + *args, **kwargs): """ - Creates a simulated Sersic profile, including PSF convolution, using pandeia's - SersicDistribution. + Create a simulated Sersic profile, including PSF convolution, using + Pandeia's SersicDistribution. Parameters ---------- - id: int - The source ID of the sersic profile - gal_params: dict - A dictionary containing the galaxy parameters. These parameters are: - x, y: float - The position of the profile centre on the detector - flux: float - The surface brightness (in counts/s/pixel) at the half-light radius - n: float - The Sersic index. This must be between 0.3 and 6.2. - re: float - The half-light radius, in pixels. - phi: float - The position angle of the major axis, in degrees east of north - ratio: float - The ratio between the major and minor axes - psf_params: dict - A dictionary containing the PSF parameters. These parameters are: - - psf_file: string - The name and location of the PSF file - xsize, ysize: int - The size of the detector - dir: string - The working directory to write model arrays to. - overrides: dict - Holds a copy of the AstroImage dictionary used to provide runtime parameter - setting. - logger: logging.logger - Logger to use for logging messages. + posX: float + The X position of the profile center on the detector. + posX: float + The Y position of the profile center on the detector. + flux: float + The surface brightness (in counts/s/pixel) at the half-light radius. + n: float + The Sersic index. This must be between 0.3 and 6.2. + re: float + The half-light radius, in pixels. + phi: float + The position angle of the major axis, in degrees east of north. + axialRatio: float + The ratio between the major and minor axes. Returns ------- - fname: string - The name of the file in which the output numpy array was saved. - x,y: int - The position on the detector of the model centre central_flux: float The flux at the central pixel of the model """ @@ -773,19 +761,19 @@ def addSersicProfile(self, posX, posY, flux, n, re, phi, axialRatio, *args, **kw source_dict['shape'] = {'geometry': 'sersic'} source_dict['shape']['major'] = re source_dict['shape']['minor'] = re*axialRatio - source_dict['sersic_index'] = n + source_dict['shape']['sersic_index'] = n source_dict['spectrum'] = {'redshift': 0., 'sed': {'sed_type': 'flat'}} source_dict['normalization'] = {'type': 'none'} source_dict['position'] = {'orientation': 90-phi} - source_dict['position']['x_offset'] = self.xsize - posX - source_dict['position']['y_offset'] = self.ysize - posY + source_dict['position']['x_offset'] = posX - self.xsize / 2 + source_dict['position']['y_offset'] = self.ysize / 2 - posY g = coords.Grid(1., 1., self.xsize, self.ysize) xc, yc = ix, iy # Roman is the only telescope supported src = source.Source('roman', config=source_dict) src.grid = g - sersic = profile.SersicDistribution(src) + sersic = profile.SersicDistribution(src, 1) img = deepcopy(sersic.prof)*flux/np.sum(sersic.prof) central_flux = img[yc, xc] @@ -796,11 +784,68 @@ def addSersicProfile(self, posX, posY, flux, n, re, phi, axialRatio, *args, **kw psf_data = np.zeros((boxsize, boxsize), dtype=np.float32) psf_x, psf_y = rind(boxsize/2), rind(boxsize/2) psf_data = place_source(psf_x, psf_y, 1., psf_data, epsf, boxsize=boxsize, psf_center=psf_middle) - result = convolve_fft(img, psf_data) self.data += result return central_flux + + def oldSersicProfile(self, posX, posY, flux, n, re, phi, axialRatio, + convolve_galaxy, *args, **kwargs): + """ + Create a simulated Sersic profile, including PSF convolution, using + the old (and faster) Astropy Sersic2D model. + + Parameters + ---------- + posX: float + The X position of the profile center on the detector. + posX: float + The Y position of the profile center on the detector. + flux: float + The surface brightness (in counts/s/pixel) at the half-light radius. + n: float + The Sersic index. This must be between 0.3 and 6.2. + re: float + The half-light radius, in pixels. + phi: float + The position angle of the major axis, in degrees east of north. + axialRatio: float + The ratio between the major and minor axes. + convolve_galaxy : bool + Whether to convolve the final image with the Roman PSF. + [default: True] + + Returns + ------- + central_flux: float + The flux at the central pixel of the model + """ + if flux == 0.: + return 0. + + # Generate 2D Sersic profile + from astropy.modeling.models import Sersic2D + x, y = np.meshgrid(np.arange(self.xsize), np.arange(self.ysize)) + mod = Sersic2D(amplitude=flux, r_eff=re, n=n, x_0=posX, y_0=posY, ellip=(1.-axialRatio), theta=(np.radians(phi) + 0.5*np.pi)) + img = mod(x, y) + + # Convolve with Roman PSF + if convolve_galaxy: + psf_array, psf_middle = self.make_epsf_array() + boxsize = rind(np.floor(psf_middle)/PSF_UPSCALE) + epsf = interpolate_epsf(posX, posY, psf_array, self.shape[0]) + psf_data = np.zeros((boxsize, boxsize), dtype=np.float32) + psf_x, psf_y = rind(boxsize/2), rind(boxsize/2) + psf_data = place_source(psf_x, psf_y, 1., psf_data, epsf, boxsize=boxsize, psf_center=psf_middle) + result = convolve_fft(img, psf_data) + self.data += result + else: + self.data += img + + # Calculate central flux + central_flux = mod(posX, posY) + return central_flux + def rotate(self, angle, reshape=False): """ Rotate the image a number of degrees as specified diff --git a/stips/instruments/instrument.py b/stips/instruments/instrument.py index 3641499..6a844a1 100755 --- a/stips/instruments/instrument.py +++ b/stips/instruments/instrument.py @@ -66,6 +66,8 @@ def __init__(self, **kwargs): self.exptime = kwargs.get('exptime', 1.) self.bright_limit = kwargs.get('bright_limit', kwargs) self.xbright_limit = kwargs.get('xbright_limit', kwargs) + self.fast_galaxy = kwargs.get('fast_galaxy', kwargs) + self.convolve_galaxy = kwargs.get('convolve_galaxy', kwargs) self.filter = None self.detectors = None self.instrument = kwargs.get('instrument', 'wfi') diff --git a/stips/observation_module/observation_module.py b/stips/observation_module/observation_module.py index 5a013f6..550cb3f 100755 --- a/stips/observation_module/observation_module.py +++ b/stips/observation_module/observation_module.py @@ -62,6 +62,8 @@ def __init__(self, obs, **kwargs): self.detectors = int(obs.get('detectors', 1)) self.excludes = obs.get('excludes', []) self.exptime = float(obs.get('exptime', 1.)) + self.fast_galaxy = obs.get('fast_galaxy', False) + self.convolve_galaxy = obs.get('convolve_galaxy', True) self.bright_limit = obs.get('bright_limit', 14.) self.xbright_limit = obs.get('xbright_limit', 3.) if len(self.filters) == 0 and 'filter' in obs: diff --git a/stips/utilities/utilities.py b/stips/utilities/utilities.py index 523d785..0ad44dc 100755 --- a/stips/utilities/utilities.py +++ b/stips/utilities/utilities.py @@ -338,14 +338,14 @@ def DownloadReferenceData(): # pandeia print("Checking pandeia data") - pandeia_data_file = "pandeia_data-3.0.tar.gz" - pandeia_url = "https://stsci.box.com/shared/static/3n9e05mxkjzquxaq1gl6nqp6l0ksz5c2.gz" + pandeia_data_file = "pandeia_data-3.1_roman.tar.gz" + pandeia_url = "https://stsci.box.com/shared/static/cmljh0lsffz4345064eso7lix70f9477.gz" pandeia_data_path = os.environ[GetParameter("pandeia_data_name", use_data=False)] if not os.path.isdir(pandeia_data_path): print("Downloading pandeia data to {}".format(pandeia_data_path)) os.makedirs(pandeia_data_path) get_compressed_file(pandeia_url, pandeia_data_file, pandeia_data_path, - "pandeia_data-3.0_roman_rc3/") + "pandeia_data-3.1_roman/") else: print("Found at {}".format(pandeia_data_path))