コード例 #1
0
    def main(args):

        import time
        from mangadap.config import defaults
        from mangadap.par.analysisplan import AnalysisPlanSet
        from mangadap.proc.spatiallybinnedspectra import SpatiallyBinnedSpectra
        from mangadap.proc.stellarcontinuummodel import StellarContinuumModel
        from mangadap.proc.emissionlinemodel import EmissionLineModel

        t = time.perf_counter()

        # Set the the analysis path and make sure it exists
        analysis_path = defaults.dap_analysis_path(drpver=args.drpver, dapver=args.dapver) \
                                if args.analysis_path is None else args.analysis_path

        analysisplan = AnalysisPlanSet.from_par_file(args.plan_file)
        daptypes = []
        for p in analysisplan:
            bin_method = SpatiallyBinnedSpectra.define_method(p['bin_key'])
            sc_method = StellarContinuumModel.define_method(p['continuum_key'])
            el_method = EmissionLineModel.define_method(p['elfit_key'])
            daptypes += [defaults.dap_method(bin_method['key'],
                                            sc_method['fitpar']['template_library_key'],
                                            el_method['continuum_tpl_key'])]

        dap_status(analysis_path, daptypes, logdir=args.logdir)

        print('Elapsed time: {0} seconds'.format(time.perf_counter() - t))
コード例 #2
0
ファイル: plate_fit_qa.py プロジェクト: HSIYJND/mangadap
def main(args):
    t = time.perf_counter()
    if args.bgagg:
        pyplot.switch_backend('agg')

    # Set the paths
    redux_path = defaults.drp_redux_path(drpver=args.drpver) \
                        if args.redux_path is None else args.redux_path
    analysis_path = defaults.dap_analysis_path(drpver=args.drpver, dapver=args.dapver) \
                        if args.analysis_path is None else args.analysis_path

    daptypes = []
    if args.daptype is None:
        analysisplan = AnalysisPlanSet.default() if args.plan_file is None \
                            else AnalysisPlanSet.from_par_file(args.plan_file)
        for p in analysisplan:
            bin_method = SpatiallyBinnedSpectra.define_method(p['bin_key'])
            sc_method = StellarContinuumModel.define_method(p['continuum_key'])
            el_method = EmissionLineModel.define_method(p['elfit_key'])
            daptypes += [
                defaults.dap_method(
                    bin_method['key'],
                    sc_method['fitpar']['template_library_key'],
                    el_method['continuum_tpl_key'])
            ]
    else:
        daptypes = [args.daptype]

    for daptype in daptypes:
        plate_fit_qa(args.dapver, analysis_path, daptype, args.plate)

    print('Elapsed time: {0} seconds'.format(time.perf_counter() - t))
コード例 #3
0
def main(args):

    t = time.perf_counter()

    if args.bgagg:
        pyplot.switch_backend('agg')

    # Set the the analysis path and make sure it exists
    analysis_path = defaults.dap_analysis_path(drpver=args.drpver, dapver=args.dapver) \
                            if args.analysis_path is None else args.analysis_path

    daptypes = []
    if args.daptype is None:
        analysisplan = AnalysisPlanSet.default() if args.plan_file is None \
                            else AnalysisPlanSet.from_par_file(args.plan_file)
        for p in analysisplan:
            bin_method = SpatiallyBinnedSpectra.define_method(p['bin_key'])
            sc_method = StellarContinuumModel.define_method(p['continuum_key'])
            el_method = EmissionLineModel.define_method(p['elfit_key'])
            daptypes += [
                defaults.dap_method(
                    bin_method['key'],
                    sc_method['fitpar']['template_library_key'],
                    el_method['continuum_tpl_key'])
            ]
    else:
        daptypes = [args.daptype]

    for daptype in daptypes:
        plan_qa_dir = defaults.dap_method_path(daptype,
                                               plate=args.plate,
                                               ifudesign=args.ifudesign,
                                               qa=True,
                                               drpver=args.drpver,
                                               dapver=args.dapver,
                                               analysis_path=analysis_path)
        ofile = os.path.join(
            plan_qa_dir, 'manga-{0}-{1}-MAPS-{2}-spotcheck.png'.format(
                args.plate, args.ifudesign, daptype))
        if not os.path.isdir(plan_qa_dir):
            os.makedirs(plan_qa_dir)

        spotcheck_images(analysis_path,
                         daptype,
                         args.plate,
                         args.ifudesign,
                         ofile=ofile)

    print('Elapsed time: {0} seconds'.format(time.perf_counter() - t))
コード例 #4
0
ファイル: dapall_qa.py プロジェクト: HSIYJND/mangadap
def main(args):
    t = time.perf_counter()

    if args.bgagg:
        pyplot.switch_backend('agg')

    # Set the paths
    redux_path = defaults.drp_redux_path(drpver=args.drpver) \
                        if args.redux_path is None else args.redux_path
    analysis_path = defaults.dap_analysis_path(drpver=args.drpver, dapver=args.dapver) \
                            if args.analysis_path is None else args.analysis_path

    daptypes = []
    if args.daptype is None:
        analysisplan = AnalysisPlanSet.default() if args.plan_file is None \
                            else AnalysisPlanSet.from_par_file(args.plan_file)
        for p in analysisplan:
            bin_method = SpatiallyBinnedSpectra.define_method(p['bin_key'])
            sc_method = StellarContinuumModel.define_method(p['continuum_key'])
            el_method = EmissionLineModel.define_method(p['elfit_key'])
            daptypes += [
                defaults.dap_method(
                    bin_method['key'],
                    sc_method['fitpar']['template_library_key'],
                    el_method['continuum_tpl_key'])
            ]
    else:
        daptypes = [args.daptype]

    drpall_file = defaults.drpall_file(drpver=args.drpver,
                                       redux_path=redux_path)
    dapall_file = defaults.dapall_file(drpver=args.drpver,
                                       dapver=args.dapver,
                                       analysis_path=analysis_path)

    drpall_hdu = fits.open(drpall_file)
    dapall_hdu = fits.open(dapall_file)

    eml = channel_dictionary(dapall_hdu, 0, prefix='ELG')
    spi = channel_dictionary(dapall_hdu, 0, prefix='SPI')

    for daptype in daptypes:
        dapall_qa(drpall_hdu['MANGA'].data, dapall_hdu[daptype].data,
                  analysis_path, daptype, eml, spi)

    print('Elapsed time: {0} seconds'.format(time.perf_counter() - t))
コード例 #5
0
ファイル: ppxffit_qa.py プロジェクト: HSIYJND/mangadap
def main(args):
    t = time.perf_counter()

    if args.bgagg:
        pyplot.switch_backend('agg')

    # Get the DAP method types to plot
    analysisplan = AnalysisPlanSet.default() if args.plan_file is None \
                        else AnalysisPlanSet.from_par_file(args.plan_file)

    # Construct the plot for each analysis plan
    for plan in analysisplan:

        # Get the template library keyword
        tpl_renorm_file = args.template_flux_file
        if tpl_renorm_file is None:
            sc_method = StellarContinuumModel.define_method(
                plan['continuum_key'])
            tpl_key = sc_method['fitpar']['template_library_key']
            library = TemplateLibrary.define_library(tpl_key)
            library_root = os.path.split(library['file_search'])[0]
            tpl_renorm_file = os.path.join(
                library_root, '{0}_fluxes.db'.format(tpl_key.lower()))
            if not os.path.isfile(tpl_renorm_file):
                warnings.warn(
                    'Could not find file: {0}'.format(tpl_renorm_file))
                tpl_renorm_file = None

        tpl_flux_renorm = None if tpl_renorm_file is None \
                            else numpy.genfromtxt(tpl_renorm_file, dtype=float)[:,2]

        # Construct the plot
        ppxffit_qa_plot(args.plate,
                        args.ifudesign,
                        plan,
                        drpver=args.drpver,
                        redux_path=args.redux_path,
                        dapver=args.dapver,
                        analysis_path=args.analysis_path,
                        tpl_flux_renorm=tpl_flux_renorm)

    print('Elapsed time: {0} seconds'.format(time.perf_counter() - t))
コード例 #6
0
def generate_file_paths(obs,
                        analysisplan,
                        drpver=None,
                        redux_path=None,
                        dapver=None,
                        directory_path=None,
                        analysis_path=None):

    # Generate the paths to the MAPS and LOGCUBE files:
    bin_method = SpatiallyBinnedSpectra.define_method(analysisplan['bin_key'])
    sc_method = StellarContinuumModel.define_method(
        analysisplan['continuum_key'])
    el_method = EmissionLineModel.define_method(analysisplan['elfit_key'])
    method = defaults.dap_method(bin_method['key'],
                                 sc_method['fitpar']['template_library_key'],
                                 el_method['continuum_tpl_key'])
    directory_path = defaults.dap_method_path(method, plate=obs['plate'],
                                              ifudesign=obs['ifudesign'], drpver=drpver,
                                              dapver=dapver, analysis_path=analysis_path) \
                                if directory_path is None else str(directory_path)

    #-------------------------------------------------------------------
    # Read the maps to plot
    maps_file = os.path.join(
        directory_path,
        defaults.dap_file_name(obs['plate'],
                               obs['ifudesign'],
                               method,
                               mode='MAPS'))
    print('MAP file: {0}'.format(maps_file))
    model_file = os.path.join(
        directory_path,
        defaults.dap_file_name(obs['plate'],
                               obs['ifudesign'],
                               method,
                               mode='LOGCUBE'))
    print('LOGCUBE file: {0}'.format(model_file))

    return maps_file, model_file
