Skip to content

Commit 62e15be

Browse files
authored
Merge pull request #135 from astropy/dev
v2.2 update
2 parents ee57629 + 1a57c93 commit 62e15be

File tree

12 files changed

+2037
-21
lines changed

12 files changed

+2037
-21
lines changed

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
author = 'Matthew Hosek Jr, Jessica R. Lu, Casey Y. Lam'
2626

2727
# The short X.Y version
28-
version = '2.1.15'
28+
version = '2.2'
2929
# The full version, including alpha/beta/rc tags
30-
release = '2.1.15'
30+
release = '2.2'
3131

3232

3333

docs/contributors.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@ Sage Hironaka Remulla -- added Rubin Observatory filters
4040
Lingfeng Wei -- bugfix to improve creation of iso_dir in IsochronePhot
4141

4242
Macy Huston -- New metallicity bound + isochrone filter checks,
43-
imf_mass_lim bugfix, roman filter bugfix
43+
imf_mass_lim bugfix, roman filter bugfix, added Euclid filters, Synthpop compatibility
44+
updates (v2.2)

docs/filters.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Available filters:
3131
* 2MASS
3232
* CTIO_OSIRIS
3333
* DeCam
34+
* Euclid
3435
* GAIA
3536
* HAWK-I
3637
* Hubble Space Telescope
@@ -80,6 +81,14 @@ Filters: u, g, r, i, z, Y
8081

8182
Example: ``'decam,r'``
8283

84+
**Euclid**
85+
86+
`Euclid (NISP) space telescope filters <https://doi.org/10.5270/esa-kx8w57c>`_
87+
88+
Filters: Y, J, H
89+
90+
Example: ``'euclid,Y'``
91+
8392
**GAIA**
8493

8594
The `GAIA Space Telescope filters <https://www.cosmos.esa.int/web/gaia/iow_20180316>`_.

docs/index.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,21 @@ releases will be co-authors in future SPISEA software papers.
8282

8383
Change Log
8484
----------
85+
2.2 (2026-01-16)
86+
* Compatibility updates for SPISEA to work with `SynthPop
87+
<https://synthpop.readthedocs.io/en/latest/>`_. Updates include:
88+
* Low mass objects below the isochrone grid can optionally be kept
89+
in clusters (off by default) and will have
90+
``current_mass=initial_mass`` and ``phase=98``, with no other
91+
evolutionary information or photometry.
92+
* Evolution model versions are now logged in IsochronePhot files
93+
and checked if present.
94+
* The option ``synthpop_extension`` is now available for MISTv1
95+
version=1.2 evolution. This fills in the missing parameter space
96+
down to initial mass 0.1Msun in isochrones where needed. Use of
97+
this option will require downloading updated isochrone files.
98+
* Added support for Euclid filters.
99+
85100
2.1.15 (2025-10-25)
86101
* Updated Roman filter name from outdated w146 to current f146. From
87102
now on a STScI CDBS data version from 2024-03-22 or later is

filt_func/euclid/H.dat

Lines changed: 743 additions & 0 deletions
Large diffs are not rendered by default.

filt_func/euclid/J.dat

Lines changed: 693 additions & 0 deletions
Large diffs are not rendered by default.

filt_func/euclid/Y.dat

Lines changed: 343 additions & 0 deletions
Large diffs are not rendered by default.

spisea/evolution.py

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,17 @@ class StellarEvolution(object):
7979
8080
z_list: list
8181
List of metallicities
82+
83+
model_version_name: string
84+
Name of the model class plus additional details like version
85+
numbers and rotation if relevant.
8286
"""
8387
def __init__(self, model_dir, age_list, mass_list, z_list):
8488
self.model_dir = model_dir
8589
self.z_list = z_list
8690
self.mass_list = mass_list
8791
self.age_list = age_list
92+
self.model_version_name = "None"
8893

8994
return
9095

@@ -93,6 +98,7 @@ def __init__(self):
9398
r"""
9499
Define intrinsic properties for Geneva stellar models.
95100
"""
101+
self.model_version_name = "Geneva"
96102
# populate list of model masses (in solar masses)
97103
mass_list = [(0.1 + i*0.005) for i in range(181)]
98104

@@ -171,6 +177,10 @@ class Ekstrom12(StellarEvolution):
171177
If true, then use rotating Ekstrom models. Default is true.
172178
"""
173179
def __init__(self, rot=True):
180+
if rot:
181+
self.model_version_name = "Ekstrom12-rot"
182+
else:
183+
self.model_version_name = "Ekstrom12-norot"
174184
# define metallicity parameters for Ekstrom+12 models
175185
self.z_list = [0.014]
176186

