def ppxfmontecarlo(datum, wavelengths=None, fluxes=None, ivars=None, outputdir='./', nsimulations=0, inversevariance=True, mask=sky_mask, verbose=1, plot=False, rv=0, ident='', keep=True, template_files=None): ''' Measure CaT strength and optionally calculate uncertainty This function measures the CaT index strength by masking sky lines, fitting a linear combination of template spectra using pPXF, normalising the fitted spectrum, and measuring the CaT index strength on the normalised spectrum. pPXF also fits the radial velocity and velocity dispersion. The function can also compute confidence intervals on the CaT strength, radial velocity and velocity dispersion by using the fitted spectrum and the error array to generating a series of Monte Carlo realisations of the input spectrum and repeating the measurement process for each. ''' if datum is None: datum = gcppxfdata.gcppxfdata() datum.rv = rv if ident == '': ident = str(np.random.randint(1e10)) datum.id = ident datum.file = ident start = datetime.datetime.now() if wavelengths is None or fluxes is None: wavelengths, fluxes = onedspec.getspectrum(datum.scispectrum) zp1 = 1 + datum.rv * 1e3 / constants.c catrange = (wavelengths > 8425 * zp1) & (wavelengths < 8850 * zp1) if ivars is None: wavelengths, sigmas = onedspec.getspectrum(datum.errorspectrum) else: sigmas = ivars if inversevariance: np.putmask(sigmas, sigmas <= 0, 1e-10) sigmas = sigmas**-.5 cat_wavelengths = wavelengths[catrange] cat_fluxes = fluxes[catrange] datum.catwavelengths = cat_wavelengths datum.catfluxes = cat_fluxes cat_sigmas = sigmas[catrange] datum.catsigmas = cat_sigmas s2nregion = (wavelengths > 8400) & (wavelengths < 8500) means2n = (fluxes[s2nregion] / sigmas[s2nregion]).mean() datum.s2n = means2n / (wavelengths[1] - wavelengths[0])**.5 log_wavelengths, log_fluxes = interp.lineartolog(cat_wavelengths, cat_fluxes, function='nearest', ratio=True) log_wavelengths, log_sigmas = interp.lineartolog(cat_wavelengths, cat_sigmas, function='nearest', ratio=True) logDispersion = np.log10(log_wavelengths[1]) - np.log10(log_wavelengths[0]) if template_files is None: template_files = default_templates if not len(template_files): raise Exception('No templates') log_templates = [] for template_file in template_files: template_wavelengths, template_fluxes = onedspec.getspectrum(template_file) log_template_wavelengths, log_template_fluxes = interp.lineartolog(template_wavelengths, template_fluxes, function='nearest', ratio=True, logDispersion=logDispersion) log_templates.append(log_template_fluxes) log_templates = np.vstack(log_templates).T delta_v = (np.log(log_template_wavelengths[0]) - np.log(log_wavelengths[0])) * constants.c / 1e3 regionmask = np.ones(log_wavelengths.size, dtype=np.bool_) if mask is not None: for maskregion in mask: regionmask = regionmask & ~((log_wavelengths > maskregion[0]) & (log_wavelengths < maskregion[1])) goodpixels = np.nonzero(regionmask)[0] else: goodpixels = np.arange(log_wavelengths.size) if verbose > 1: quiet = False else: quiet = True vel_scale = logDispersion * np.log(10) * constants.c / 1e3 log_fit_fluxes, datum.fitwavelengths, datum.fitfluxes, datum.normfluxes, datum.fitrv, datum.fitsigma, datum.CaT = ppxf_CaT(log_wavelengths, log_templates, log_fluxes, log_sigmas, vel_scale, delta_v, datum.rv, 10, goodpixels, quiet) if plot: import matplotlib.pyplot as plt plt.figure() plt.title(datum.file) plt.plot() plt.plot(datum.catwavelengths / (1 + datum.fitrv * 1e3 / constants.c), datum.catfluxes, 'k-') plt.plot(datum.fitwavelengths, datum.fitfluxes, 'r-', lw=1.5) # residules = datum.catfluxes - datum.fitfluxes # plt.plot(datum.fitwavelengths, residules / datum.catsigmas) # plt.plot(datum.catwavelengths / (1 + datum.fitrv * 1e3 / constants.c), datum.catsigmas) plt.xlabel(u'Wavelength (\u00C5)') plt.ylabel('Counts') datum.samplewavelengths = datum.fitwavelengths if nsimulations: samples = [] for i in range(nsimulations): noise = log_sigmas * np.random.normal(size=log_sigmas.size) sample_flux = log_fit_fluxes + noise samples.append((log_wavelengths, log_templates, sample_flux, log_sigmas, vel_scale, delta_v, datum.rv, 10, goodpixels, quiet)) workers = min(multiprocessing.cpu_count(), 12) pool = multiprocessing.Pool(processes=workers) if verbose > 1: print 'Using', workers, 'workers' sample_results = pool.map(_boot_ppxf_CaT, samples) sample_fit_fluxes = [] sample_normed_fluxes = [] sample_rvs = [] sample_sigmas = [] sample_CaTs = [] for i in range(len(sample_results)): sample_result = sample_results[i] sample_fit_fluxes.append(sample_result[2]) sample_normed_fluxes.append(sample_result[3]) sample_rvs.append(sample_result[4]) sample_sigmas.append(sample_result[5]) sample_CaTs.append(sample_result[6]) sample_fit_fluxes = np.vstack(sample_fit_fluxes) sample_normed_fluxes = np.vstack(sample_normed_fluxes) sample_rvs = np.asarray(sample_rvs) sample_sigmas = np.asarray(sample_sigmas) sample_CaTs = np.asarray(sample_CaTs) print sample_fit_fluxes.shape for i in range(sample_normed_fluxes.shape[1]): sample_fit_fluxes[:,i].sort() sample_normed_fluxes[:,i].sort() lowindex = int(.16 * nsimulations) highindex = int(.84 * nsimulations) - 1 datum.lowsample = sample_fit_fluxes[lowindex] datum.highsample = sample_fit_fluxes[highindex] datum.lownormsample = sample_normed_fluxes[lowindex] datum.highnormsample = sample_normed_fluxes[highindex] datum.CaT_samples = sample_CaTs rv_peak, rv_lower, rv_upper, rv_spline = boot.kde_interval(sample_rvs) datum.fitrvle = datum.fitrv - rv_lower datum.fitrvue = rv_upper - datum.fitrv sigma_peak, sigma_lower, sigma_upper, sigma_spline = boot.kde_interval(sample_sigmas) datum.fitsigmale = datum.fitsigma - sigma_lower datum.fitsigmaue = sigma_upper - datum.fitsigma CaT_peak, CaT_lower, CaT_upper, CaT_spline = boot.kde_interval(sample_CaTs) datum.CaTle = datum.CaT - CaT_lower datum.CaTue = CaT_upper - datum.CaT if plot: plt.figure() plt.title(datum.file) plt.hist(sample_rvs, histtype='step', normed=True, bins=int(2 * sample_rvs.size**0.5)) rvs = np.linspace(2 * sample_rvs.min() - sample_rvs.mean(), 2 * sample_rvs.max() - sample_rvs.mean(), 512) plt.plot(rvs, rv_spline(rvs)) plt.xlabel(u'rv (km s$^{\\mathregular{\u22121}}$)') print 'rv', round(datum.fitrv, 1), round(-datum.fitrvle, 1), round(datum.fitrvue, 1) plt.figure() plt.title(datum.file) plt.hist(sample_sigmas, histtype='step', normed=True, bins=int(2 * sample_sigmas.size**0.5)) sigmas = np.linspace(2 * sample_sigmas.min() - sample_sigmas.mean(), 2 * sample_sigmas.max() - sample_sigmas.mean(), 512) plt.plot(sigmas, sigma_spline(sigmas)) plt.xlabel(u'\u03C3 (km s$^{\\mathregular{\u22121}}$)') print 'sigma', round(datum.fitsigma, 1), round(-datum.fitsigmale, 1), round(datum.fitsigmaue, 1) plt.figure() plt.title(datum.file) plt.hist(sample_CaTs, histtype='step', normed=True, bins=int(2 * sample_CaTs.size**0.5)) CaTs = np.linspace(2 * sample_CaTs.min() - sample_CaTs.mean(), 2 * sample_CaTs.max() - sample_CaTs.mean(), 512) plt.plot(CaTs, CaT_spline(CaTs)) plt.xlabel(u'CaT (\u00C5)') print 'CaT', round(datum.CaT, 2), round(-datum.CaTle, 2), round(datum.CaTue, 2) print '[Z/H]', round(datum.CaT * 0.46058111 - 3.75039355, 2), round(-datum.CaTle * 0.46058111, 2), round(datum.CaTue * 0.46058111, 2) else: datum.CaTle = 0 datum.CaTue = 0 datum.lowsample = np.zeros(datum.samplewavelengths.size) datum.highsample = np.zeros(datum.samplewavelengths.size) datum.lownormsample = np.zeros(datum.samplewavelengths.size) datum.highnormsample = np.zeros(datum.samplewavelengths.size) datum.restframemask = sky_mask / zp1 end = datetime.datetime.now() datum.runtime = end - start if verbose: print outputdir + datum.file + '.pickle' print round(datum.CaT, 3), round(datum.CaTle, 3), round(datum.CaTue, 3), round(datum.s2n, 1), datum.runtime, datum.runtime.total_seconds() / (nsimulations + 1) print if keep: pickle.dump(datum, open(outputdir + datum.file + '.pickle', 'w')) if plot: plt.show() return datum
parser.add_argument('-v', '--rv', type=float, help='radial velocity') parser.add_argument('-N', '--num-simulations', type=int, default=0, help='Number of Monte Carlo simulations') parser.add_argument('-o', '--output-dir', help='output directory') #parser.add_argument('-l', '--idl', default='64', help='IDL version') parser.add_argument('-s', '--sigma', action='store_true', default=False, help='Error array is sigmas rather than ivars') parser.add_argument('-n', '--name', help='object name') parser.add_argument('-p', '--plot', action='store_true', default=False, help='Plot fitted spectra and Monte Carlo results') parser.add_argument('--colour') parser.add_argument('--coloure') parser.add_argument('--radius') if __name__ == "__main__": args = parser.parse_args() if not args.output_dir: args.output_dir = os.getcwd() + '/' if not args.name: args.name = args.spectrum[0] if not args.rv: args.rv = 0 datum = gcppxfdata.gcppxfdata() datum.id = args.name datum.file = args.name datum.rv = args.rv datum.scispectrum = args.spectrum[0] datum.errorspectrum = args.error[0] gcppxf.ppxfmontecarlo(datum, outputdir=args.output_dir, nsimulations=args.num_simulations, inversevariance=(not args.sigma), plot=args.plot)