コード例 #7
0
ファイル: ppxffit_qa.py プロジェクト: HSIYJND/mangadap
def maps_data(plt, ifu, plan, drpver, dapver, analysis_path):
    bin_method = SpatiallyBinnedSpectra.define_method(plan['bin_key'])
    sc_method = StellarContinuumModel.define_method(plan['continuum_key'])
    el_method = EmissionLineModel.define_method(plan['elfit_key'])
    method = defaults.dap_method(bin_method['key'],
                                 sc_method['fitpar']['template_library_key'],
                                 el_method['continuum_tpl_key'])
    directory_path = defaults.dap_method_path(method,
                                              plate=plt,
                                              ifudesign=ifu,
                                              drpver=drpver,
                                              dapver=dapver,
                                              analysis_path=analysis_path)
    maps_file = defaults.dap_file_name(plt, ifu, method, mode='MAPS')

    with fits.open(os.path.join(directory_path, maps_file)) as hdu:

        mask = hdu['BINID'].data[1, :, :] < 0
        r68_map = numpy.ma.MaskedArray(hdu['STELLAR_FOM'].data[3, :, :],
                                       mask=mask)
        r99_map = numpy.ma.MaskedArray(hdu['STELLAR_FOM'].data[4, :, :],
                                       mask=mask)
        rchi2_map = numpy.ma.MaskedArray(hdu['STELLAR_FOM'].data[2, :, :],
                                         mask=mask)
        svel_map = numpy.ma.MaskedArray(hdu['STELLAR_VEL'].data[:, :],
                                        mask=mask)
        ssigo_map = numpy.ma.MaskedArray(hdu['STELLAR_SIGMA'].data[:, :],
                                         mask=mask)
        ssigcor_map = numpy.ma.MaskedArray(
            hdu['STELLAR_SIGMACORR'].data[1, :, :], mask=mask)
        ssigc_map = numpy.ma.sqrt(
            numpy.square(ssigo_map) - numpy.square(ssigcor_map))

        extent = map_extent(hdu, 'SPX_MFLUX')

    return r68_map, r99_map, rchi2_map, svel_map, ssigo_map, ssigcor_map, ssigc_map, extent
コード例 #8
0
def test_moments_with_continuum():
    # Read the data
    specfile = data_test_file('MaNGA_test_spectra.fits.gz')
    hdu = fits.open(specfile)
    drpbm = DRPFitsBitMask()
    flux = numpy.ma.MaskedArray(hdu['FLUX'].data,
                                mask=drpbm.flagged(
                                    hdu['MASK'].data,
                                    MaNGADataCube.do_not_fit_flags()))
    ferr = numpy.ma.power(hdu['IVAR'].data, -0.5)
    flux[ferr.mask] = numpy.ma.masked
    ferr[flux.mask] = numpy.ma.masked
    nspec = flux.shape[0]

    # Instantiate the template libary
    velscale_ratio = 4
    tpl = TemplateLibrary('MILESHC',
                          match_resolution=False,
                          velscale_ratio=velscale_ratio,
                          spectral_step=1e-4,
                          log=True,
                          hardcopy=False)
    tpl_sres = numpy.mean(tpl['SPECRES'].data, axis=0)

    # Get the pixel mask
    pixelmask = SpectralPixelMask(artdb=ArtifactDB.from_key('BADSKY'),
                                  emldb=EmissionLineDB.from_key('ELPSCMSK'))

    # Instantiate the fitting class
    ppxf = PPXFFit(StellarContinuumModelBitMask())

    # Perform the fit
    fit_wave, fit_flux, fit_mask, fit_par \
        = ppxf.fit(tpl['WAVE'].data.copy(), tpl['FLUX'].data.copy(), hdu['WAVE'].data, flux, ferr,
                   hdu['Z'].data, numpy.full(nspec, 100.), iteration_mode='no_global_wrej',
                   reject_boxcar=100, ensemble=False, velscale_ratio=velscale_ratio,
                   mask=pixelmask, matched_resolution=False, tpl_sres=tpl_sres,
                   obj_sres=hdu['SRES'].data, degree=8, moments=2)

    # Remask the continuum fit
    sc_continuum = StellarContinuumModel.reset_continuum_mask_window(
        numpy.ma.MaskedArray(fit_flux, mask=fit_mask > 0))

    # Read the database that define the emission lines and passbands
    momdb = EmissionMomentsDB.from_key('ELBMILES')

    # Measure the moments
    elmombm = EmissionLineMomentsBitMask()
    elmom = EmissionLineMoments.measure_moments(momdb,
                                                hdu['WAVE'].data,
                                                flux,
                                                continuum=sc_continuum,
                                                redshift=hdu['Z'].data,
                                                bitmask=elmombm)

    # Measure the EW based on the moments
    include_band = numpy.array([numpy.invert(momdb.dummy)]*nspec) \
                        & numpy.invert(elmombm.flagged(elmom['MASK'],
                                                       flag=['BLUE_EMPTY', 'RED_EMPTY']))
    line_center = (1.0 + hdu['Z'].data)[:, None] * momdb['restwave'][None, :]
    elmom['BMED'], elmom['RMED'], pos, elmom['EWCONT'], elmom['EW'], elmom['EWERR'] \
            = emission_line_equivalent_width(hdu['WAVE'].data, flux, momdb['blueside'],
                                             momdb['redside'], line_center, elmom['FLUX'],
                                             redshift=hdu['Z'].data,
                                             line_flux_err=elmom['FLUXERR'],
                                             include_band=include_band)

    # Check the flags
    reference = {
        'BLUE_INCOMP': 21,
        'MAIN_JUMP': 0,
        'UNDEFINED_MOM2': 42,
        'JUMP_BTWN_SIDEBANDS': 0,
        'RED_JUMP': 0,
        'DIVBYZERO': 0,
        'NO_ABSORPTION_CORRECTION': 0,
        'RED_EMPTY': 21,
        'UNDEFINED_BANDS': 8,
        'DIDNOTUSE': 0,
        'UNDEFINED_MOM1': 0,
        'FORESTAR': 0,
        'NON_POSITIVE_CONTINUUM': 0,
        'LOW_SNR': 0,
        'MAIN_EMPTY': 21,
        'BLUE_JUMP': 0,
        'RED_INCOMP': 21,
        'MAIN_INCOMP': 21,
        'BLUE_EMPTY': 21
    }
    assert numpy.all([
        reference[k] == numpy.sum(elmombm.flagged(elmom['MASK'], flag=k))
        for k in elmombm.keys()
    ]), 'Number of flagged measurements changed'

    # Check that the values are finite
    assert numpy.all([ numpy.all(numpy.isfinite(elmom[n])) for n in elmom.dtype.names]), \
                        'Found non-finite values in output'

    # Check the band definitions
    assert numpy.all(numpy.equal(elmom['REDSHIFT'],
                                 hdu['Z'].data)), 'Redshift changed'
    assert numpy.all(numpy.isclose(numpy.mean(momdb['blueside'], axis=1)[None,:],
                                   elmom['BCEN']/(1+hdu['Z'].data[:,None]))
                        | elmombm.flagged(elmom['MASK'], flag='UNDEFINED_BANDS')), \
                'Blue passband center incorrect'
    assert numpy.all(numpy.isclose(numpy.mean(momdb['redside'], axis=1)[None,:],
                                   elmom['RCEN']/(1+hdu['Z'].data[:,None]))
                        | elmombm.flagged(elmom['MASK'], flag='UNDEFINED_BANDS')), \
                'Red passband center incorrect'

    # Check the values
    assert numpy.all(
        numpy.absolute(elmom['FLUX'][0] - numpy.array([
            0.63, 0.00, 0.22, -1.32, -0.88, -0.68, -0.44, -0.13, -1.14, -0.07,
            -0.11, 0.01, 0.38, 0.73, 0.71, 0.44, 0.08, 0.74, 1.30, 2.34, 0.55,
            0.44
        ])) < 0.01), 'Fluxes too different'

    assert numpy.all(numpy.absolute(elmom['MOM1'][0] -
                        numpy.array([ 14682.6,      0.0, 14843.2, 14865.8, 14890.4, 14404.7,
                                      14208.6,  12376.0, 14662.5, 14148.5, 15804.1, 17948.4,
                                      14874.5,  14774.9, 14840.5, 14746.0, 15093.1, 14857.8,
                                      14839.0,  14840.2, 14876.0, 14859.5])) < 0.1), \
                    '1st moments too different'

    assert numpy.all(numpy.absolute(elmom['MOM2'][0] -
                        numpy.array([322.2,   0.0, 591.4, 436.4, 474.6,   0.0,   0.0,   0.0,
                                     364.6,   0.0,   0.0,   0.0, 289.1, 226.9, 282.6, 283.8,
                                     227.0, 207.7, 207.7, 253.6, 197.0, 212.4])) < 0.1), \
                    '2nd moments too different'

    assert numpy.all(numpy.absolute(elmom['EW'][0] -
                        numpy.array([ 0.63,  0.00,  0.20, -1.28, -0.76, -0.54, -0.30, -0.09,
                                     -0.61, -0.03, -0.04,  0.00,  0.13,  0.25,  0.24,  0.13,
                                      0.02,  0.22,  0.38,  0.69,  0.17,  0.13])) < 0.01), \
                    'EW too different'
