dfm / python-fsps

Python bindings to Charlie Conroy's Flexible Stellar Population Synthesis (FSPS) Fortran code
https://python-fsps.readthedocs.io
MIT License
67 stars 38 forks source link

Inconsistent mags using get_mags() default (tage=0.0) vs. non-zero tage #68

Closed rrgupta closed 3 years ago

rrgupta commented 8 years ago

This is related to Issue #4 but a separate problem, I think. When I run get_mags() without any tage option it gives me an array of mags at each isochrone age, as expected. But I'm finding that when I specify a nonzero tage in get_mags() I get a set of mags returned that are inconsistent with the default tage=0.0 output for that given age.

Here's an example using the MIST library:

>>> import fsps
>>> import numpy as np
>>> from astropy.table import Table
>>> sp = fsps.StellarPopulation(sfh=4, tau=5.5, zmet=10, sf_start=1.2)
>>> t = Table(sp.get_mags(bands=['sdss_r']), names=['sdss_r'])
>>> t['logAge'] = sp.ssp_ages
>>> t['Age'] = np.power(10, t['logAge']-9.)
>>> print t
    sdss_r    logAge        Age       
------------- ------ -----------------
142.634235255    5.0            0.0001
142.634235255   5.05  0.00011220184543
142.634235255    5.1 0.000125892541179
142.634235255   5.15 0.000141253754462
142.634235255    5.2 0.000158489319246
142.634235255   5.25 0.000177827941004
142.634235255    5.3 0.000199526231497
142.634235255   5.35 0.000223872113857
142.634235255    5.4 0.000251188643151
142.634235255   5.45 0.000281838293126
142.634235255    5.5 0.000316227766017
142.634235255   5.55 0.000354813389234
142.634235255    5.6 0.000398107170553
142.634235255   5.65 0.000446683592151
142.634235255    5.7 0.000501187233627
142.634235255   5.75  0.00056234132519
          ...    ...               ...
6.31373519347   9.55     3.54813389234
6.14171523938    9.6     3.98107170553
5.99198782259   9.65     4.46683592151
5.86297949488    9.7     5.01187233627
5.75375976228   9.75      5.6234132519
5.66396496904    9.8      6.3095734448
5.59361712903   9.85     7.07945784384
 5.5430831926    9.9     7.94328234724
5.51296640503   9.95     8.91250938134
  5.504291255   10.0              10.0
5.51808303428  10.05      11.220184543
5.55538642226   10.1     12.5892541179
5.61704470988  10.15     14.1253754462
5.70352203524   10.2     15.8489319246
5.81433320474  10.25     17.7827941004
5.94943981657   10.3     19.9526231497
Length = 107 rows
>>> t10 = sp.get_mags(bands=['sdss_r'], tage=10.)
 COMPSP WARNING: sf_trunc<sf_start.... sf_trunc will be ignored.
>>> print t10
[ 4.86723385]

You can see that at an age of 10 Gyr, the mags are not the same (4.86723385 for tage=10. and 5.504291255 for tage=0.0). Am I misunderstanding how the tage option for get_mags() works?

bd-j commented 8 years ago

when tage !=0 the normalization is such that one solar mass formed from t=0 to tage. When tage=0 the normalization is such that one solar mass formed from t=0 to the oldest isochrone.

The compsp warning should not be coming up though.

rrgupta commented 8 years ago

Got it, thanks.

Yeah, I wasn't worried about the COMPSP warning since I figured it was just because sf_trunc=0.0 by default and so for any value of sf_start >0, it will give that warning.

FYI, the python-fsps doc string says sf_trunc and sf_slope are undocumented, but it looks like the most recent version of the FSPS MANUAL.pdf has definitions documented in there.

Feel free to close this issue whenever. Thanks again!

rrgupta commented 8 years ago

