import bagpipes as pipes import numpy as np import matplotlib.pyplot as plt from pipes_utils import * from matplotlib import rcParams # rcParams.update({'figure.autolayout': True}) datafiles = [ "phil_model_01", "phil_model_02", "phil_model_03", "phil_model_04", "phil_model_05", "phil_model_06", "phil_model_07", "phil_model_08", "phil_model_09", "phil_model_10" ] for filename in datafiles: galaxy, model_components = import_spectrum(filename) # Create the model galaxy object with the defined parameters. model_ID = filename obs_wavs = np.arange(1000.0, 10000.0, 5.0) model = pipes.model_galaxy(model_components, spec_wavs=obs_wavs) sfh = model.sfh.plot(show=False) plt.tight_layout() plt.savefig("pipes/plots/prior/" + model_ID + "_sfh.pdf")
def Generate_Spectra(self, Number, Thresh, Scaling, show): AGN_ON_Spectras = [] AGN_ON = NewFunctions.AGN_Periods( self.Agn_Type, self.Active_Galaxies, self.TriggerTimes, Number, Thresh, Scaling, self.Galaxies['Galaxy'].sfh.age_of_universe, show=show) for i in range(len(AGN_ON)): for j in range(len(AGN_ON[i])): _Z = NewFunctions.Z_Calc(AGN_ON[i][j] * 10**-9) model_components = {} model_components["redshift"] = _Z try: mass_frac = NewFunctions.Mass_Calculator( self.Gal_Params['redshift'], AGN_ON[i][j], self.Galaxies, Number, 100, T_min=AGN_ON[0][0] - 4e8) except ValueError: break dust = {} dust["type"] = "Calzetti" dust["Av"] = 0.2 dblplaw = {} dblplaw['alpha'] = 0.5 dblplaw['beta'] = 10 dblplaw['metallicity'] = 0.2 model_components['dust'] = dust lognormal = {} lognormal['fwhm'] = 0.2 lognormal['metallicity'] = 0.75 dblplaw['tau'] = self.Galaxies['TimesMasses'][Number][ 'PwrLawTime'] lognormal['tmax'] = self.Galaxies['TimesMasses'][Number][ 'BurstTime'] if mass_frac != 0: lognormal['massformed'] = np.log10( mass_frac * 10**self.Galaxies['TimesMasses'][Number]['BurstMass']) model_components['lognormal'] = lognormal dblplaw['massformed'] = self.Galaxies['TimesMasses'][Number][ 'PwrLawMass'] model_components['dblplaw'] = dblplaw _galaxy = bagpipes.model_galaxy(model_components, filt_list=self.Filters, spec_wavs=self.Obs_Wavs) AGN_ON_Spectras.append(_galaxy.spectrum) if j == 0: _galaxy.sfh.plot() return AGN_ON_Spectras
def Generate_SFHs(WL, AGN_df, SB_Prob, Gal_Params, SFH_Only=True, No_SB=False, Save_Data=False): obs_wavs = np.arange(WL[0], WL[1], 0.1) goodss_filt_list = np.loadtxt("filters/goodss_filt_list.txt", dtype="str") masses = AGN_df.data['m_gal'] ledds = AGN_df.data['ledd'] thresh = SB_Prob lognormsfh = [] bheights = [] TimesMasses = [] if not SFH_Only: SB_sfh_list = [] NSB_sfh_list = [] SB_sfhs = [] NSB_sfhs = [] SB_spectra = [] NSB_spectra = [] SB_mass = [] NSB_mass = [] for i in range(len(masses)): lgnl_U, lgnl_L = Gal_Params['lognorm']['Tmax'], Gal_Params['lognorm'][ 'Tmin'] model_components = {} model_components["redshift"] = Gal_Params["redshift"] dust = {} dust["type"] = "Calzetti" dust["Av"] = 0.2 dblplaw = {} dblplaw['alpha'] = Gal_Params['dblplaw']['alpha'] dblplaw['beta'] = Gal_Params['dblplaw']['beta'] dblplaw['metallicity'] = Gal_Params['dblplaw']['metallicity'] model_components['dust'] = dust lognormal = {} lognormal['fwhm'] = Gal_Params['lognorm']['fwhm'] lognormal['metallicity'] = Gal_Params['lognorm']['metallicity'] time_dblp = np.random.uniform( 3, 6, 1)[0] #creates randomness in when galaxies formed dblplaw['tau'] = time_dblp time_lgnl = np.random.uniform(lgnl_U, lgnl_L, 1)[0] lognormal['tmax'] = time_lgnl mass_fraction = np.random.uniform( 5, 20, 1)[0] #randomness to the amount of mass in a starburst. lognormal['massformed'] = np.log10(masses[i] / mass_fraction) chance = np.random.uniform(0, 1, 1)[0] if chance > thresh: #Separating starburst galaxies from galaxies with out starbursts model_components[ 'lognormal'] = lognormal #Only some galaxies will have starbursts. dblplaw['massformed'] = np.log10(masses[i] - (masses[i] / mass_fraction)) model_components['dblplaw'] = dblplaw _galaxy = bagpipes.model_galaxy(model_components, filt_list=goodss_filt_list, spec_wavs=obs_wavs) if not SFH_Only: SB_sfhs.append(_galaxy.sfh.sfh) SB_sfh_list.append(_galaxy.sfh.sfh[0]) SB_spectra.append(_galaxy.spectrum) SB_mass.append(masses[i]) lognormsfh.append(_galaxy.sfh.component_sfrs['lognormal']) bheights.append(ledds[i]) TimesMasses.append({ 'BurstTime': time_lgnl, 'PwrLawTime': time_dblp, 'BurstMass': lognormal['massformed'], 'PwrLawMass': dblplaw['massformed'] }) elif No_SB: #Galaxies without starbursts dblplaw['massformed'] = np.log10(masses[i]) model_components['dblplaw'] = dblplaw _galaxy = bagpipes.model_galaxy(model_components, filt_list=goodss_filt_list, spec_wavs=obs_wavs) NSB_sfhs.append(_galaxy.sfh.sfh) NSB_sfh_list.append(_galaxy.sfh.sfh[0]) NSB_spectra.append(_galaxy.spectrum) NSB_mass.append(masses[i]) Time = (_galaxy.sfh.age_of_universe - _galaxy.sfh.ages) Time_Gyr = Time * 10**-9 SFH_Dic = { 'Time': Time, 'Galaxy': _galaxy, 'lognormlist': lognormsfh, 'AccRates': bheights, 'TimesMasses': TimesMasses } if not SFH_Only: SB_Data = { 'SB_mass': SB_mass, 'SB_sfh_list': SB_sfh_list, 'SB_sfhs': SB_sfhs, 'SB_spectra': SB_spectra, 'Time': Time_Gyr, 'Model_Components': model_components } if SFH_Only: return SFH_Dic elif not SFH_Only: Data = MainSequenceData(SB_Data, SFH_Dic, Save=Save_Data) out = {'Data': Data, 'SB_Data': SB_Data, 'SFH_Data': SFH_Dic} return out
def Generate_Spectra(self, Number, Thresh, Scaling, show, Res, AGN_Off=False, Tmin=None): AGN_ON_WL, AGN_ON_Flux = [], [] if AGN_Off: _df = self.Active_Galaxies minT = self.Galaxies['TimesMasses'][Number][ 'PwrLawTime'] * 10**9 #min(_df['Universe Time'][_df['SFH {}'.format(Number)] > 0.0]) if (not Tmin) or (Tmin < minT): raise Exception( 'Error: Tmin cannot be \'None\' value and must be greater than {}.' .format(minT)) Tmax = max(_df['Universe Time'.format(Number)].dropna()) DeltaT = Tmax / Res AGN_ON = [list(np.arange(Tmin, Tmax, DeltaT))] else: AGN_ON = AGN.AGN_Periods( self.Agn_Type, self.Active_Galaxies, self.TriggerTimes, Number, Thresh, Scaling, self.Galaxies['Galaxy'].sfh.age_of_universe, Res=Res, show=show) for i in range(len(AGN_ON)): for j in range(len(AGN_ON[i])): _Z = AGN.Z_Calc(AGN_ON[i][j] * 10**-9) model_components = {} model_components["redshift"] = _Z dust = {} dust["type"] = "Calzetti" dust["Av"] = 0.2 dblplaw = {} dblplaw['alpha'] = 0.5 dblplaw['beta'] = 10 dblplaw['metallicity'] = 0.2 model_components['dust'] = dust lognormal = {} lognormal['fwhm'] = 0.2 lognormal['metallicity'] = 0.75 dblplaw['tau'] = self.Galaxies['TimesMasses'][Number][ 'PwrLawTime'] lognormal['tmax'] = self.Galaxies['TimesMasses'][Number][ 'BurstTime'] try: if (AGN_Off) or (self.Agn_Type == 'Random'): mass_frac_dblp = SF.Mass_Calculator( self.Gal_Params['redshift'], AGN_ON[i][j], self.Galaxies, Number, 100, T_min=Tmin, component='dblplaw', dblp=dblplaw) if AGN_ON[i][j] > min( self.Active_Galaxies['Universe Time'][ self.Active_Galaxies['SFH {}'.format( Number)] > 0.0]): mass_frac = SF.Mass_Calculator( self.Gal_Params['redshift'], AGN_ON[i][j], self.Galaxies, Number, 100, T_min=AGN_ON[0][0] - 4e8) if mass_frac != 0: lognormal['massformed'] = np.log10( mass_frac * 10**self.Galaxies['TimesMasses'][Number] ['BurstMass']) model_components['lognormal'] = lognormal else: mass_frac_dblp = 1 mass_frac = SF.Mass_Calculator( self.Gal_Params['redshift'], AGN_ON[i][j], self.Galaxies, Number, 100, T_min=AGN_ON[0][0] - 4e8) if mass_frac != 0: lognormal['massformed'] = np.log10( mass_frac * 10**self.Galaxies['TimesMasses'] [Number]['BurstMass']) model_components['lognormal'] = lognormal except ValueError: print('BANG!') break dblplaw['massformed'] = np.log10( mass_frac_dblp * 10**self.Galaxies['TimesMasses'][Number]['PwrLawMass']) model_components['dblplaw'] = dblplaw _galaxy = bagpipes.model_galaxy(model_components, filt_list=self.Filters, spec_wavs=self.Obs_Wavs) log_wavs = np.log10(_galaxy.wavelengths) full_spectrum = _galaxy.spectrum_full * _galaxy.lum_flux * _galaxy.wavelengths wavs = (log_wavs > 2.75) & (log_wavs < 6.75) log_wavs = log_wavs[wavs] full_spectrum = full_spectrum[wavs] dat = pd.DataFrame([10**log_wavs, np.log10(full_spectrum) ]).T.rename(columns={ 0: 'Log WL', 1: 'Flux' }) dat = dat[(dat['Log WL'] > 2000) & (dat['Log WL'] < 6000)] AGN_ON_WL.append(np.array(dat['Log WL'])) AGN_ON_Flux.append(np.array(dat['Flux'])) return AGN_ON_WL, AGN_ON_Flux
dblplaw['metallicity'] = 0.2 model_components['dust'] = dust lognormal = {} lognormal['fwhm'] = 0.2 lognormal['metallicity'] = 0.75 dblplaw['tau'] = TimesMasses[ind]['PwrLawTime'] lognormal['tmax'] = TimesMasses[ind]['BurstTime'] lognormal['massformed'] = TimesMasses[ind]['BurstMass'] dblplaw['massformed'] = TimesMasses[ind]['PwrLawMass'] model_components['lognormal'] = lognormal model_components['dblplaw'] = dblplaw _galaxy = bagpipes.model_galaxy(model_components, filt_list=goodss_filt_list, spec_wavs=obs_wavs) AGN_ON_Spectras.append(_galaxy.spectrum) Spectra_Sum = sum(AGN_ON_Spectras) Spectra_Average = Spectra_Sum / len(AGN_ON_Spectras) fig = plt.figure(figsize=(12, 4)) ax = plt.subplot() x, y = zip(*Spectra_Average) y = np.array(y) / 10**-14 #x = np.array(x)/len(AGN_ON_Spectras) plt.plot(x, y) ax.set_ylabel("$\\mathrm{f_{\\lambda}}\\ \\mathrm{/\\ 10^{" + str(-14) + "}\\ erg\\ s^{-1}\\ cm^{-2}\\ \\AA^{-1}}$") ax.set_xlabel("$\\lambda / \\mathrm{\\AA}$")
def static_plot(self, show=True, figsize=(13,9)): """ Creates the figure, lines, texts and annotations. Returns figure and axes (in a list) for further manipulation by the user if needed. """ self.fig = plt.figure(figsize=figsize) if self.index_list is None: gs1 = matplotlib.gridspec.GridSpec(13, 1, hspace=0., wspace=0.) else: index_ncols = -(-len(self.index_list)//5) gs0 = self.fig.add_gridspec(1, 3+index_ncols) gs1 = gs0[:3].subgridspec(13, 1, hspace=0., wspace=0.) gs2 = gs0[3:].subgridspec(5, index_ncols, hspace=0.5, wspace=0.2) # indices plots for i in range(len(self.index_list)): self.index_list[i]['ax'] = plt.subplot(gs2[i%5,i//5]) self.ax1 = plt.subplot(gs1[0:5]) #SFH plot self.ax2 = plt.subplot(gs1[6:11]) #main spectrum plot self.ax3 = plt.subplot(gs1[11:]) #residual plot init_input_logM, self.total_sfh, init_custom_sfh = utils.create_sfh(self.init_comp) self.sfh_line, self.z_line, self.z_text, self.input_logM_text, self.bad_sfh_text \ = plotting.add_sfh_plot(self.init_comp, self.total_sfh, init_input_logM, self.ax1, sfh_color=self.plot_colors['sfh'], z_line_color=self.plot_colors['z']) self.model = pipes.model_galaxy(utils.make_pipes_components(self.init_comp, init_custom_sfh), spec_wavs=self.wavelengths) # full spectrum in inset self.sub_ax = plt.axes([0,0,1,1]) # Manually set the position and relative size of the inset axes within ax2 ip = InsetPosition(self.ax2, self.sub_ax_arg) self.sub_ax.set_axes_locator(ip) sub_y_scale_spec,self.sub_spec_line = plotting.add_bp_spectrum(self.model.spectrum, self.sub_ax, sub=True, color=self.plot_colors['spectrum']) self.spec_zoom_poly = self.sub_ax.fill_between(self.init_spec_lim, [0]*2, [20]*2, color=self.plot_colors['zoom'], alpha=0.1) # the main spectrum plot self.spec_line, self.run_med_line, self.overflow_text, y_scale_spec \ = plotting.add_main_spec(self.model.spectrum, self.ax2, self.init_spec_lim, median_width=self.median_width, color=self.plot_colors['spectrum'], continuum_color=self.plot_colors['continuum']) # the residual plot self.res_line = plotting.add_residual(self.model.spectrum, self.ax3, self.init_spec_lim, median_width=self.median_width, color=self.spec_line.get_color()) # indices plots if self.index_list is not None: self.index_names = [ind["name"] for ind in self.index_list] # calculate and plot indices self.indices = np.zeros(len(self.index_list)) for i in range(self.indices.shape[0]): self.indices[i] = pipes.input.spectral_indices.measure_index( self.index_list[i], self.model.spectrum, self.init_comp["redshift"]) self.index_list[i] = plotting.add_index_spectrum( self.index_list[i], self.model.spectrum, self.indices[i], self.init_comp["redshift"], y_scale_spec, color_continuum=self.plot_colors['index_continuum'], color_feature=self.plot_colors['index_feature'], alpha=0.2 ) plt.tight_layout() if show: plt.show() return self.fig, [self.ax1, self.ax2, self.ax3, self.sub_ax]
def ribbon_plot(self, parameter, range=None, log_space=False, nlines=10, lw=1, alpha=1.0, show=True, figsize=(13,10), cmap='viridis', reverse=False): """ Creates a 2-panel spectrum and residual plot where the varying spectra of a galaxy with the defined initial components under the change of one specified parameter. Spectra are in lines that match with the specified colourmap, shown as a colorbar on the side. When range is not specified, it defaults to the slider ranges in slider_params. Putting log_space=True spaces the parameter values for the spectra in log, instead of the default linear spacing. Putting reverse=True inverts the zorder and colour scheme of the lines, included for cases where it is easier to spot variations by plotting the spectra of higher parameter values at lower zorder. Returns figure and axes (in a list) for further manipulation by the user if needed. """ # create a dummy model init_input_logM, init_sfh, init_custom_sfh = utils.create_sfh(self.init_comp) model = pipes.model_galaxy( utils.make_pipes_components(self.init_comp, init_custom_sfh), spec_wavs=self.wavelengths) # calculate the ticks at which to vary the chosen parameter if range is None: range = slider_params.slider_lib[parameter]['lims'] if log_space: param_ticks = 10**np.linspace(np.log10(range[0]),np.log10(range[1]),nlines) else: param_ticks = np.linspace(range[0],range[1],nlines) if reverse: param_ticks = param_ticks[::-1] # loop through parameter ticks and update model to get spectrum and residuals to plot spectrums = [] ymaxs = [] residuals = [] for i,ticki in enumerate(param_ticks): new_init_comp = copy.deepcopy(self.init_comp) if ':' in parameter: new_init_comp[parameter.split(':')[0]][parameter.split(':')[1]] = ticki else: new_init_comp[parameter] = ticki init_input_logM, init_sfh, init_custom_sfh = utils.create_sfh(new_init_comp) model.update(utils.make_pipes_components(new_init_comp, init_custom_sfh)) zoom_in_spec = model.spectrum[np.where((model.spectrum[:,0] >= self.init_spec_lim[0]) & (model.spectrum[:,0] <= self.init_spec_lim[1]))] spectrums.append(zoom_in_spec.copy()) #figure out the optimal y scale to use, first calculate all ymaxes ymaxs.append(1.05*np.max(spectrums[-1][:, 1])) #calculate residuals (full range) run_med = utils.running_median(model.spectrum[:,0], model.spectrum[:,1], width=self.median_width) residual = model.spectrum[:,1] / run_med zoom_in_res = residual[np.where((model.spectrum[:,0] >= self.init_spec_lim[0]) & (model.spectrum[:,0] <= self.init_spec_lim[1]))] residuals.append(zoom_in_res.copy()) # extract colours from the chosen colourmap if reverse: colormap = matplotlib.cm.get_cmap(cmap+'_r') else: colormap = matplotlib.cm.get_cmap(cmap) colors = matplotlib.cm.get_cmap(cmap)((param_ticks-param_ticks[0])/(param_ticks[-1]-param_ticks[0])) # now create the figure fig = plt.figure(figsize=figsize) gs1 = matplotlib.gridspec.GridSpec(7, 1, hspace=0., wspace=0.) ax1 = plt.subplot(gs1[:5]) #main spectrum plot ax2 = plt.subplot(gs1[5:]) #residual plot ymax = max(ymaxs) y_scale = int(np.log10(ymax))-1 res_lims = [] for i,spectrum in enumerate(spectrums): ax1.plot(spectrum[:, 0], spectrum[:, 1]*10**-y_scale, color=colors[i], zorder=4, lw=lw, alpha=alpha) ax2.plot(spectrum[:, 0], residuals[i], color=colors[i], lw=lw, zorder=1, alpha=alpha) res_span = max(residuals[i]) - min(residuals[i]) res_lims.append([min(residuals[i])-0.1*res_span, max(residuals[i])+0.1*res_span]) # Sort out spectrum limits and axis labels ax1.set_ylim(0., ymax*10**-y_scale) ax1.set_xlim(self.init_spec_lim) ax1.set_xticks([]) pipes.plotting.auto_axis_label(ax1, y_scale, z_non_zero=True) # add residual value guidelines and labels ax2.axhline(1, color="black", ls="--", lw=1, zorder=0) ax2.axhline(1.5, color="black", ls=":", lw=1, zorder=0) ax2.annotate('1.5x', [0.98*(self.init_spec_lim[1]-self.init_spec_lim[0])+self.init_spec_lim[0], 1.5], ha='center', va='center') ax2.axhline(0.5, color="black", ls=":", lw=1, zorder=0) ax2.annotate('0.5x', [0.98*(self.init_spec_lim[1]-self.init_spec_lim[0])+self.init_spec_lim[0], 0.5], ha='center', va='center') # Sort out residual limits and axis labels ax2.set_xlim(self.init_spec_lim) pipes.plotting.auto_x_ticks(ax2) pipes.plotting.auto_axis_label(ax2, -1, z_non_zero=True) ax2.set_ylabel('flux/\ncontinuum') # rescale the y axis to be determined only by the residuals in frame res_lims = np.array(res_lims) ax2.set_ylim([min(res_lims[:,0]), max(res_lims[:,1])]) plt.subplots_adjust(right=0.90) cax = plt.axes([0.91, 0.14, 0.02, 0.72]) cbar = plt.colorbar(plt.cm.ScalarMappable(cmap=colormap, norm=matplotlib.colors.Normalize(vmin=range[0], vmax=range[1])), cax=cax) cbar.set_label(slider_params.slider_lib[parameter]['label'], rotation=270) if show: plt.show() return fig, [ax1, ax2]