@@ -401,6 +411,7 @@ def __init__(self):
401411
models.
402412
"""
403413
# populate list of model masses (in solar masses)
414+
self.model_version_name = "Parsec1.2s"
404415
#mass_list = [(0.1 + i*0.005) for i in range(181)]
405416

406417
# define metallicity parameters for Parsec models
@@ -551,6 +562,7 @@ def __init__(self):
551562
Define intrinsic properties for the Pisa (Tognelli+11) stellar
552563
models.
553564
"""
565+
self.model_version_name = "Pisa"
554566
# define metallicity parameters for Pisa models
555567
self.z_list = [0.015]
556568

@@ -710,6 +722,7 @@ class Baraffe15(StellarEvolution):
710722
Downloaded from `BHAC15 site <http://perso.ens-lyon.fr/isabelle.baraffe/BHAC15dir/BHAC15_tracks>`_.
711723
"""
712724
def __init__(self):
725+
self.model_version_name = "Baraffe15"
713726
# define metallicity parameters for Baraffe models
714727
self.z_list = [0.015]
715728

@@ -1008,8 +1021,14 @@ class MISTv1(StellarEvolution):
10081021
was downloaded from MIST website on 2/2017, while Version 1.2
10091022
was downloaded on 8/2018 (solar metallicity)
10101023
and 4/2019 (other metallicities). Default is 1.2.
1024+
1025+
synthpop_extension: boolean (default False)
1026+
If True, the isochrones are extended down to a minimum initial
1027+
mass of 0.1Msun using grids interpolated via SynthPop. If False,
1028+
the web-downloaded MIST isochrones are used with their varying
1029+
lower mass limits. True option is only valid for version=1.2.
10111030
"""
1012-
def __init__(self, version=1.2):
1031+
def __init__(self, version=1.2, synthpop_extension=False):
10131032
# define metallicity parameters for MIST models
10141033
self.z_list = [0.0000014, # [Fe/H] = -4.00
10151034
0.0000045, # [Fe/H] = -3.50
@@ -1032,15 +1051,28 @@ def __init__(self, version=1.2):
10321051

10331052
# Set version directory
10341053
self.version = version
1035-
if self.version == 1.0:
1054+
self.synthpop_extension = synthpop_extension
1055+
if (self.version == 1.0) and (not synthpop_extension):
1056+
self.model_version_name = 'MISTv1.0'
10361057
version_dir = 'v1.0/'
1058+
elif (self.version == 1.0) and synthpop_extension:
1059+
raise ValueError('Synthpop isochrone extension not supported for MISTv1.0 isochrones')
10371060
elif self.version == 1.2:
1061+
self.model_version_name = 'MISTv1.2'
10381062
version_dir = 'v1.2/'
10391063
else:
10401064
raise ValueError('Version {0} not supported for MIST isochrones'.format(version))
10411065

10421066
# Specify location of model files
10431067
self.model_dir = models_dir+'MISTv1/' + version_dir
1068+
if self.synthpop_extension:
1069+
self.model_version_name = self.model_version_name + '-synthpop'
1070+
self.model_extension_dir = models_dir+'MISTv1/' + version_dir[:-1] + '-synthpop/'
1071+
if not os.path.exists(self.model_extension_dir):
1072+
raise ValueError(f'Missing {self.model_extension_dir}. Please download the latest SPISEA data at https://w.astro.berkeley.edu/~jlu/spisea/spisea_models.tar.gz.')
1073+
1074+
else:
1075+
self.model_extension_dir = None
10441076

10451077
# Specifying metallicity
10461078
self.z_solar = 0.0142
@@ -1060,8 +1092,8 @@ def __init__(self, version=1.2):
10601092
0.025: 'z025/',
10611093
0.045: 'z045/'}
10621094

1063-
# Define required evo_grid number
1064-
self.evo_grid_min = 1.1
1095+
# Define required evo_grid number (now 1.2 for synthpop extension)
1096+
self.evo_grid_min = 1.2
10651097

10661098
def isochrone(self, age=1.e8, metallicity=0.0):
10671099
r"""
@@ -1096,10 +1128,18 @@ def isochrone(self, age=1.e8, metallicity=0.0):
10961128

10971129
# generate isochrone file string
10981130
full_iso_file = self.model_dir + 'iso/' + z_dir + iso_file
1131+
if self.synthpop_extension:
1132+
addl_iso_file = self.model_extension_dir + 'iso/' + z_dir + iso_file
10991133

11001134
# return isochrone data. Column locations depend on
11011135
# version
11021136
iso = Table.read(full_iso_file, format='fits')
1137+
if self.synthpop_extension:
1138+
addl_iso = Table.read(addl_iso_file, format='fits')
1139+
for row in addl_iso:
1140+
iso.add_row(row)
1141+
iso.sort('col3')
1142+
iso.meta['comments2'] = addl_iso.meta['comments']
11031143
if self.version == 1.0:
11041144
iso.rename_column('col7', 'Z')
11051145
iso.rename_column('col2', 'logAge')
@@ -1232,6 +1272,10 @@ class MergedBaraffePisaEkstromParsec(StellarEvolution):
12321272
If true, then use rotating Ekstrom models. Default is true.
12331273
"""
12341274
def __init__(self, rot=True):
1275+
if rot:
1276+
self.model_version_name = "MergedBaraffePisaEkstromParsec-rot"
1277+
else:
1278+
self.model_version_name = "MergedBaraffePisaEkstromParsec-norot"
12351279
# populate list of model masses (in solar masses)
12361280
mass_list = [(0.1 + i*0.005) for i in range(181)]
12371281