コード例 #9
0
    # Perform the fit
    cont_wave, cont_flux, cont_mask, cont_par \
        = ppxf.fit(sc_tpl['WAVE'].data.copy(), sc_tpl['FLUX'].data.copy(), wave, flux, ferr,
                   z, dispersion, iteration_mode='no_global_wrej', reject_boxcar=100,
                   ensemble=False, velscale_ratio=velscale_ratio, mask=sc_pixel_mask,
                   matched_resolution=False, tpl_sres=sc_tpl_sres, obj_sres=sres, degree=8,
                   moments=2, plot=False)

    # How many templates did it find:
    print(sc_tpl.ntpl)
    # From what files:
    print(sc_tpl.file_list)
    # What were the weights assigned to each template
    print(cont_par['TPLWGT'][0, :])

    # Remask the continuum fit
    sc_continuum = StellarContinuumModel.reset_continuum_mask_window(
        numpy.ma.MaskedArray(cont_flux, mask=cont_mask > 0))

    # Show the fit and residual
    pyplot.plot(wave, flux[0, :], label='Data')
    pyplot.plot(wave, sc_continuum[0, :], label='Model')
    pyplot.plot(wave, flux[0, :] - sc_continuum[0, :], label='Resid')
    pyplot.legend()
    pyplot.xlabel('Wavelength')
    pyplot.ylabel('Flux')
    pyplot.show()
    #-------------------------------------------------------------------

    print('Elapsed time: {0} seconds'.format(time.perf_counter() - t))
コード例 #10
0
    clobber = False
    
    # Read the DRP LOGCUBE file
    print('Reading DRP fits file.')
    drpf = DRPFits(plate, ifu, 'CUBE', read=True, redux_path=redux_path)

    # Calculate the S/N and coordinates
    rdxqa = ReductionAssessment('SNRG', drpf, clobber=clobber, analysis_path=analysis_path)

    # Peform the Voronoi binning to S/N>~10
    binned_spectra = SpatiallyBinnedSpectra('VOR10', drpf, rdxqa, clobber=clobber,
                                            analysis_path=analysis_path)

    # Fit the stellar kinematics
    stellar_continuum = StellarContinuumModel('GAU-MILESHC', binned_spectra, clobber=clobber,
                                              guess_vel=vel, guess_sig=100.,
                                              analysis_path=analysis_path)

    # Get the emission-line moments
    emission_line_moments = EmissionLineMoments('EMOMF', binned_spectra, clobber=clobber,
                                                stellar_continuum=stellar_continuum,
                                                redshift=nsa_redshift,
                                                analysis_path=analysis_path)

    # Get an estimate of the redshift of each bin using the first moment
    # of the H-alpha emission line:
    el_init_redshift = numpy.full(binned_spectra.nbins, nsa_redshift, dtype=float)
    # HARDCODED FOR A SPECIFIC EMISSION-LINE MOMENT DATABASE
    # TODO: Should
    #   - pass the EmissionLineMoments object to EmissionLineModel
    #   - include the channel used for this in EmissionLineModelDef
コード例 #11
0
ファイル: ppxffit_qa.py プロジェクト: HSIYJND/mangadap
def ppxffit_qa_plot(plt,
                    ifu,
                    plan,
                    drpver=None,
                    redux_path=None,
                    dapver=None,
                    analysis_path=None,
                    tpl_flux_renorm=None):

    # Set the redux and DRP directory paths
    _drpver = defaults.drp_version() if drpver is None else drpver
    _redux_path = defaults.drp_redux_path(
        drpver=_drpver) if redux_path is None else redux_path
    if not os.path.isdir(_redux_path):
        raise NotADirectoryError('{0} is not a directory.'.format(_redux_path))

    # Set the analysis path
    _dapver = defaults.dap_version() if dapver is None else dapver
    _analysis_path = defaults.dap_analysis_path(drpver=_drpver, dapver=_dapver) \
                            if analysis_path is None else analysis_path
    if not os.path.isdir(_analysis_path):
        raise NotADirectoryError(
            '{0} is not a directory.'.format(_analysis_path))

    # Get the method, it's root directory, and the qa directories
    bin_method = SpatiallyBinnedSpectra.define_method(plan['bin_key'])
    sc_method = StellarContinuumModel.define_method(plan['continuum_key'])
    el_method = EmissionLineModel.define_method(plan['elfit_key'])
    method = defaults.dap_method(bin_method['key'],
                                 sc_method['fitpar']['template_library_key'],
                                 el_method['continuum_tpl_key'])
    method_dir = defaults.dap_method_path(method,
                                          plate=plt,
                                          ifudesign=ifu,
                                          drpver=_drpver,
                                          dapver=_dapver,
                                          analysis_path=_analysis_path)
    method_qa_dir = defaults.dap_method_path(method,
                                             plate=plt,
                                             ifudesign=ifu,
                                             qa=True,
                                             drpver=_drpver,
                                             dapver=_dapver,
                                             analysis_path=_analysis_path)

    # Check that the paths exists
    if not os.path.isdir(method_dir):
        raise NotADirectoryError(
            '{0} is not a directory; run the DAP first!'.format(method_dir))
    if not os.path.isdir(method_qa_dir):
        os.makedirs(method_qa_dir)

    # Get the name of the output file
    ofile = os.path.join(
        method_qa_dir,
        'manga-{0}-{1}-MAPS-{2}-ppxffit.png'.format(plt, ifu, method))

    # Get the g-r map
    gmr_map = gmr_data(plt, ifu, _drpver, _redux_path)

    # Get the reduction assessment data
    signal_map, snr_map = rdxqa_data(plt, ifu, plan, _drpver, _dapver,
                                     _analysis_path)

    # Get the template weights and additive-polynomial coefficients
    binid_map, t, dt, tn, dtn, a, da, an, dan \
            = continuum_component_data(plt, ifu, plan, _drpver, _dapver, _analysis_path,
                                       signal_map=signal_map, tpl_flux_renorm=tpl_flux_renorm)

    #    print('t:', numpy.sum(t > 0), numpy.prod(t.shape))
    #    print('dt:', numpy.sum(dt > 0), numpy.prod(dt.shape))
    #    print('tn:', numpy.sum(tn > 0), numpy.prod(tn.shape))
    #    print('dtn:', numpy.sum(dtn > 0), numpy.prod(dtn.shape))

    #    print('a:', numpy.sum(a > 0), numpy.prod(a.shape))
    #    print('da:', numpy.sum(da > 0), numpy.prod(da.shape))
    #    print('an:', numpy.sum(an > 0), numpy.prod(an.shape))
    #    print('dan:', numpy.sum(dan > 0), numpy.prod(dan.shape))

    # Map the continuum component data
    t_map = DAPFitsUtil.reconstruct_map(binid_map.shape,
                                        binid_map.ravel(),
                                        t,
                                        quiet=True)
    t_map = numpy.ma.MaskedArray(t_map, mask=numpy.invert(t_map > 0))

    dt_map = DAPFitsUtil.reconstruct_map(binid_map.shape,
                                         binid_map.ravel(),
                                         dt,
                                         quiet=True)
    dt_map = numpy.ma.MaskedArray(dt_map,
                                  mask=numpy.invert(dt_map > 0))  #/t_map

    tn_map = DAPFitsUtil.reconstruct_map(binid_map.shape,
                                         binid_map.ravel(),
                                         tn,
                                         quiet=True)
    tn_map = numpy.ma.MaskedArray(tn_map, mask=numpy.invert(tn_map > 0))

    dtn_map = DAPFitsUtil.reconstruct_map(binid_map.shape,
                                          binid_map.ravel(),
                                          dtn,
                                          quiet=True)
    dtn_map = numpy.ma.MaskedArray(dtn_map,
                                   mask=numpy.invert(dtn_map > 0))  #/tn_map

    a_map = DAPFitsUtil.reconstruct_map(binid_map.shape,
                                        binid_map.ravel(),
                                        a,
                                        quiet=True)
    a_map = numpy.ma.MaskedArray(a_map, mask=numpy.invert(a_map > 0))

    da_map = DAPFitsUtil.reconstruct_map(binid_map.shape,
                                         binid_map.ravel(),
                                         da,
                                         quiet=True)
    da_map = numpy.ma.MaskedArray(da_map,
                                  mask=numpy.invert(da_map > 0))  #/a_map

    an_map = DAPFitsUtil.reconstruct_map(binid_map.shape,
                                         binid_map.ravel(),
                                         an,
                                         quiet=True)
    an_map = numpy.ma.MaskedArray(an_map, mask=numpy.invert(an_map > 0))

    dan_map = DAPFitsUtil.reconstruct_map(binid_map.shape,
                                          binid_map.ravel(),
                                          dan,
                                          quiet=True)
    dan_map = numpy.ma.MaskedArray(dan_map,
                                   mask=numpy.invert(dan_map > 0))  #/an_map

    # Get the remaining output maps from the MAPS file
    r68_map, r99_map, rchi2_map, svel_map, ssigo_map, ssigcor_map, ssigc_map, extent \
            = maps_data(plt, ifu, plan, _drpver, _dapver, _analysis_path)

    #    if not os.path.isfile(ofile):
    stellar_continuum_maps(plt,
                           ifu,
                           method,
                           snr_map,
                           r68_map,
                           r99_map,
                           rchi2_map,
                           signal_map,
                           a_map,
                           da_map,
                           an_map,
                           dan_map,
                           gmr_map,
                           t_map,
                           dt_map,
                           tn_map,
                           dtn_map,
                           svel_map,
                           ssigo_map,
                           ssigcor_map,
                           ssigc_map,
                           extent=extent,
                           ofile=ofile)
