def ChiSqMap(initial_param='smc', Av_init=-0.62, beta_init=-1.45, time_thresh=5): ''' Loop through a bunch of different parameter values and map out how chisq changes as you change these values. ''' directory = '/Users/amorgan/Data/PAIRITEL/120119A/PTELDustCompare/AlignedDataPTELPROMPT+SMARTS.dat' objblock = PhotParse.PhotParse(directory) sedtimelist = objblock.obsdict['PAIRITEL_J'].tmidlist addl_sed_times = objblock.obsdict['SMARTS_J'].tmidlist for time in addl_sed_times: sedtimelist.append(time) directory = '/Users/amorgan/Data/PAIRITEL/120119A/PTELDustCompare/AlignedDataPTELPROMPT+SMARTS.dat' objblock = PhotParse.PhotParse(directory) sedtimelist = objblock.obsdict['PAIRITEL_J'].tmidlist addl_sed_times = objblock.obsdict['SMARTS_J'].tmidlist for time in addl_sed_times: sedtimelist.append(time) objblock = PhotParse.PhotParse(directory) if not sedtimelist: # use this as a default if it is not explicitly defined sedtimelist = objblock.obsdict['PAIRITEL_J'].tmidlist # need to do this to see how many alignments we have aligndict = _align_SED_times(objblock, sedtimelist, time_thresh=time_thresh) # need to do this to see how many alignments we have aligndict = _align_SED_times(objblock, sedtimelist, time_thresh=time_thresh) # set up the fit dict fitdict = _getfitdict(initial_param, Av_init=Av_init, beta_init=beta_init) fitdict.pop('const') # get rid of the old const fitdict.pop('Av') fitdict.pop('beta') # add the correct number of normalization constants based on the number of aligned SEDs for constnumber in np.arange(len(aligndict)): name = 'const' + str(constnumber) fitdict.update({name: {'init': 10000, 'fixed': False}}) # do a for loop here, fixing Av_1 and beta_1 at different values numav = 25 numbeta = 25 steps = numav * numbeta Av_1_steps = np.linspace(-2.01, 0.01, num=numav) # 50 items from -2 to 0 beta_1_steps = np.linspace(-1.01, 3.01, num=numbeta) chisqarr = np.zeros((numav, numbeta)) count = 0 for avind in np.arange(numav): Av_1 = Av_1_steps[avind] for betaind in np.arange(numbeta): count += 1 print "Doing step %i of %i" % (count, steps) beta_1 = beta_1_steps[betaind] fitdict2 = { 'Av_0': { 'init': -0.62, 'fixed': True }, 'Av_1': { 'init': Av_1, 'fixed': True }, 'Av_2': { 'init': 1000, 'fixed': False }, 'beta_0': { 'init': -1.45, 'fixed': True }, 'beta_1': { 'init': beta_1, 'fixed': True }, 'beta_2': { 'init': 1000, 'fixed': False } } fitdict.update(fitdict2) try: outdict = SEDtimeSimulFit(objblock, sedtimelist, fitdict) chisq = outdict['chi2'] except: chisq = np.nan chisqarr[avind, betaind] = chisq return chisqarr
def SEDtimeSimulFit120119A(objblock=None, initial_param='smc', fixparam='Av', sedtimelist=None, Av_0init=-0.57, Av_1init=0, Av_2init=50, beta_0init=-1.57, beta_1init=0, beta_2init=50, randomize_inits=False, unred_latetime=False, plot=False, plotchi2=True, retfig=True, time_thresh=5, plot_every_model=False, fixxlim=None): ''' time_thresh: Number of seconds we can be off in time from the reference interp_type used to be a paaramter when it was done inside here, but now we want the interpolation to be done prior to calling this function set unred_latetime=True and initial param to mw for the assumption of late-time SMC and early time MW ''' fig = None if objblock == None: print "WARNING: NO OBJBLOCK SPECIFIED. USING DEFAULTS" directory = '/Users/amorgan/Data/PAIRITEL/120119A/PTELDustCompare/AlignedDataPTELPROMPT+SMARTS.dat' objblock = PhotParse.PhotParse(directory) #NOTE: Now do the interpolation PRIOR to calling this function # if interp_type != None: # directory='/Users/amorgan/Data/PAIRITEL/120119A/Combined/120119Afinal.dat' # objblock = BuildInterpolation(interp_type=interp_type) # sedtimelist = objblock.sedtimelist #made sedtimelist an attribute in BuildInterpolation # # FIXME : need to have a smarter way of building the sedtimelist; should be built up in # # the smartinterpolation stage, using all the "take as given" frames # # sedtimelist=objblock.obsdict['PAIRITEL_J'].tmidlist[0:20] #only take the first ptel ones # addl_sed_times=objblock.obsdict['SMARTS_J'].tmidlist[0:3] #add the smarts # for time in addl_sed_times: # sedtimelist.append(time) # defaulttimelist='PTELSMARTS' # interpolation will give us an sedtimelist. If we didnt do this, we need to choose it.. if sedtimelist == None: print "WARNING: NO SEDTIMELIST SPECIFIED. USING DEFAULTS." sedtimelist = objblock.obsdict['PAIRITEL_J'].tmidlist[ 0:20] #only take the first ptel ones addl_sed_times = objblock.obsdict['SMARTS_J'].tmidlist[ 0:3] #add the smarts for time in addl_sed_times: sedtimelist.append(time) # if defaulttimelist == 'PAIRITEL': # use this as a default if it is not explicitly defined # sedtimelist=objblock.obsdict['PAIRITEL_J'].tmidlist # elif defaulttimelist == 'PTELSMARTS': # sedtimelist=objblock.obsdict['PAIRITEL_J'].tmidlist[0:20]#only take the first ptel ones # addl_sed_times=objblock.obsdict['SMARTS_J'].tmidlist[0:3] #add the smarts # for time in addl_sed_times: # sedtimelist.append(time) # else: # raise ValueError('Invalid defaulttimelist') # need to do this to see how many alignments we have aligndict = _align_SED_times(objblock, sedtimelist, time_thresh=time_thresh) # set up the fit dict fitdict = _getfitdict(initial_param, Av_init=Av_0init, beta_init=beta_0init) fitdict.pop('const') # get rid of the old const fitdict.pop('Av') fitdict.pop('beta') # add the correct number of normalization constants based on the number of aligned SEDs for constnumber in np.arange(len(aligndict)): name = 'const' + str(constnumber) fitdict.update({name: {'init': 20000, 'fixed': False}}) # setting up the new parameters fitdict2 = { 'Av_0': { 'init': Av_0init, 'fixed': False }, 'Av_1': { 'init': Av_1init, 'fixed': False }, 'Av_2': { 'init': Av_2init, 'fixed': False }, 'beta_0': { 'init': beta_0init, 'fixed': False }, 'beta_1': { 'init': beta_1init, 'fixed': False }, 'beta_2': { 'init': beta_2init, 'fixed': False } } # fixing those as desired if fixparam == 'beta': fixlist = ['beta_0', 'beta_1', 'beta_2'] elif fixparam == 'Av': fixlist = ['Av_0', 'Av_1', 'Av_2'] elif fixparam == 'both': fixlist = ['Av_0', 'beta_0'] elif fixparam == 'all': # for testing purposes fixlist = ['Av_0', 'Av_1', 'Av_2', 'beta_0', 'beta_1', 'beta_2'] elif fixparam == 'none': fixlist = [] else: raise ValueError('invalid fixparam') for key in fixlist: if key in fitdict2: fitdict2[key]['fixed'] = True else: errmsg = '%s is not a valid fit parameter' raise ValueError(errmsg) # Go through and randomize the initial parameters, if desired, according to # The acceptable physical ranges. Crappy coding practice ahoy! if randomize_inits: import random Av_0range = (0, -2.0) Av_1range = (0, -2.0) Av_2range = (0, 1000) beta_0range = (-2.0, 2.0) beta_1range = (-2.0, 2.0) beta_2range = (0, 1000) const_range = (10000, 30000) if not fitdict2['Av_0']['fixed']: fitdict2['Av_0']['init'] = random.uniform(Av_0range[0], Av_0range[1]) if not fitdict2['Av_1']['fixed']: fitdict2['Av_1']['init'] = random.uniform(Av_1range[0], Av_1range[1]) if not fitdict2['Av_2']['fixed']: fitdict2['Av_2']['init'] = random.uniform(Av_2range[0], Av_2range[1]) if not fitdict2['beta_0']['fixed']: fitdict2['beta_0']['init'] = random.uniform( beta_0range[0], beta_0range[1]) if not fitdict2['beta_1']['fixed']: fitdict2['beta_1']['init'] = random.uniform( beta_1range[0], beta_1range[1]) if not fitdict2['beta_2']['fixed']: fitdict2['beta_2']['init'] = random.uniform( beta_2range[0], beta_2range[1]) for key, value in fitdict.iteritems( ): # loop through all the constants if key[0:5] == 'const': value['init'] = random.uniform(const_range[0], const_range[1]) ### END RANDOMIZATION fitdict.update(fitdict2) outdict = SEDtimeSimulFit(objblock, sedtimelist, fitdict, correct_late_time_dust=unred_latetime) #### FIX THIS - from the fitdict you should be able to get thie initial value # from the ones what were fixed, and those that were free # return outdict Av1 = None Av2 = None Av0 = None beta1 = None beta2 = None beta0 = None paramcount = 0 # keeping track of parameters since qFit.fit throws them in random places for param in outdict['parameters']: if param.name == 'Av_1': Av1 = param.value Av1_index = paramcount elif fitdict['Av_1'][ 'fixed'] == True: # if we fixed it, wouldnt have gone to parameters Av1 = fitdict['Av_1']['init'] Av1_index = None if param.name == 'Av_2': Av2 = param.value Av2_index = paramcount elif fitdict['Av_2'][ 'fixed'] == True: # if we fixed it, wouldnt have gone to parameters Av2 = fitdict['Av_2']['init'] Av2_index = None if param.name == 'Av_0': Av0 = param.value Av0_index = paramcount elif fitdict['Av_0'][ 'fixed'] == True: # if we fixed it, wouldnt have gone to parameters Av0 = fitdict['Av_0']['init'] Av0_index = None if param.name == 'beta_1': beta1 = param.value beta1_index = paramcount elif fitdict['beta_1'][ 'fixed'] == True: # if we fixed it, wouldnt have gone to parameters beta1 = fitdict['beta_1']['init'] beta1_index = None if param.name == 'beta_2': beta2 = param.value beta2_index = paramcount elif fitdict['beta_2'][ 'fixed'] == True: # if we fixed it, wouldnt have gone to parameters beta2 = fitdict['beta_2']['init'] beta2_index = None if param.name == 'beta_0': beta0 = param.value beta0_index = paramcount elif fitdict['beta_0'][ 'fixed'] == True: # if we fixed it, wouldnt have gone to parameters beta0 = fitdict['beta_0']['init'] beta0_index = None paramcount += 1 #### ##### # recalculate chi2 as a function of time based on the model and each time point chi2list = [] doflist = [] reducedchi2list = [] for time in sedtimelist: corrtime = time / (1. + objblock.redshift) # grab the Av and beta values for each time point # note we use the corrected time here, but the observer time in the SEDvsTime, # because SEDvsTime only uses it as an index Av_snap = DecayingExponentialAv(corrtime, Av0, Av1, Av2) beta_snap = DecayingExponentialbeta(corrtime, beta0, beta1, beta2) #hack! chi2, dof = SEDvsTime(objblock, initial_param=initial_param, plotsed=False, fitlist=[], sedtimelist=[time], retfig=False, fig=None, plotchi2=False, retchi2=True, Av_init=Av_snap, beta_init=beta_snap) chi2list.append(chi2) doflist.append(dof) reducedchi2list.append(float(chi2) / int(dof)) print "chi2 list:" print chi2list print sum(chi2list) print "Dof list:" print doflist print sum(doflist) corrtimelist = np.array(sedtimelist) / (1. + objblock.redshift) # raise Exception #### #### if plot: fig = plt.figure() t = 10**np.linspace(1, 4, 1000) #evenly spaced in log space plot_uncertainty_estimate = True if not fitdict['beta_1']['fixed'] and not fitdict['Av_1']['fixed']: if not plotchi2: ax1 = fig.add_axes([0.1, 0.1, 0.8, 0.4]) ax2 = fig.add_axes([0.1, 0.5, 0.8, 0.4]) ax1.semilogx() ax2.semilogx() else: ax2 = fig.add_axes([0.1, 0.6, 0.8, 0.3]) ax1 = fig.add_axes([0.1, 0.3, 0.8, 0.3]) ax3 = fig.add_axes([0.1, 0.1, 0.8, 0.2]) ax3.semilogx() ax1.semilogx() ax2.semilogx() # plot model c = DecayingExponentialAv(t, Av0, Av1, Av2) d = DecayingExponentialbeta(t, beta0, beta1, beta2) c = -1 * np.array(c) #changing since Av negative ax2.plot(t, d, lw=2, color='#FF0000') #beta old_ax2lim = ax2.get_ylim() #saving for later ax1.plot(t, c, lw=2, color='#FF0000') #Av old_ax1lim = ax1.get_ylim() # saving for later if plot_uncertainty_estimate: ## plot unerlying uncertainty, drawing from multivariate gaussian mean = [param.value for param in outdict['parameters']] mean = tuple(mean) cov = outdict['covarmatrix'] # nxvals=1000 nsimulations = 1500 samples = np.random.multivariate_normal( mean, cov, (nsimulations)) simymat = np.empty((nsimulations, len(t))) ############# ## FOR BETA count = 0 badbetacount = 0 for sample in samples: if beta0_index is not None: sample_beta_0 = sample[beta0_index] else: sample_beta_0 = beta0 # fixed value if beta0_index is None if beta2_index is not None: sample_beta_2 = sample[beta2_index] else: sample_beta_2 = beta2 # fixed value if beta2_index is None if beta1_index is not None: sample_beta_1 = sample[beta1_index] else: sample_beta_1 = beta1 # fixed value if beta1_index is None simyvals = DecayingExponentialbeta(t, sample_beta_0, sample_beta_1, sample_beta_2) # some samples were diverging to unphysical values; weird since # the late time values were supposedly fixed to set values. Given # that, here we will only add to the matrix and plot if the late # time value is not something crazy. Lazy hack now of just +/- 100 if simyvals[-1] < 100 and simyvals[-1] > -100: simymat[count] = simyvals if plot_every_model: ax2.plot(t, simyvals, lw=2, color='black', alpha=0.01) count += 1 else: badbetacount += 1 #correct for the bad fits above: goodcount = nsimulations - badbetacount simymat = simymat[:goodcount] #two sigma is 95.4% simylower02point3 = stats.scoreatpercentile(simymat, 2.3) simyupper97point7 = stats.scoreatpercentile(simymat, 97.7) if not plot_every_model: ax2.fill_between(t, simylower02point3, simyupper97point7, color='#CCCCCC') else: ax2.plot(t, simylower02point3, linestyle=':', lw=2, color='#FF6600') ax2.plot(t, simyupper97point7, linestyle=':', lw=2, color='#FF6600') simyupper84 = stats.scoreatpercentile(simymat, 84.1) simylower16 = stats.scoreatpercentile(simymat, 15.9) if not plot_every_model: ax2.fill_between(t, simylower16, simyupper84, color='#888888') else: ax2.plot(t, simylower16, linestyle='--', lw=2, color='#FF3300') ax2.plot(t, simyupper84, linestyle='--', lw=2, color='#FF3300') ## FOR AV simymat = np.empty((nsimulations, len(t))) count = 0 badavcount = 0 for sample in samples: if Av0_index is not None: sample_Av_0 = sample[Av0_index] else: sample_Av_0 = Av0 # fixed value if Av0_index is None if Av2_index is not None: sample_Av_2 = sample[Av2_index] else: sample_Av_2 = Av2 # fixed value if Av2_index is None if Av1_index is not None: sample_Av_1 = sample[Av1_index] else: sample_Av_1 = Av1 # fixed value if Av1_index is None simyvals = DecayingExponentialAv(t, sample_Av_0, sample_Av_1, sample_Av_2) simyvals = -1 * np.array( simyvals) #changing since Av negative # some samples were diverging to unphysical values; weird since # the late time values were supposedly fixed to set values. Given # that, here we will only add to the matrix and plot if the late # time value is not something crazy. Lazy hack now of just +/- 100 if simyvals[-1] < 100 and simyvals[-1] > -100: simymat[count] = simyvals if plot_every_model: ax1.plot(t, simyvals, lw=2, color='black', alpha=0.01) count += 1 else: badavcount += 1 #correct for the bad fits above: goodcount = nsimulations - badavcount simymat = simymat[:goodcount] #two sigma is 95.4% simylower02point3 = stats.scoreatpercentile(simymat, 2.3) simyupper97point7 = stats.scoreatpercentile(simymat, 97.7) if not plot_every_model: ax1.fill_between(t, simylower02point3, simyupper97point7, color='#CCCCCC') else: ax1.plot(t, simylower02point3, linestyle=':', lw=2, color='#FF6600') ax1.plot(t, simyupper97point7, linestyle=':', lw=2, color='#FF6600') simyupper84 = stats.scoreatpercentile(simymat, 84.1) simylower16 = stats.scoreatpercentile(simymat, 15.9) if not plot_every_model: ax1.fill_between(t, simylower16, simyupper84, color='#888888') else: ax1.plot(t, simylower16, linestyle='--', lw=2, color='#FF3300') ax1.plot(t, simyupper84, linestyle='--', lw=2, color='#FF3300') ####### print "Number of betas diverging out of %i: %i" % ( nsimulations, badbetacount) print "Number of Avs diverging out of %i: %i" % (nsimulations, badavcount) #plot again c = DecayingExponentialAv(t, Av0, Av1, Av2) d = DecayingExponentialbeta(t, beta0, beta1, beta2) c = -1 * np.array(c) #changing since Av negative ax2.plot(t, d, lw=2, color='#FF0000') #beta ax1.plot(t, c, lw=2, color='#FF0000') #Av ax1.set_ylim(old_ax1lim) ax2.set_ylim(old_ax2lim) ax1.set_ylim((1.0, 1.65)) ax2.set_ylim((-1.28, -0.90)) ax1.set_ylabel(r'$A_V$', size=16) ax2.set_ylabel(r'$\beta$', size=16) ax1.set_xlabel(r'$t$ (s, rest frame)', size=16) # if not fixylimAv: # pass # else: # ax1.set_ylim(fixylimAv) # if not fixylimbeta: # pass # else: # ax2.set_ylim(fixylimbeta) if plotchi2: ax3.scatter(corrtimelist, reducedchi2list) ax2.set_xlabel('') ax3.set_xlabel(r'$t$ (s, rest frame)', size=16) ax3.set_ylabel(r'$\chi^2$ / dof', size=16) ylim = ax3.get_ylim() ax3.set_ylim([0, ylim[1] ]) # ensure bottom is 0; cant have chi2 < 0 xlim = ax3.get_xlim() # set all xlims to be the same ax1.set_xlim(xlim) ax1.set_xticks(ax1.get_xticks()[1:-1]) ax2.set_xlim(xlim) ax2.set_xticks(ax2.get_xticks()[1:-1]) ax1.set_yticks(ax1.get_yticks()[1:-1]) ax2.set_yticks(ax2.get_yticks()[1:]) ax3.set_yticks(ax3.get_yticks()[:-1]) string = 'Total chi2 / dof = %.2f / %i' % (outdict['chi2'], outdict['dof']) fig.text(0.55, 0.2, string) else: ax2.set_xticks([]) #beta ax2.set_yticks(ax2.get_yticks()[1:]) elif not fitdict['Av_1']['fixed']: ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) ax.semilogx() # c=DecayingExponentialAv(t,Av0,Av1,Av2) c = DecayingExponentialAv(t, Av0, Av1, Av2) c = -1 * np.array(c) #changing since Av negative ax.plot(t, c) elif not fitdict['beta_1']['fixed']: ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) ax.semilogx() # c=DecayingExponentialbeta(t,Av0,Av1,Av2) c = DecayingExponentialbeta(t, beta0, beta1, beta2) ax.plot(t, c) if fixxlim: try: ax1.set_xlim(fixxlim) except: pass try: ax2.set_xlim(fixxlim) except: pass try: ax3.set_xlim(fixxlim) except: pass try: ax.set_xlim(fixxlim) except: pass fig.show() filepath = storepath + 'SEDtimesimulfit.png' fig.savefig(filepath) filepath = storepath + 'SEDtimesimulfit.pdf' fig.savefig(filepath) if retfig and fig != None: return fig else: return outdict