Load the libraries we need:
library(ProSpect)
library(LaplacesDemon)
library(foreach)
library(celestial)
## Loading required package: RANN
## Loading required package: NISTunits
## Loading required package: pracma
##
## Attaching package: 'pracma'
## The following objects are masked from 'package:LaplacesDemon':
##
## logit, loglog, Mode
library(magicaxis)
library(Highlander)
Load some data we want to use:
data("BC03lr") #BC03 spectral library
data("Dale_NormTot") #Normalised Dale templates
data("pivwave") # Pivot/effective wavelengths
Set up using the GAMA filters, additional filters can be used from the EAZY_filters data object which comes with ProSpect
seed = 1
redshift = 0.1
agemax = 13.3e9-cosdistTravelTime(z=redshift, H0 = 67.8, OmegaM = 0.308)*1e9
filters=c('FUV_GALEX', 'NUV_GALEX', 'u_SDSS', 'g_SDSS', 'r_SDSS', 'i_SDSS', 'Z_VISTA',
'Y_VISTA', 'J_VISTA', 'H_VISTA', 'K_VISTA', 'W1_WISE' , 'W2_WISE', 'W3_WISE',
'W4_WISE', 'P100_Herschel', 'P160_Herschel', 'S250_Herschel' , 'S350_Herschel',
'S500_Herschel')
filtout=foreach(i = filters)%do%{approxfun(getfilt(i))}
temppiv=pivwave[pivwave$filter %in% filters,]
Create our model galaxy We will be using a snorm_trunc SFH function and a massmap_lin metallicity with the following parameters:
inpar=c(mSFR = 0, #log-space
mpeak = 0.7, #log-space
mperiod = 0.3, #log-space
mskew = 0.3,
tau_birth = 0, #log-space
tau_screen = -0.5, #log-space
alpha_SF_birth = 1,
alpha_SF_screen = 3,
Zfinal = -2 #log-space
)
Simple function to view our target SFH:
plotSFH=function(par,agemax=13.3, add=FALSE,col='black',ylim=NULL,...){
magcurve(massfunc_snorm_trunc(age=x,mSFR=10^par[1],mpeak=10^par[2],mperiod=10^par[3],
mskew=par[4], magemax=agemax),0,13.8e9,add=add,col=col,
ylim=ylim,xlab='Age (Yr)', ylab='SFR (Msol / Yr)',...)
}
plotSFH(inpar)
Now we can generate our galaxies SED:
genSED=ProSpectSED(massfunc=massfunc_snorm_trunc,
mSFR=10^inpar[1],
mpeak=10^inpar[2],
mperiod=10^inpar[3],
mskew=inpar[4],
tau_birth=10^inpar[5],
tau_screen=10^inpar[6],
alpha_SF_birth=inpar[7],
alpha_SF_screen=inpar[8],
Zfinal = 10^inpar[9],
z=0.1,
Z=Zfunc_massmap_lin,
filtout=filtout,
Dale=Dale_NormTot,
speclib=BC03lr,
agemax=agemax
)
At this point we create our mock photometry catalogue entry with a fractional error in flux of 0.1 assumed (roughly 0.092 mag error). The photom output of ProSpectSED is always Jansky, which is what we want for fitting (you shouldn’t fit in magnitude space!).
flux_input=data.frame(filter=temppiv$filter, pivwave=temppiv$pivwave, flux=genSED$Photom, fluxerr=genSED$Photom*0.1)
print(flux_input)
## filter pivwave flux fluxerr
## 1 FUV_GALEX 1535.080 4.011918e-06 4.011918e-07
## 2 NUV_GALEX 2300.785 5.984452e-06 5.984452e-07
## 3 u_SDSS 3567.001 1.275130e-05 1.275130e-06
## 4 g_SDSS 4734.851 3.799885e-05 3.799885e-06
## 5 r_SDSS 6194.748 6.333013e-05 6.333013e-06
## 6 i_SDSS 7509.465 7.908547e-05 7.908547e-06
## 7 Z_VISTA 8833.013 9.498800e-05 9.498800e-06
## 8 Y_VISTA 10223.626 1.086040e-04 1.086040e-05
## 9 J_VISTA 12545.988 1.157941e-04 1.157941e-05
## 10 H_VISTA 16476.995 1.312316e-04 1.312316e-05
## 11 K_VISTA 21549.195 1.208860e-04 1.208860e-05
## 12 W1_WISE 33897.093 7.034516e-05 7.034516e-06
## 13 W2_WISE 46406.422 4.483248e-05 4.483248e-06
## 14 W3_WISE 125700.270 2.740481e-04 2.740481e-05
## 15 W4_WISE 223141.602 6.297586e-04 6.297586e-05
## 16 P100_Herschel 983273.314 7.548473e-03 7.548473e-04
## 17 P160_Herschel 1546806.337 9.272729e-03 9.272729e-04
## 18 S250_Herschel 2482806.324 6.245763e-03 6.245763e-04
## 19 S350_Herschel 3484355.144 3.030799e-03 3.030799e-04
## 20 S500_Herschel 5004155.150 1.060366e-03 1.060366e-04
In principle if you have a real galaxy to fit and it is already in the required format of flux_input, you can start from this point.
To speed things up we will also pre-compute the Luminosity distance to our source (since this will be the same for every iteration, and will save some computation time):
LumDist_Mpc = cosdistLumDist(z=0.1, H0 = 67.8, OmegaM = 0.308)
Data=list(flux=flux_input,
arglist=list(z=0.1,
massfunc=massfunc_snorm_trunc,
agemax=agemax,
Zagemax = (agemax/1e9),
magemax=(agemax/1e9),
Z=Zfunc_massmap_lin,
LumDist_Mpc=LumDist_Mpc),
speclib=BC03lr,
Dale=Dale_NormTot,
filtout=filtout,
Dale_M2L_func=Dale_M2L_func, # required to get monitored dust masses
SFH=SFHfunc, # the preferred functional form of the SFH (eg either SFHfunc, SFHburst)
parm.names=c('mSFR','mpeak','mperiod','mskew','tau_birth','tau_screen', 'alpha_SF_birth','alpha_SF_screen', 'Zfinal'), # which parameters to fit for
mon.names=c("LP","masstot","dustmass.birth", "dustmass.screen", "dustmass.total", "dustlum.birth", "dustlum.screen", "dustlum.total", "SFRburst", paste("flux.",filters,sep='')), # some of the things you may wish to monitor in each step of the chain
logged=c(T,T,T,F,T,T,F,F,T), # fit parameters in logged or linear space
intervals=list(lo=c(-4,-2,-1,-0.5,-2.5,-2.5,0,0,-4),
hi=c(3,1,1,1,1.5,1,4,4,-1.3)), # fitting range for parameters
fit = 'LD', # specifies the way in which the SED should be fitted ('LD', 'optim', 'CMA', or 'check')
mon.names=c('LP','masstot','SFRburst',paste('flux.',flux_input$filter,sep='')),
N=length(filters), # number of observed filters
like='st', # Using a student-t likelihood
verbose=FALSE
)
Important things:
Using Highlander for the fits:
startpoint = (Data$intervals$lo+Data$intervals$hi)/2
testHigh = Highlander(startpoint, Data,
ProSpectSEDlike, Niters=c(200,200), NfinalMCMC = 200,
lower=Data$intervals$lo, upper=Data$intervals$hi,
seed=seed, optim_iters = 2, likefunctype = 'LD')
## Iteration 1
## CMA 1: -27.687 -0.124 0.768 0.712 -0.279 1.384 -0.747 2.706 1.956 -1.906
##
## Laplace's Demon was called on Fri Aug 13 12:13:35 2021
##
## Performing initial checks...
## Algorithm: Componentwise Hit-And-Run Metropolis
##
## Laplace's Demon is beginning to update...
## Iteration: 100, Proposal: Componentwise, LP: -31.8
## Iteration: 200, Proposal: Componentwise, LP: -27.9
##
## Assessing Stationarity
## Assessing Thinning and ESS
## Creating Summaries
## Creating Output
##
## Laplace's Demon has finished.
## LD Mode 1: -26.461 -0.136 0.752 0.652 0.016 0.593 -0.62 2.459 0 -1.779
## Iteration 2
## CMA 2: -23.502 -0.121 0.479 0.492 -0.389 0.379 -0.545 2.603 0.114 -1.992
##
## Laplace's Demon was called on Fri Aug 13 12:14:23 2021
##
## Performing initial checks...
## Algorithm: Componentwise Hit-And-Run Metropolis
##
## Laplace's Demon is beginning to update...
## Iteration: 100, Proposal: Componentwise, LP: -27.5
## Iteration: 200, Proposal: Componentwise, LP: -28.6
##
## Assessing Stationarity
## Assessing Thinning and ESS
## Creating Summaries
## Creating Output
##
## Laplace's Demon has finished.
## LD Mode 2: -23.5 -0.121 0.479 0.492 -0.389 0.355 -0.545 2.603 0.164 -1.992
Data$fit = 'check'
bestfit=ProSpectSEDlike(testHigh$par, Data=Data)
Checking the output
plot(bestfit)