コード例 #12
0
ファイル: ppxffit_qa.py プロジェクト: HSIYJND/mangadap
def continuum_component_data(plt,
                             ifu,
                             plan,
                             drpver,
                             dapver,
                             analysis_path,
                             signal_map=None,
                             tpl_flux_renorm=None):
    # Get the coefficient data from the StellarContinuumModel object
    sc_file = os.path.join(
        *StellarContinuumModel.default_paths(plt,
                                             ifu,
                                             plan['drpqa_key'],
                                             plan['bin_key'],
                                             plan['continuum_key'],
                                             drpver=drpver,
                                             dapver=dapver,
                                             analysis_path=analysis_path))
    hdu = fits.open(sc_file)
    # This only has the bins with stellar continuum measurements
    binid_map = hdu['BINID'].data.copy()

    if signal_map is None:
        signal = numpy.ones(hdu['PAR'].data['BINID_INDEX'].size, dtype=float)
    else:
        # Find the unique indices in the map with valid bins
        unique, unique_indx = numpy.unique(binid_map.ravel(),
                                           return_index=True)
        unique_indx = unique_indx[1:]
        # .. and pull these out of the signal map
        signal = signal_map.ravel()[unique_indx]


#    print(hdu['PAR'].data['TPLWGT'].shape)
    w = hdu['PAR'].data['TPLWGT'].copy()
    if tpl_flux_renorm is not None:
        w /= tpl_flux_renorm[None, :]
    wn = w / signal[:, None]
    #    t = numpy.sqrt(numpy.sum(numpy.square(w), axis=1))
    t = numpy.sum(numpy.absolute(w), axis=1)
    tn = numpy.sum(numpy.absolute(wn), axis=1)
    #    dtw = numpy.median(w / numpy.sum(w, axis=1)[:,None], axis=0)
    dtw = numpy.ones(w.shape[1], dtype=float)
    #    dtnw = numpy.median(wn / numpy.sum(wn, axis=1)[:,None], axis=0)
    dtnw = numpy.ones(w.shape[1], dtype=float)
    dt = numpy.ma.sqrt(
        numpy.sum(dtw[None, :] *
                  numpy.square(w - numpy.ma.median(w, axis=0)[None, :]),
                  axis=1) / numpy.sum(dtw)).filled(0.0)
    dtn = numpy.ma.sqrt(
        numpy.sum(dtnw[None, :] *
                  numpy.square(wn - numpy.ma.median(wn, axis=0)[None, :]),
                  axis=1) / numpy.sum(dtnw)).filled(0.0)

    w = hdu['PAR'].data['ADDCOEF'].copy()
    wn = w / signal[:, None]
    #    a = numpy.sqrt(numpy.sum(numpy.square(w), axis=1))
    a = numpy.sum(numpy.absolute(w), axis=1)
    an = numpy.sum(numpy.absolute(wn), axis=1)
    #    daw = numpy.median(numpy.absolute(w)
    #                        / numpy.sum(numpy.absolute(w), axis=1)[:,None], axis=0)
    daw = numpy.ones(w.shape[1], dtype=float)
    #    danw = numpy.median(numpy.absolute(wn)
    #                        / numpy.sum(numpy.absolute(wn), axis=1)[:,None], axis=0)
    danw = numpy.ones(w.shape[1], dtype=float)
    da = numpy.ma.sqrt(
        numpy.sum(daw[None, :] *
                  numpy.square(w - numpy.ma.median(w, axis=0)[None, :]),
                  axis=1) / numpy.sum(daw)).filled(0.0)
    dan = numpy.ma.sqrt(
        numpy.sum(danw[None, :] *
                  numpy.square(wn - numpy.ma.median(wn, axis=0)[None, :]),
                  axis=1) / numpy.sum(danw)).filled(0.0)

    hdu.close()
    del hdu

    return binid_map, t, dt, tn, dtn, a, da, an, dan
コード例 #13
0
ファイル: fit_selected_spectra.py プロジェクト: sdss/mangadap
def main():
    t = time.perf_counter()
    arg = parse_args()
    if not os.path.isfile(arg.inp):
        raise FileNotFoundError('No file: {0}'.format(arg.inp))
    directory_path = os.getcwd(
    ) if arg.output_root is None else os.path.abspath(arg.output_root)
    if not os.path.isdir(directory_path):
        os.makedirs(directory_path)

    data_file = os.path.abspath(arg.inp)
    fit_file = os.path.join(directory_path, arg.out)
    flag_db = None if arg.spec_flags is None else os.path.abspath(
        arg.spec_flags)

    # Read the data
    spectral_step = 1e-4
    wave, flux, ferr, sres, redshift, fit_spectrum = object_data(
        data_file, flag_db)
    nspec, npix = flux.shape
    dispersion = numpy.full(nspec, 100., dtype=numpy.float)

    #    fit_spectrum[:] = False
    #    fit_spectrum[0] = True
    #    fit_spectrum[171] = True
    #    fit_spectrum[791] = True

    # Mask spectra that should not be fit
    indx = numpy.any(numpy.logical_not(numpy.ma.getmaskarray(flux)),
                     axis=1) & fit_spectrum
    flux[numpy.logical_not(indx), :] = numpy.ma.masked

    print('Read: {0}'.format(arg.inp))
    print('Contains {0} spectra'.format(nspec))
    print(' each with {0} pixels'.format(npix))
    print('Fitting {0} spectra.'.format(numpy.sum(fit_spectrum)))

    #-------------------------------------------------------------------
    #-------------------------------------------------------------------
    # Fit the stellar continuum

    # Construct the template library
    sc_tpl = TemplateLibrary(arg.sc_tpl,
                             match_resolution=False,
                             velscale_ratio=arg.sc_vsr,
                             spectral_step=spectral_step,
                             log=True,
                             hardcopy=False)
    # Set the spectral resolution
    sc_tpl_sres = numpy.mean(sc_tpl['SPECRES'].data, axis=0).ravel()
    # Set the pixel mask
    sc_pixel_mask = SpectralPixelMask(artdb=ArtifactDB.from_key('BADSKY'),
                                      emldb=EmissionLineDB.from_key('ELPMPL8'))
    # Instantiate the fitting class
    ppxf = PPXFFit(StellarContinuumModelBitMask())

    # The following call performs the fit to the spectrum. Specifically
    # note that the code only fits the first two moments, uses an
    # 8th-order additive polynomial, and uses the 'no_global_wrej'
    # iteration mode. See
    # https://sdss-mangadap.readthedocs.io/en/latest/api/mangadap.proc.ppxffit.html#mangadap.proc.ppxffit.PPXFFit.fit
    cont_wave, cont_flux, cont_mask, cont_par \
        = ppxf.fit(sc_tpl['WAVE'].data.copy(), sc_tpl['FLUX'].data.copy(), wave, flux, ferr,
                   redshift, dispersion, iteration_mode='no_global_wrej', reject_boxcar=100,
                   ensemble=False, velscale_ratio=arg.sc_vsr, mask=sc_pixel_mask,
                   matched_resolution=False, tpl_sres=sc_tpl_sres, obj_sres=sres,
                   degree=arg.sc_deg, moments=2) #, plot=True)

    if arg.sc_only:
        write(fit_file, wave, cont_flux, cont_mask, cont_par)
        print('Elapsed time: {0} seconds'.format(time.perf_counter() - t))
        return

#    if numpy.any(cont_par['KIN'][:,1] < 0):
#        embed()
#        exit()
#-------------------------------------------------------------------

#-------------------------------------------------------------------
#-------------------------------------------------------------------
# Measure the emission-line moments

#    # Remask the continuum fit
#    sc_continuum = StellarContinuumModel.reset_continuum_mask_window(
#                        numpy.ma.MaskedArray(cont_flux, mask=cont_mask>0))
#    # Read the database that define the emission lines and passbands
#    momdb = EmissionMomentsDB.from_key(arg.el_band)
#    # Measure the moments
#    elmom = EmissionLineMoments.measure_moments(momdb, wave, flux, continuum=sc_continuum,
#                                                redshift=redshift)
#-------------------------------------------------------------------

#-------------------------------------------------------------------
# Fit the emission-line model

# Set the emission-line continuum templates if different from those
# used for the stellar continuum
    if arg.sc_tpl == arg.el_tpl:
        # If the keywords are the same, just copy over the previous
        # library and the best fitting stellar kinematics
        el_tpl = sc_tpl
        el_tpl_sres = sc_tpl_sres
        stellar_kinematics = cont_par['KIN'].copy()
    else:
        # If the template sets are different, we need to match the
        # spectral resolution to the galaxy data and use the corrected
        # velocity dispersions.
        _sres = SpectralResolution(wave, sres[0, :], log10=True)
        el_tpl = TemplateLibrary(arg.el_tpl,
                                 sres=_sres,
                                 velscale_ratio=arg.el_vsr,
                                 spectral_step=spectral_step,
                                 log=True,
                                 hardcopy=False)
        el_tpl_sres = numpy.mean(el_tpl['SPECRES'].data, axis=0).ravel()
        stellar_kinematics = cont_par['KIN'].copy()
        stellar_kinematics[:, 1] = numpy.ma.sqrt(
            numpy.square(cont_par['KIN'][:, 1]) -
            numpy.square(cont_par['SIGMACORR_SRES'])).filled(0.0)


#    if numpy.any(cont_par['KIN'][:,1] < 0):
#        embed()
#        exit()
#
#    if numpy.any(stellar_kinematics[:,1] < 0):
#        embed()
#        exit()