If tage != 0 and the normalization of get_mags() is such that 1 solar mass is formed from t=0 to tage, does that imply that the mass-to-light ratio in some band (call it X) for that model is 1.0/(10**(-0.4*model_mag_X))? And if I am using redshift_colors=True can I estimate the mass of my observed galaxy by simply multiplying the best-fit model SED M/L by 10**(-0.4*obs_mag_X)? According to Sec. 1.5 of Charlie's MANUAL.pdf (Redshift Effects), "returned magnitudes include both the relevant (1 + z) factors and the distance modulus" and so is it true that I don't need to correct my observed mags for distance modulus? If I do this, the masses I get are way too low, probably because the model mags I'm getting from get_mags() seem so bright (~ 10 mag) for 1 solar mass of material at an intermediate redshift. I must be missing something. How do you properly estimate masses from the outputs of get_mags(tage != 0)? Thanks.

bd-j commented 8 years ago

does that imply that the mass-to-light ratio in some band (call it X) for that model is 1.0/(10*_(-0.4_model_mag_X))?

Not quite. You can access the stellar masses (including stellar remnants if add_stellar_remnants==True) with the sp.stellar_mass attribute. This returns the actual surviving stellar mass for the current parameter set. The 1 solar mass is for the solar mass formed (of which some is returned to the ISM through stellar evolution.)

The interaction of get_mags() with zred, redshift, and redshift_colors is a little complicated and not ideal. Also redshift_colors looks from the source like it might be broken in FSPS for tage != 0. I think what you want is something like

sp.params['zred'] = 0
sp.params['redshift_colors'] = False
model_mag_x = sp.get_mags(redshift=z, tage=t, bands=[x])
total_mass = sp.stellar_mass * 10**(0.4 * (model_mag_x - obs_mag_x))

In this case you have to do your own conversions between age and redshift (e.g. using astropy.cosmology)

If you use zred instead and then set redshift=0 in the call to get_mags you will get apparent model magnitudes that are too small by mu - 2.5log(1+zred)

Let me know if the above gives sensible results, and thanks for all this feedback and testing!

rrgupta commented 8 years ago

Ah...I think I see. So in get_mags() the redshift and tage keywords are completely decoupled. I want to output the observed mags of a model galaxy as it evolves over cosmic time (in small redshift bins) for the purposes of SED fitting to observed mags. If I understand what you're saying, I should first compute a t(z) relation (using astropy.cosmology and assuming my favorite cosmology) and obtain the model mags by calling get_mags() and inserting these t and z values as in your example, while looping over cosmic time, under the condition that each call to get_mags() contains a pair of (z, t) that satisfy my t(z) relation:

model_mag_x = sp.get_mags(redshift=z, tage=t, bands=[x])

Is that correct?

Regarding your calculation of mass:

total_mass = sp.stellar_mass * 10**(0.4 * (model_mag_x - obs_mag_x))

my obs_mag_x should simply be my observed mags from my telescope, corrected for MW extinction but no need for k-corrections or distance modulus, right? And to be clear, the units of sp.stellar_mass are M_sun, not log10(M_sun)? Thanks (and sorry for all the naïve questions)!

bd-j commented 8 years ago

yes, that all sounds good.

Ideally setting redshift_colors=True would couple redshift and tage in get_mags but we don't yet have the necessary checks and the code in FSPS itself looks broken for the tage !=0 case. Fixing this up is on the list for the next code sprint.

rrgupta commented 8 years ago

Yeah, the last time I used FSPS was a few years back (v2.1) and at the time I was using redshift_colors=1 (True) which is why I was trying to do the same here in python-fsps. However, your solution above seems to give reasonable results that are in pretty good agreement to the masses I had computed years ago with FSPS v2.1.

bd-j commented 8 years ago

In PR #73 we added a new attribute, formed_mass that for tage =0 will allow you to work out the normalization compared to the tage=0 case. #73 also updated the docstring to note that redshift_colors has no effect in python-FSPS.

flyboys commented 6 years ago

Dear @jrleja ,regarding to the M/L ration . Using FSPS , how would you calculate Mass light ratio as a function of age for a fixed stellar mass or when your IMF=const . I am using the first channel of Spitzer satellite IRAC-1 as Band for my get mags() function .

flyboys commented 6 years ago

What I meant to say , physically M/L ratio is an indirect way to describe the age and metallicity in your stellar population . My goal is to modify it with first channel band of Spitzer satellite with a given sfr to get the luminousity as a function of age for each of my stellar population samples.