@@ -1283,6 +1327,7 @@ def isochrone(self, age=1.e8, metallicity=0.0):
12831327
age_idx = np.where(abs(np.array(self.age_list) - log_age) == min(abs(np.array(self.age_list) - log_age)) )[0][0]
12841328
iso_file = 'iso_{0:.2f}.fits'.format(self.age_list[age_idx])
12851329

1330+
12861331
# find closest metallicity value
12871332
z_idx = np.where(abs(np.array(self.z_list) - z_defined) == min(abs(np.array(self.z_list) - z_defined)) )[0][0]
12881333
z_dir = self.z_file_map[self.z_list[z_idx]]
@@ -1291,7 +1336,16 @@ def isochrone(self, age=1.e8, metallicity=0.0):
12911336
full_iso_file = self.model_dir + z_dir + iso_file
12921337

12931338
# return isochrone data
1294-
iso = Table.read(full_iso_file, format='fits')
1339+
try:
1340+
# FITS version of file (older model evolution grids)
1341+
iso = Table.read(full_iso_file, format='fits')
1342+
except:
1343+
# ASCII version of files (newer model evo grids
1344+
iso_file = 'iso_{0:.2f}.dat'.format(self.age_list[age_idx])
1345+
full_iso_file = self.model_dir + z_dir + iso_file
1346+
1347+
iso = Table.read(full_iso_file, format='ascii')
1348+
12951349
iso.rename_column('col1', 'mass')
12961350
iso.rename_column('col2', 'logT')
12971351
iso.rename_column('col3', 'logL')
@@ -1325,6 +1379,10 @@ class MergedPisaEkstromParsec(StellarEvolution):
13251379
If true, then use rotating Ekstrom models. Default is true.
13261380
"""
13271381
def __init__(self, rot=True):
1382+
if rot:
1383+
self.model_version_name = "MergedPisaEkstromParsec-rot"
1384+
else:
1385+
self.model_version_name = "MergedPisaEkstromParsec-norot"
13281386
# populate list of model masses (in solar masses)
13291387
mass_list = [(0.1 + i*0.005) for i in range(181)]
13301388

@@ -1422,6 +1480,7 @@ def __init__(self):
14221480
Define intrinsic properties for merged Siess-meynetMaeder-Padova
14231481
stellar models.
14241482
"""
1483+
self.model_version_name = "MergedSiessGenevaPadova"
14251484
# populate list of model masses (in solar masses)
14261485
mass_list = [(0.1 + i*0.005) for i in range(181)]
14271486

spisea/filters.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,7 @@ def get_rubin_filt(name):
437437
try:
438438
t = Table.read('{0}/rubin/{1}.dat'.format(filters_dir, name), format='ascii')
439439
except:
440-
raise ValueError('Could not find Rubin LSST filter file {0}/total_/{1}.dat'.format(filters_dir, name))
440+
raise ValueError('Could not find Rubin LSST filter file {0}/rubin/{1}.dat'.format(filters_dir, name))
441441

442442
wavelength = t[t.keys()[0]]
443443
transmission = t[t.keys()[1]]
@@ -450,3 +450,25 @@ def get_rubin_filt(name):
450450
name='rubin_{0}'.format(name))
451451

452452
return spectrum
453+
454+
def get_euclid_filt(name):
455+
"""
456+
Define the Euclid filters as a pysynphot spectrum object
457+
"""
458+
# Read in filter info
459+
try:
460+
t = Table.read('{0}/euclid/{1}.dat'.format(filters_dir, name), format='ascii')
461+
except:
462+
raise ValueError('Could not find Euclid filter file {0}/euclid/{1}.dat'.format(filters_dir, name))
463+
464+
wavelength = t[t.keys()[0]]
465+
transmission = t[t.keys()[1]]
466+
467+
# Convert wavelength to Angstroms
468+
wavelength = wavelength * 10
469+
470+
# Make spectrum object
471+
spectrum = pysynphot.ArrayBandpass(wavelength, transmission, waveunits='angstrom',
472+
name='euclid_{0}'.format(name))
473+
474+
return spectrum

0 commit comments

Comments
 (0)