# Mask the 5577 sky line
    el_pixel_mask = SpectralPixelMask(artdb=ArtifactDB.from_key('BADSKY'))

    # Read the emission line fitting database
    emldb = EmissionLineDB.from_key(arg.el_list)

    # Instantiate the fitting class
    emlfit = Sasuke(EmissionLineModelBitMask())

    # TODO: Improve the initial velocity guess using the first moment...

    # Perform the fit
    elfit_time = time.perf_counter()
    model_wave, model_flux, eml_flux, model_mask, eml_fit_par, eml_eml_par \
            = emlfit.fit(emldb, wave, flux, obj_ferr=ferr, obj_mask=el_pixel_mask, obj_sres=sres,
                         guess_redshift=redshift, guess_dispersion=dispersion, reject_boxcar=101,
                         stpl_wave=el_tpl['WAVE'].data, stpl_flux=el_tpl['FLUX'].data,
                         stpl_sres=el_tpl_sres, stellar_kinematics=stellar_kinematics,
                         etpl_sinst_mode='offset', etpl_sinst_min=10., velscale_ratio=arg.el_vsr,
                         matched_resolution=False, mdegree=arg.el_deg, ensemble=False)#, plot=True)
    print('EML FIT TIME: ', time.perf_counter() - elfit_time)

    # Line-fit metrics (should this be done in the fit method?)
    eml_eml_par = EmissionLineFit.line_metrics(emldb,
                                               wave,
                                               flux,
                                               ferr,
                                               model_flux,
                                               eml_eml_par,
                                               model_mask=model_mask,
                                               bitmask=emlfit.bitmask)

    # Equivalent widths
    EmissionLineFit.measure_equivalent_width(wave,
                                             flux,
                                             emldb,
                                             eml_eml_par,
                                             bitmask=emlfit.bitmask,
                                             checkdb=False)

    # Measure the emission-line moments
    #   - Model continuum
    continuum = StellarContinuumModel.reset_continuum_mask_window(model_flux -
                                                                  eml_flux)
    #   - Updated redshifts
    fit_redshift = eml_eml_par['KIN'][:,numpy.where(emldb['name'] == 'Ha')[0][0],0] \
                        / astropy.constants.c.to('km/s').value
    #   - Set the moment database
    momdb = EmissionMomentsDB.from_key(arg.el_band)
    #   - Set the moment bitmask
    mombm = EmissionLineMomentsBitMask()
    #   - Measure the moments
    elmom = EmissionLineMoments.measure_moments(momdb,
                                                wave,
                                                flux,
                                                ivar=numpy.ma.power(ferr, -2),
                                                continuum=continuum,
                                                redshift=fit_redshift,
                                                bitmask=mombm)
    #   - Select the bands that are valid
    include_band = numpy.array([numpy.logical_not(momdb.dummy)]*nspec) \
                        & numpy.logical_not(mombm.flagged(elmom['MASK'],
                                                          flag=['BLUE_EMPTY', 'RED_EMPTY']))
    #   - Set the line center at the center of the primary passband
    line_center = (1.0 + fit_redshift)[:, None] * momdb['restwave'][None, :]
    elmom['BMED'], elmom['RMED'], pos, elmom['EWCONT'], elmom['EW'], elmom['EWERR'] \
            = emission_line_equivalent_width(wave, flux, momdb['blueside'], momdb['redside'],
                                             line_center, elmom['FLUX'], redshift=fit_redshift,
                                             line_flux_err=elmom['FLUXERR'],
                                             include_band=include_band)
    #   - Flag non-positive measurements
    indx = include_band & numpy.logical_not(pos)
    elmom['MASK'][indx] = mombm.turn_on(elmom['MASK'][indx],
                                        'NON_POSITIVE_CONTINUUM')
    #   - Set the binids
    elmom['BINID'] = numpy.arange(nspec)
    elmom['BINID_INDEX'] = numpy.arange(nspec)

    write(fit_file,
          wave,
          cont_flux,
          cont_mask,
          cont_par,
          model_flux=model_flux,
          model_mask=model_mask,
          eml_flux=eml_flux,
          eml_fit_par=eml_fit_par,
          eml_eml_par=eml_eml_par,
          elmom=elmom)
    print('Elapsed time: {0} seconds'.format(time.perf_counter() - t))
コード例 #14
0
def main():

    t = time.perf_counter()

    #-------------------------------------------------------------------
    # Read spectra to fit. The following reads a single MaNGA spectrum.
    # This is where you should read in your own spectrum to fit.
    # Plate-IFU to use
    plt = 7815
    ifu = 3702
    # Spaxel coordinates
    x = 25 #30
    y = 25 #37
    # Where to find the relevant datacube.  This example accesses the test data
    # that can be downloaded by executing the script here:
    # https://github.com/sdss/mangadap/blob/master/download_test_data.py
    directory_path = defaults.dap_source_dir() / 'data' / 'remote'
    # Read a spectrum
    wave, flux, ivar, sres = get_spectra(plt, ifu, x, y, directory_path=directory_path)
    # In general, the DAP fitting functions expect data to be in 2D
    # arrays with shape (N-spectra,N-wave). So if you only have one
    # spectrum, you need to expand the dimensions:
    flux = flux.reshape(1,-1)
    ivar = ivar.reshape(1,-1)
    ferr = numpy.ma.power(ivar, -0.5)
    sres = sres.reshape(1,-1)

    # The majority (if not all) of the DAP methods expect that your
    # spectra are binned logarithmically in wavelength (primarily
    # because this is what pPXF expects). You can either have the DAP
    # function determine this value (commented line below) or set it
    # directly. The value is used to resample the template spectra to
    # match the sampling of the spectra to fit (up to some integer; see
    # velscale_ratio).
#    spectral_step = spectral_coordinate_step(wave, log=True)
    spectral_step = 1e-4

    # Hereafter, the methods expect a wavelength vector, a flux array
    # with the spectra to fit, an ferr array with the 1-sigma errors in
    # the flux, and sres with the wavelength-dependent spectral
    # resolution, R = lambda / Dlambda
    #-------------------------------------------------------------------

    #-------------------------------------------------------------------
    # The DAP needs a reasonable guess of the redshift of the spectrum
    # (within +/- 2000 km/s). In this example, I'm pulling the redshift
    # from the DRPall file. There must be one redshift estimate per
    # spectrum to fit.  Here that means it's a single element array
    # This example accesses the test data
    # that can be downloaded by executing the script here:
    # https://github.com/sdss/mangadap/blob/master/download_test_data.py
    drpall_file = directory_path / f'drpall-{drp_test_version}.fits'
    z = numpy.array([get_redshift(plt, ifu, drpall_file)])
    print('Redshift: {0}'.format(z[0]))
    # The DAP also requires an initial guess for the velocity
    # dispersion. A guess of 100 km/s is usually robust, but this may
    # depend on your spectral resolution.
    dispersion = numpy.array([100.])
    #-------------------------------------------------------------------

    #-------------------------------------------------------------------
    # The following sets the keyword for the template spectra to use
    # during the fit. You can specify different template sets to use
    # during the stellar-continuum (stellar kinematics) fit and the
    # emission-line modeling.

    # Templates used in the stellar continuum fits
    sc_tpl_key = 'MILESHC'
    # Templates used in the emission-line modeling
    el_tpl_key = 'MASTARSSP'

    # You also need to specify the sampling for the template spectra.
    # The templates must be sampled with the same pixel step as the
    # spectra to be fit, up to an integer factor. The critical thing
    # for the sampling is that you do not want to undersample the
    # spectral resolution element of the template spectra. Here, I set
    # the sampling for the MILES templates to be a factor of 4 smaller
    # than the MaNGA spectrum to be fit (which is a bit of overkill
    # given the resolution difference). I set the sampling of the
    # MaStar templates to be the same as the galaxy data.

    # Template pixel scale a factor of 4 smaller than galaxy data
    sc_velscale_ratio = 4
    # Template sampling is the same as the galaxy data
    el_velscale_ratio = 1

    # You then need to identify the database that defines the
    # emission-line passbands (elmom_key) for the non-parametric
    # emission-line moment calculations, and the emission-line
    # parameters (elfit_key) for the Gaussian emission-line modeling.
    # See
    # https://sdss-mangadap.readthedocs.io/en/latest/emissionlines.html.
    elmom_key = 'ELBMPL9'
    elfit_key = 'ELPMPL11'

    # If you want to also calculate the spectral indices, you can
    # provide a keyword that indicates the database with the passband
    # definitions for both the absorption-line and bandhead/color
    # indices to measure. The script allows these to be None, if you
    # don't want to calculate the spectral indices. See
    # https://sdss-mangadap.readthedocs.io/en/latest/spectralindices.html
    absindx_key = 'EXTINDX'
    bhdindx_key = 'BHBASIC'

    # Now we want to construct a pixel mask that excludes regions with
    # known artifacts and emission lines. The 'BADSKY' artifact
    # database only masks the 5577, which can have strong left-over
    # residuals after sky-subtraction. The list of emission lines (set
    # by the ELPMPL8 keyword) can be different from the list of
    # emission lines fit below.
    sc_pixel_mask = SpectralPixelMask(artdb=ArtifactDB.from_key('BADSKY'),
                                      emldb=EmissionLineDB.from_key('ELPMPL11'))
    # Mask the 5577 sky line
    el_pixel_mask = SpectralPixelMask(artdb=ArtifactDB.from_key('BADSKY'))

    # Finally, you can set whether or not to show a set of plots.
    #
    # Show the ppxf-generated plots for each fit stage.
    fit_plots = False
    # Show summary plots
    usr_plots = True
    #-------------------------------------------------------------------


    #-------------------------------------------------------------------
    # Fit the stellar continuum

    # First, we construct the template library. The keyword that
    # selects the template library (sc_tpl_key) is defined above. The
    # following call reads in the template library and processes the
    # data to have the appropriate pixel sampling. Note that *no*
    # matching of the spectral resolution to the galaxy spectrum is
    # performed.
    sc_tpl = TemplateLibrary(sc_tpl_key, match_resolution=False, velscale_ratio=sc_velscale_ratio,
                             spectral_step=spectral_step, log=True, hardcopy=False)

    # This calculation of the mean spectral resolution is a kludge. The
    # template library should provide spectra that are *all* at the
    # same spectral resolution. Otherwise, one cannot freely combine
    # the spectra to fit the Doppler broadening of the galaxy spectrum
    # in a robust (constrained) way (without substantially more
    # effort). There should be no difference between what's done below
    # and simply taking the spectral resolution to be that of the first
    # template spectrum (i.e., sc_tpl['SPECRES'].data[0])
    sc_tpl_sres = numpy.mean(sc_tpl['SPECRES'].data, axis=0).ravel()

    # Instantiate the fitting class, including the mask that it should
    # use to flag the data. [[This mask should just be default...]]
    ppxf = PPXFFit(StellarContinuumModelBitMask())

    # The following call performs the fit to the spectrum. Specifically
    # note that the code only fits the first two moments, uses an
    # 8th-order additive polynomial, and uses the 'no_global_wrej'
    # iteration mode. See
    # https://sdss-mangadap.readthedocs.io/en/latest/api/mangadap.proc.ppxffit.html#mangadap.proc.ppxffit.PPXFFit.fit
    cont_wave, cont_flux, cont_mask, cont_par \
        = ppxf.fit(sc_tpl['WAVE'].data.copy(), sc_tpl['FLUX'].data.copy(), wave, flux, ferr,
                   z, dispersion, iteration_mode='no_global_wrej', reject_boxcar=100,
                   ensemble=False, velscale_ratio=sc_velscale_ratio, mask=sc_pixel_mask,
                   matched_resolution=False, tpl_sres=sc_tpl_sres, obj_sres=sres, degree=8,
                   moments=2, plot=fit_plots)

    # The returned objects from the fit are the wavelength, model, and
    # mask vectors and the record array with the best-fitting model
    # parameters. The datamodel of the best-fitting model parameters is
    # set by:
    # https://sdss-mangadap.readthedocs.io/en/latest/api/mangadap.proc.spectralfitting.html#mangadap.proc.spectralfitting.StellarKinematicsFit._per_stellar_kinematics_dtype

    # Remask the continuum fit
    sc_continuum = StellarContinuumModel.reset_continuum_mask_window(
                        numpy.ma.MaskedArray(cont_flux, mask=cont_mask>0))

    # Show the fit and residual
    if usr_plots:
        pyplot.plot(wave, flux[0,:], label='Data')
        pyplot.plot(wave, sc_continuum[0,:], label='Model')
        pyplot.plot(wave, flux[0,:] - sc_continuum[0,:], label='Resid')
        pyplot.legend()
        pyplot.xlabel('Wavelength')
        pyplot.ylabel('Flux')
        pyplot.show()
    #-------------------------------------------------------------------

    #-------------------------------------------------------------------
    # Get the emission-line moments using the fitted stellar continuum

    # Read the database that define the emission lines and passbands
    momdb = EmissionMomentsDB.from_key(elmom_key)

    # Measure the moments
    elmom = EmissionLineMoments.measure_moments(momdb, wave, flux, continuum=sc_continuum,
                                                redshift=z)
    #-------------------------------------------------------------------

    #-------------------------------------------------------------------
    # Fit the emission-line model

    # Set the emission-line continuum templates if different from those
    # used for the stellar continuum
    if sc_tpl_key == el_tpl_key:
        # If the keywords are the same, just copy over the previous
        # library ...
        el_tpl = sc_tpl
        el_tpl_sres = sc_tpl_sres
        # ... and the best fitting stellar kinematics
        stellar_kinematics = cont_par['KIN']
    else:
        # If the template sets are different, we need to match the
        # spectral resolution to the galaxy data ...
        _sres = SpectralResolution(wave, sres[0,:], log10=True)
        el_tpl = TemplateLibrary(el_tpl_key, sres=_sres, velscale_ratio=el_velscale_ratio,
                                 spectral_step=spectral_step, log=True, hardcopy=False)
        el_tpl_sres = numpy.mean(el_tpl['SPECRES'].data, axis=0).ravel()
        # ... and use the corrected velocity dispersions.
        stellar_kinematics = cont_par['KIN']
        stellar_kinematics[:,1] = numpy.ma.sqrt(numpy.square(cont_par['KIN'][:,1]) -
                                                    numpy.square(cont_par['SIGMACORR_EMP']))

    # Read the emission line fitting database
    emldb = EmissionLineDB.from_key(elfit_key)

    # Instantiate the fitting class
    emlfit = Sasuke(EmissionLineModelBitMask())

    # Perform the fit
    efit_t = time.perf_counter()
    eml_wave, model_flux, eml_flux, eml_mask, eml_fit_par, eml_eml_par \
            = emlfit.fit(emldb, wave, flux, obj_ferr=ferr, obj_mask=el_pixel_mask, obj_sres=sres,
                         guess_redshift=z, guess_dispersion=dispersion, reject_boxcar=101,
                         stpl_wave=el_tpl['WAVE'].data, stpl_flux=el_tpl['FLUX'].data,
                         stpl_sres=el_tpl_sres, stellar_kinematics=stellar_kinematics,
                         etpl_sinst_mode='offset', etpl_sinst_min=10.,
                         velscale_ratio=el_velscale_ratio, matched_resolution=False, mdegree=8,
                         plot=fit_plots)
    print('TIME: ', time.perf_counter() - efit_t)

    # Line-fit metrics
    eml_eml_par = EmissionLineFit.line_metrics(emldb, wave, flux, ferr, model_flux, eml_eml_par,
                                               model_mask=eml_mask, bitmask=emlfit.bitmask)

    # Get the stellar continuum that was fit for the emission lines
    elcmask = eml_mask.ravel() > 0
    goodpix = numpy.arange(elcmask.size)[numpy.invert(elcmask)]
    start, end = goodpix[0], goodpix[-1]+1
    elcmask[start:end] = False
    el_continuum = numpy.ma.MaskedArray(model_flux - eml_flux,
                                        mask=elcmask.reshape(model_flux.shape))

    # Plot the result
    if usr_plots:
        pyplot.plot(wave, flux[0,:], label='Data')
        pyplot.plot(wave, model_flux[0,:], label='Model')
        pyplot.plot(wave, el_continuum[0,:], label='EL Cont.')
        pyplot.plot(wave, sc_continuum[0,:], label='SC Cont.')
        pyplot.legend()
        pyplot.xlabel('Wavelength')
        pyplot.ylabel('Flux')
        pyplot.show()

    # Remeasure the emission-line moments with the new continuum
    new_elmom = EmissionLineMoments.measure_moments(momdb, wave, flux, continuum=el_continuum,
                                                    redshift=z)

    # Compare the summed flux and Gaussian-fitted flux for all the
    # fitted lines
    if usr_plots:
        pyplot.scatter(emldb['restwave'], (new_elmom['FLUX']-eml_eml_par['FLUX']).ravel(),
                       c=eml_eml_par['FLUX'].ravel(), cmap='viridis', marker='.', s=60, lw=0,
                       zorder=4)
        pyplot.grid()
        pyplot.xlabel('Wavelength')
        pyplot.ylabel('Summed-Gaussian Difference')
        pyplot.show()
    #-------------------------------------------------------------------

    #-------------------------------------------------------------------
    # Measure the spectral indices
    if absindx_key is None or bhdindx_key is None:
        # Neither are defined, so we're done
        print('Elapsed time: {0} seconds'.format(time.perf_counter() - t))
        return

    # Setup the databases that define the indices to measure
    absdb = None if absindx_key is None else AbsorptionIndexDB.from_key(absindx_key)
    bhddb = None if bhdindx_key is None else BandheadIndexDB.from_key(bhdindx_key)

    # Remove the modeled emission lines from the spectra
    flux_noeml = flux - eml_flux
    redshift = stellar_kinematics[:,0] / astropy.constants.c.to('km/s').value
    sp_indices = SpectralIndices.measure_indices(absdb, bhddb, wave, flux_noeml, ivar=ivar,
                                                 redshift=redshift)

    # Calculate the velocity dispersion corrections
    #   - Construct versions of the best-fitting model spectra with and without
    #     the included dispersion
    continuum = Sasuke.construct_continuum_models(emldb, el_tpl['WAVE'].data, el_tpl['FLUX'].data,
                                                  wave, flux.shape, eml_fit_par)
    continuum_dcnvlv = Sasuke.construct_continuum_models(emldb, el_tpl['WAVE'].data,
                                                         el_tpl['FLUX'].data, wave, flux.shape,
                                                         eml_fit_par, redshift_only=True)

    #   - Get the dispersion corrections and fill the relevant columns of the
    #     index table
    sp_indices['BCONT_MOD'], sp_indices['BCONT_CORR'], sp_indices['RCONT_MOD'], \
        sp_indices['RCONT_CORR'], sp_indices['MCONT_MOD'], sp_indices['MCONT_CORR'], \
        sp_indices['AWGT_MOD'], sp_indices['AWGT_CORR'], \
        sp_indices['INDX_MOD'], sp_indices['INDX_CORR'], \
        sp_indices['INDX_BF_MOD'], sp_indices['INDX_BF_CORR'], \
        good_les, good_ang, good_mag, is_abs \
                = SpectralIndices.calculate_dispersion_corrections(absdb, bhddb, wave, flux,
                                                                   continuum, continuum_dcnvlv,
                                                                   redshift=redshift,
                                                                   redshift_dcnvlv=redshift)

    # Apply the index corrections.  This is only done here for the
    # Worthey/Trager definition of the indices, as an example
    corrected_indices = numpy.zeros(sp_indices['INDX'].shape, dtype=float)
    corrected_indices_err = numpy.zeros(sp_indices['INDX'].shape, dtype=float)
    # Unitless indices
    corrected_indices[good_les], corrected_indices_err[good_les] \
            = SpectralIndices.apply_dispersion_corrections(sp_indices['INDX'][good_les],
                                                           sp_indices['INDX_CORR'][good_les],
                                                           err=sp_indices['INDX_ERR'][good_les])
    # Indices in angstroms
    corrected_indices[good_ang], corrected_indices_err[good_ang] \
            = SpectralIndices.apply_dispersion_corrections(sp_indices['INDX'][good_ang],
                                                           sp_indices['INDX_CORR'][good_ang],
                                                           err=sp_indices['INDX_ERR'][good_ang],
                                                           unit='ang')
    # Indices in magnitudes
    corrected_indices[good_mag], corrected_indices_err[good_mag] \
            = SpectralIndices.apply_dispersion_corrections(sp_indices['INDX'][good_mag],
                                                           sp_indices['INDX_CORR'][good_mag],
                                                           err=sp_indices['INDX_ERR'][good_mag],
                                                           unit='mag')

    # Print the results for a few indices
    index_names = numpy.append(absdb['name'], bhddb['name'])
    print('-'*73)
    print(f'{"NAME":<8} {"Raw Index":>12} {"err":>12} {"Index Corr":>12} {"Index":>12} {"err":>12}')
    print(f'{"-"*8:<8} {"-"*12:<12} {"-"*12:<12} {"-"*12:<12} {"-"*12:<12} {"-"*12:<12}')
    for name in ['Hb', 'HDeltaA', 'Mgb', 'Dn4000']:
        i = numpy.where(index_names == name)[0][0]
        print(f'{name:<8} {sp_indices["INDX"][0,i]:12.4f} {sp_indices["INDX_ERR"][0,i]:12.4f} '
              f'{sp_indices["INDX_CORR"][0,i]:12.4f} {corrected_indices[0,i]:12.4f} '
              f'{corrected_indices_err[0,i]:12.4f}')
    print('-'*73)

    embed()

    print('Elapsed time: {0} seconds'.format(time.perf_counter() - t))
コード例 #15
0
                                               # Use pre-pixelized LSF (KHRR added this)
                                               prepixel_sres=True)

    # Bin the spectra using the new binning method
    binned_spectra = SpatiallyBinnedSpectra('Aperture',     # Key for binning method
                                            cube,           # DRP data to bin
                                            rdxqa,          # Cube coordinates and S/N assessments
                                            method_list=binning_method, # Methods to select from
                                            output_path=output_path)

    # The rest of this is just a single execution of the remaining
    # analysis steps in
    # $MANGADAP_DIR/python/mangadap/survey/manga_dap.py , with some
    # simplifications

    stellar_continuum = StellarContinuumModel('GAU-MILESHC', binned_spectra, guess_vel=vel,
                                              guess_sig=100., output_path=output_path)

    emission_line_moments = EmissionLineMoments('EMOMM', binned_spectra,
                                                stellar_continuum=stellar_continuum,
                                                redshift=nsa_redshift, output_path=output_path)

    emission_line_model = EmissionLineModel('EFITM', binned_spectra,
                                            stellar_continuum=stellar_continuum,
                                            redshift=nsa_redshift, dispersion=100.0,
                                            output_path=output_path)
        
    spectral_indices = SpectralIndices('INDXEN', binned_spectra, redshift=nsa_redshift,
                                       stellar_continuum=stellar_continuum,
                                       emission_line_model=emission_line_model,
                                       output_path=output_path)
コード例 #16
0
def main():
    select_file = 'repr/representative_spectra_selection_v2.fits'
    spec_file = 'repr/benchmark_spectra_v2.fits'
    flag_file = 'repr/representative_spectra_flags_v2.db'

    #    mod_file = None
    #    plot_file = 'repr/representative_spectra_v2.pdf'

    #    mod_file = 'repr/benchmark_spectra_v2_model.fits'
    #    plot_file = 'repr/representative_spectra_v2_model.pdf'

    #    mod_file = 'repr/run5/run5_MILESHC_4_8_MASTARSSP_1_14_ELBMPL9_ELPMPL11.fits.gz'
    #    plot_file = 'repr/representative_spectra_v2_model_run5_ssp_14_sig1.4.pdf'
    #    mod_file = 'repr/run5/run5_MILESHC_4_8_MASTARSSP_1_14_ELBMPL9_ELPMPL11A.fits.gz'
    #    plot_file = 'repr/representative_spectra_v2_model_run5_ssp_14_sig3.0.pdf'
    #    mod_file = 'repr/run5/run5_MILESHC_4_8_MASTARSSP_1_14_ELBMPL9_ELPMPL11B.fits.gz'
    #    plot_file = 'repr/representative_spectra_v2_model_run5_ssp_14_sigmix.pdf'
    mod_file = 'repr/run7/run7_MILESHC_4_8_MASTARSSP_1_14_ELBMPL9_ELPMPL11UPA.fits.gz'
    plot_file = 'repr/representative_spectra_v2_model_run7_ssp_14_sigmixup.pdf'

    select_hdu = fits.open(select_file)
    spec_hdu = fits.open(spec_file)
    mod_hdu = None if mod_file is None else fits.open(mod_file)

    nspec = spec_hdu['FLUX'].shape[0]

    restwave_limits = numpy.array([3575, 10300])
    d4000_limits = numpy.array([3700, 4300])
    mg_limits = numpy.array([5100, 5285])
    halpha_limits = numpy.array([6460, 6676])
    ca_limits = numpy.array([8450, 8750])

    drp_bm = DRPFitsBitMask()
    cube_bm = DAPCubeBitMask()

    wave = spec_hdu['WAVE'].data
    flux = numpy.ma.MaskedArray(spec_hdu['FLUX'].data,
                                mask=drp_bm.flagged(
                                    spec_hdu['MASK'].data,
                                    flag=['DONOTUSE', 'FORESTAR']))

    if mod_hdu is None:
        model = numpy.ma.MaskedArray(spec_hdu['MODEL'].data,
                                     mask=cube_bm.flagged(
                                         spec_hdu['MODEL_MASK'].data,
                                         flag='NOMODEL'))
        cont = numpy.ma.MaskedArray(
            spec_hdu['MODEL'].data - spec_hdu['EMLINE'].data,
            mask=cube_bm.flagged(spec_hdu['MODEL_MASK'].data, flag='NOMODEL'))
        stellar = numpy.ma.MaskedArray(spec_hdu['STELLAR'].data,
                                       mask=cube_bm.flagged(
                                           spec_hdu['STELLAR_MASK'].data,
                                           flag='NOMODEL'))
    else:
        model = numpy.ma.MaskedArray(mod_hdu['MODEL'].data,
                                     mask=mod_hdu['MODEL_MASK'].data > 0)
        model = StellarContinuumModel.reset_continuum_mask_window(model)
        cont = numpy.ma.MaskedArray(mod_hdu['MODEL'].data -
                                    mod_hdu['EMLINE'].data,
                                    mask=mod_hdu['MODEL_MASK'].data > 0)
        cont = StellarContinuumModel.reset_continuum_mask_window(cont)

        stellar = numpy.ma.MaskedArray(mod_hdu['STELLAR'].data,
                                       mask=mod_hdu['STELLAR_MASK'].data > 0)
        stellar = StellarContinuumModel.reset_continuum_mask_window(stellar)

    if not os.path.isfile(flag_file):
        include_flags = numpy.ones(nspec, dtype=int)
        numpy.savetxt(flag_file,
                      numpy.array([
                          select_hdu['PAR'].data['PLT'].astype(int),
                          select_hdu['PAR'].data['IFU'].astype(int),
                          select_hdu['PAR'].data['BIN'].astype(int),
                          numpy.ones(nspec, dtype=int)
                      ]).T,
                      fmt=['%5d', '%5d', '%5d', '%3d'],
                      header='{0:>3} {1:>5} {2:>5} {3:>3}'.format(
                          'PLT', 'IFU', 'BIN', 'SEL'))

    rc('font', size=8)

    with PdfPages(plot_file) as pdf:

        #        j = 0
        for i in range(nspec):
            print('{0}/{1}'.format((i + 1), nspec), end='\r')
            lambda_limits = restwave_limits * (1 +
                                               select_hdu['PAR'].data['Z'][i])
            indx = numpy.logical_not(numpy.ma.getmaskarray(flux)[i,:]) \
                        & (wave > lambda_limits[0]) & (wave < lambda_limits[1])
            if numpy.sum(indx) == 0:
                continue
            if numpy.sum(numpy.logical_not(
                    numpy.ma.getmaskarray(model)[i, :])) == 0:
                continue

            mod_lim = [
                numpy.ma.amin(model[i, indx]),
                numpy.ma.amax(model[i, indx])
            ]
            Df = (mod_lim[1] - mod_lim[0]) * 1.5
            flux_limits = numpy.mean(mod_lim) + numpy.array([-Df / 2, Df / 2])

            if not numpy.all(numpy.isfinite(flux_limits)):
                embed()
                exit()

            fig = pyplot.figure()

            # Full spectrum
            ax = fig.add_axes([0.06, 0.45, 0.92, 0.5])
            ax.minorticks_on()
            ax.tick_params(which='major',
                           length=10,
                           direction='in',
                           top=True,
                           right=True)
            ax.tick_params(which='minor',
                           length=5,
                           direction='in',
                           top=True,
                           right=True)
            ax.set_xlim(lambda_limits)
            ax.set_ylim(flux_limits)
            ax.grid(True, which='major', color='0.8', zorder=0, linestyle='-')
            ax.step(wave, flux[i, :], zorder=2, color='k', lw=0.5, where='mid')
            ax.plot(wave, stellar[i, :], zorder=3, color='C1', lw=1.0)
            ax.plot(wave, model[i, :], zorder=4, color='C3', lw=1.0)
            ax.plot(wave, cont[i, :], zorder=5, color='C9', lw=1.0)

            ax.text(-0.05,
                    0.5,
                    r'$F_\lambda$',
                    ha='center',
                    va='center',
                    transform=ax.transAxes,
                    rotation='vertical')
            ax.text(0.5,
                    -0.1,
                    r'$\lambda_{\rm obs}\ [{\rm \AA}]$',
                    ha='center',
                    va='center',
                    transform=ax.transAxes)

            ax.text(0.01,
                    1.03,
                    '{0}: {1}-{2}-{3}; '.format(
                        i, select_hdu['PAR'].data['PLT'][i],
                        select_hdu['PAR'].data['IFU'][i],
                        select_hdu['PAR'].data['BIN'][i]) +
                    'z={0:.4f}; '.format(select_hdu['PAR'].data['Z'][i]) +
                    'S/N={0:.1f}; '.format(select_hdu['PAR'].data['SNR'][i]) +
                    r'$\sigma_{\ast,{\rm obs}}$=' +
                    r'{0:.1f}; D4000={1:.1f}; H$\alpha$ EW={2:.1f}'.format(
                        select_hdu['PAR'].data['SIGMA'][i],
                        select_hdu['PAR'].data['D4000'][i],
                        select_hdu['PAR'].data['HAEW'][i]),
                    horizontalalignment='left',
                    verticalalignment='center',
                    transform=ax.transAxes)

            lambda_limits = d4000_limits * (1 + select_hdu['PAR'].data['Z'][i])
            indx = numpy.logical_not(numpy.ma.getmaskarray(flux)[i,:]) \
                        & (wave > lambda_limits[0]) & (wave < lambda_limits[1])
            mod_lim = [0,1] if numpy.sum(indx) == 0 \
                        else [numpy.ma.amin(model[i,indx]), numpy.ma.amax(model[i,indx])]
            Df = (mod_lim[1] - mod_lim[0]) * 1.5
            flux_limits = numpy.mean(mod_lim) + numpy.array([-Df / 2, Df / 2])

            ax = fig.add_axes([0.06, 0.08, 0.19, 0.27])
            ax.minorticks_on()
            ax.tick_params(which='major',
                           length=10,
                           direction='in',
                           top=True,
                           right=True)
            ax.tick_params(which='minor',
                           length=5,
                           direction='in',
                           top=True,
                           right=True)
            ax.set_xlim(lambda_limits)
            ax.set_ylim(flux_limits)
            ax.grid(True, which='major', color='0.8', zorder=0, linestyle='-')
            ax.plot(wave, flux[i, :], zorder=2, color='k', lw=0.5)
            ax.plot(wave, stellar[i, :], zorder=3, color='C1', lw=1.0)
            ax.plot(wave, model[i, :], zorder=4, color='C3', lw=1.0)
            ax.plot(wave, cont[i, :], zorder=5, color='C9', lw=1.0)

            ax.text(0.5,
                    -0.2,
                    r'$\lambda_{\rm obs}\ [{\rm \AA}]$',
                    ha='center',
                    va='center',
                    transform=ax.transAxes)

            lambda_limits = mg_limits * (1 + select_hdu['PAR'].data['Z'][i])
            indx = numpy.logical_not(numpy.ma.getmaskarray(flux)[i,:]) \
                        & (wave > lambda_limits[0]) & (wave < lambda_limits[1])
            mod_lim = [0,1] if numpy.sum(indx) == 0 \
                        else [numpy.ma.amin(model[i,indx]), numpy.ma.amax(model[i,indx])]
            Df = (mod_lim[1] - mod_lim[0]) * 1.5
            flux_limits = numpy.mean(mod_lim) + numpy.array([-Df / 2, Df / 2])

            ax = fig.add_axes([0.30, 0.08, 0.19, 0.27])
            ax.minorticks_on()
            ax.tick_params(which='major',
                           length=10,
                           direction='in',
                           top=True,
                           right=True)
            ax.tick_params(which='minor',
                           length=5,
                           direction='in',
                           top=True,
                           right=True)
            ax.set_xlim(lambda_limits)
            ax.set_ylim(flux_limits)
            ax.grid(True, which='major', color='0.8', zorder=0, linestyle='-')
            ax.plot(wave, flux[i, :], zorder=2, color='k', lw=0.5)
            ax.plot(wave, stellar[i, :], zorder=3, color='C1', lw=1.0)
            ax.plot(wave, model[i, :], zorder=4, color='C3', lw=1.0)
            ax.plot(wave, cont[i, :], zorder=5, color='C9', lw=1.0)

            ax.text(0.5,
                    -0.2,
                    r'$\lambda_{\rm obs}\ [{\rm \AA}]$',
                    ha='center',
                    va='center',
                    transform=ax.transAxes)

            lambda_limits = halpha_limits * (1 +
                                             select_hdu['PAR'].data['Z'][i])
            indx = numpy.logical_not(numpy.ma.getmaskarray(flux)[i,:]) \
                        & (wave > lambda_limits[0]) & (wave < lambda_limits[1])
            mod_lim = [0,1] if numpy.sum(indx) == 0 \
                        else [numpy.ma.amin(model[i,indx]), numpy.ma.amax(model[i,indx])]
            Df = (mod_lim[1] - mod_lim[0]) * 1.5
            flux_limits = numpy.mean(mod_lim) + numpy.array([-Df / 2, Df / 2])

            ax = fig.add_axes([0.54, 0.08, 0.19, 0.27])
            ax.minorticks_on()
            ax.tick_params(which='major',
                           length=10,
                           direction='in',
                           top=True,
                           right=True)
            ax.tick_params(which='minor',
                           length=5,
                           direction='in',
                           top=True,
                           right=True)
            ax.set_xlim(lambda_limits)
            ax.set_ylim(flux_limits)
            ax.grid(True, which='major', color='0.8', zorder=0, linestyle='-')
            ax.plot(wave, flux[i, :], zorder=2, color='k', lw=0.5)
            ax.plot(wave, stellar[i, :], zorder=3, color='C1', lw=1.0)
            ax.plot(wave, model[i, :], zorder=4, color='C3', lw=1.0)
            ax.plot(wave, cont[i, :], zorder=5, color='C9', lw=1.0)

            ax.text(0.5,
                    -0.2,
                    r'$\lambda_{\rm obs}\ [{\rm \AA}]$',
                    ha='center',
                    va='center',
                    transform=ax.transAxes)

            lambda_limits = ca_limits * (1 + select_hdu['PAR'].data['Z'][i])
            indx = numpy.logical_not(numpy.ma.getmaskarray(flux)[i,:]) \
                        & (wave > lambda_limits[0]) & (wave < lambda_limits[1])
            mod_lim = [0,1] if numpy.sum(indx) == 0 \
                        else [numpy.ma.amin(model[i,indx]), numpy.ma.amax(model[i,indx])]
            Df = (mod_lim[1] - mod_lim[0]) * 1.5
            flux_limits = numpy.mean(mod_lim) + numpy.array([-Df / 2, Df / 2])

            ax = fig.add_axes([0.78, 0.08, 0.19, 0.27])
            ax.minorticks_on()
            ax.tick_params(which='major',
                           length=10,
                           direction='in',
                           top=True,
                           right=True)
            ax.tick_params(which='minor',
                           length=5,
                           direction='in',
                           top=True,
                           right=True)
            ax.set_xlim(lambda_limits)
            ax.set_ylim(flux_limits)
            ax.grid(True, which='major', color='0.8', zorder=0, linestyle='-')
            ax.plot(wave, flux[i, :], zorder=2, color='k', lw=0.5)
            ax.plot(wave, stellar[i, :], zorder=3, color='C1', lw=1.0)
            ax.plot(wave, model[i, :], zorder=4, color='C3', lw=1.0)
            ax.plot(wave, cont[i, :], zorder=5, color='C9', lw=1.0)

            ax.text(0.5,
                    -0.2,
                    r'$\lambda_{\rm obs}\ [{\rm \AA}]$',
                    ha='center',
                    va='center',
                    transform=ax.transAxes)

            pdf.savefig(orientation='landscape')
            fig.clear()
            pyplot.close(fig)


#            j += 1
#            if j == 10:
#                break

    print('{0}/{0}'.format(nspec))