def object_data(f, fit_flag_file): with fits.open(f) as hdu: flux = hdu['FLUX'].data ivar = hdu['IVAR'].data mask = hdu['MASK'].data sres = hdu['LSF'].data wave = hdu['WAVE'].data redshift = hdu['Z'].data sres = numpy.ma.divide(wave[None, :], sres) / DAPConstants.sig2fwhm if numpy.any(numpy.ma.getmaskarray(sres)): sres = numpy.ma.apply_along_axis(interpolate_masked_vector, 1, sres) bm = DRPFitsBitMask() nspec = flux.shape[0] fit_flags = numpy.ones(nspec, dtype=bool) if fit_flag_file is None \ else (numpy.genfromtxt(fit_flag_file)[:,3]).astype(bool) if len(fit_flags) != nspec: print(nspec, len(fit_flags)) raise ValueError('Incorrect number of fitting flags.') ferr = numpy.ma.power(ivar, -0.5) bool_mask = bm.flagged(mask, flag=['DONOTUSE', 'FORESTAR' ]) | numpy.ma.getmaskarray(ferr) return wave, numpy.ma.MaskedArray(flux, mask=bool_mask), \ numpy.ma.MaskedArray(ferr, mask=bool_mask), sres, redshift, fit_flags
def test_drpfitsbitmask(): # Read the data specfile = data_test_file('MaNGA_test_spectra.fits.gz') hdu = fits.open(specfile) drpbm = DRPFitsBitMask() assert numpy.sum(drpbm.flagged(hdu['MASK'].data, MaNGADataCube.do_not_fit_flags())) == 4601, \ 'Flags changed'
def test_moments(): # 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] # 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, 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': 46, 'JUMP_BTWN_SIDEBANDS': 0, 'RED_JUMP': 0, 'DIVBYZERO': 0, 'NO_ABSORPTION_CORRECTION': 176, '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.allclose(elmom['FLUX'][0], numpy.array([ -0.83366296, 0., -0.7368989, -6.84760392, -5.8392653, -3.84394899, -9.63158548, -10.1459227, -1.86639944, 0.19851703, 0.04831539, -5.58001859, 0.86652478, -1.3277138, 4.48556862, 0.12541773, -1.37675776, 1.14456948, -1.41808526, 2.48743805, -0.31254732, 0.04046428 ]), rtol=0.0, atol=1e-2), 'Fluxes changed' assert numpy.allclose( elmom['MOM1'][0], numpy.array([ 15403.91870501, 0., 13866.58355013, 14816.45834376, 14861.90408263, 14545.21106265, 14929.76054479, 14774.62443577, 14943.56586856, 13010.07824437, 15933.25294444, 14918.25984067, 14425.53398781, 15207.53998774, 14803.71786274, 14160.66542001, 14720.66321017, 14706.89675211, 14880.91017052, 14901.49219165, 14880.79548007, 15615.43369812 ]), rtol=0.0, atol=1e-1), '1st moments changed' assert numpy.allclose(elmom['MOM2'][0], numpy.array([ 0., 0., 0., 439.76305578, 479.32501708, 325.96571646, 348.71402151, 362.29430475, 128.76827924, 0., 0., 322.61461489, 268.26542796, 27.14271982, 259.24977286, 0., 181.94055378, 129.62366078, 147.48288905, 225.76488299, 132.57819153, 0. ]), rtol=0.0, atol=1e-1), '2nd moments changed' assert numpy.allclose(elmom['EW'][0], numpy.array([ -0.83148156, 0., -0.67854382, -6.65583709, -4.99844209, -3.06783667, -6.6506484, -6.86724193, -0.99166185, 0.08843696, 0.01728948, -1.81199184, 0.28592615, -0.46054113, 1.48650809, 0.03822714, -0.40850899, 0.33980593, -0.42043643, 0.73608197, -0.09406925, 0.01217937 ]), rtol=0.0, atol=1e-2), 'EW changed'
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'
def test_sasuke(): # 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 sc_wave, sc_flux, sc_mask, sc_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) # Mask the 5577 sky line pixelmask = SpectralPixelMask(artdb=ArtifactDB.from_key('BADSKY')) # Read the emission line fitting database emldb = EmissionLineDB.from_key('ELPMILES') assert emldb['name'][ 18] == 'Ha', 'Emission-line database names or ordering changed' # Instantiate the fitting class emlfit = Sasuke(EmissionLineModelBitMask()) # Perform the fit el_wave, model, el_flux, el_mask, el_fit, el_par \ = emlfit.fit(emldb, hdu['WAVE'].data, flux, obj_ferr=ferr, obj_mask=pixelmask, obj_sres=hdu['SRES'].data, guess_redshift=hdu['Z'].data, guess_dispersion=numpy.full(nspec, 100.), reject_boxcar=101, stpl_wave=tpl['WAVE'].data, stpl_flux=tpl['FLUX'].data, stpl_sres=tpl_sres, stellar_kinematics=sc_par['KIN'], etpl_sinst_mode='offset', etpl_sinst_min=10., velscale_ratio=velscale_ratio, matched_resolution=False) # Rejected pixels assert numpy.sum(emlfit.bitmask.flagged(el_mask, flag='PPXF_REJECT')) == 266, \ 'Different number of rejected pixels' # Unable to fit assert numpy.array_equal(emlfit.bitmask.flagged_bits(el_fit['MASK'][5]), ['NO_FIT']), \ 'Expected NO_FIT in 6th spectrum' # No *attempted* fits should fail assert numpy.sum(emlfit.bitmask.flagged(el_fit['MASK'], flag='FIT_FAILED')) == 0, \ 'Fits should not fail' # Number of used templates assert numpy.array_equal(numpy.sum(numpy.absolute(el_fit['TPLWGT']) > 1e-10, axis=1), [25, 22, 34, 32, 27, 0, 16, 22]), \ 'Different number of templates with non-zero weights' # No additive coefficients assert numpy.all(el_fit['ADDCOEF'] == 0), \ 'No additive coefficients should exist' # No multiplicative coefficients assert numpy.all(el_fit['MULTCOEF'] == 0), \ 'No multiplicative coefficients should exist' # Fit statistics assert numpy.all( numpy.absolute( el_fit['RCHI2'] - numpy.array([2.34, 1.22, 1.58, 1.88, 3.20, 0., 1.05, 0.88])) < 0.02 ), 'Reduced chi-square are too different' assert numpy.all( numpy.absolute(el_fit['RMS'] - numpy.array( [0.036, 0.019, 0.036, 0.024, 0.051, 0.000, 0.012, 0.012])) < 0.001 ), 'RMS too different' assert numpy.all(numpy.absolute(el_fit['FRMS'] - numpy.array([0.021, 0.025, 0.025, 0.033, 0.018, 0.000, 1.052, 0.101])) < 0.001), \ 'Fractional RMS too different' assert numpy.all(numpy.absolute(el_fit['RMSGRW'][:,2] - numpy.array([0.070, 0.038, 0.071, 0.047, 0.101, 0.000, 0.026, 0.024])) < 0.001), \ 'Median absolute residual too different' # All lines should have the same velocity assert numpy.all(numpy.all(el_par['KIN'][:,:,0] == el_par['KIN'][:,None,0,0], axis=1)), \ 'All velocities should be the same' # Test velocity values # TODO: Need some better examples! assert numpy.all(numpy.absolute(el_par['KIN'][:,0,0] - numpy.array([14704.9, 14869.3, 14767.1, 8161.9, 9258.7, 0.0, 5130.9, 5430.3])) < 0.1), \ 'Velocities are too different' # H-alpha dispersions assert numpy.all(numpy.absolute(el_par['KIN'][:,18,1] - numpy.array([1000.5, 1000.5, 224.7, 124.9, 171.2, 0.0, 81.2, 50.0])) < 1e-1), \ 'H-alpha dispersions are too different'
def test_ppxffit(): # 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) # Test the results # Rejected pixels assert numpy.sum(ppxf.bitmask.flagged(fit_mask, flag='PPXF_REJECT')) == 119, \ 'Different number of rejected pixels' # Unable to fit assert numpy.array_equal(ppxf.bitmask.flagged_bits(fit_par['MASK'][5]), ['NO_FIT']), \ 'Expected NO_FIT in 6th spectrum' # Number of used templates assert numpy.array_equal(numpy.sum(numpy.absolute(fit_par['TPLWGT']) > 1e-10, axis=1), [12, 13, 17, 15, 15, 0, 8, 12]), \ 'Different number of templates with non-zero weights' # Number of additive coefficients assert fit_par['ADDCOEF'].shape[ 1] == 9, 'Incorrect number of additive coefficients' # No multiplicative coefficients assert numpy.all(fit_par['MULTCOEF'] == 0), \ 'No multiplicative coefficients should exist' # Kinematics and errors assert numpy.all(numpy.absolute(fit_par['KIN'] - numpy.array([[ 14880.7, 292.9], [ 15053.4, 123.2], [ 14787.5, 236.4], [ 8291.8, 169.7], [ 9261.4, 202.7], [ 0.0, 0.0], [ 5123.5, 63.8], [ 5455.6, 51.8]])) < 0.1), \ 'Kinematics are too different' assert numpy.all(numpy.absolute(fit_par['KINERR'] - numpy.array([[2.0,1.9], [1.5,1.7], [ 2.4, 2.4], [2.2,2.3], [1.1,1.1], [0.0,0.0], [26.1,30.8], [4.7,7.5]])) < 0.1), \ 'Kinematic errors are too different' # Velocity dispersion corrections assert numpy.all(numpy.absolute(fit_par['SIGMACORR_SRES'] - numpy.array([23.5, 10.1, 27.3, 38.7, 22.3, 0.0, 63.8, 23.8])) < 0.1), \ 'SRES corrections are too different' assert numpy.all(numpy.absolute(fit_par['SIGMACORR_EMP'] - numpy.array([22.6, 0.0, 26.0, 38.2, 18.0, 0.0, 70.1, 0.0])) < 0.1), \ 'EMP corrections are too different' # Figures of merit assert numpy.all(numpy.absolute(fit_par['RCHI2'] - numpy.array([ 1.94, 1.18, 1.40, 1.53, 2.50, 0.00, 1.06, 0.86])) < 0.01), \ 'Reduced chi-square too different' assert numpy.all( numpy.absolute(fit_par['RMS'] - numpy.array( [0.033, 0.019, 0.034, 0.023, 0.046, 0.000, 0.015, 0.015])) < 0.001 ), 'RMS too different' assert numpy.all( numpy.absolute(fit_par['FRMS'] - numpy.array( [0.018, 0.023, 0.023, 0.032, 0.018, 0.000, 33.577, 0.148])) < 0.001 ), 'Fractional RMS too different' assert numpy.all( numpy.absolute(fit_par['RMSGRW'][:, 2] - numpy.array( [0.067, 0.037, 0.068, 0.046, 0.093, 0.000, 0.029, 0.027])) < 0.001 ), 'Median absolute residual too different'
def collate_data(ofile, tbl, dapver=None, daptype=None): # The number of pixels is HARDWIRED! nspec = len(tbl) npix = 4563 drpbm = DRPFitsBitMask() cube_bm = DAPCubeBitMask() flux = numpy.zeros((nspec, npix), dtype=float) ivar = numpy.zeros((nspec, npix), dtype=float) mask = numpy.zeros((nspec, npix), dtype=drpbm.minimum_dtype()) model = numpy.zeros((nspec, npix), dtype=float) model_mask = numpy.zeros((nspec, npix), dtype=cube_bm.minimum_dtype()) emline = numpy.zeros((nspec, npix), dtype=float) stellar = numpy.zeros((nspec, npix), dtype=float) stellar_mask = numpy.zeros((nspec, npix), dtype=cube_bm.minimum_dtype()) lsf = numpy.zeros((nspec, npix), dtype=float) redshift = numpy.zeros(nspec, dtype=float) filled = numpy.zeros(nspec, dtype=bool) for s in range(nspec): print('{0}/{1}'.format(s+1, nspec), end='\r') if tbl['NBIN'][s] == 0: mask[s,:] = drpbm.turn_on(mask[s,:], 'DONOTUSE') filled[s] = True continue if filled[s]: continue # Open both the DRP datacube and the DAP model datacube drp_hdu = fits.open(os.path.join(*DRPFits.default_paths(tbl['PLT'][s], tbl['IFU'][s], 'CUBE'))) dap_hdu = fits.open(os.path.join( defaults.dap_method_path(daptype, plate=tbl['PLT'][s], ifudesign=tbl['IFU'][s], dapver=dapver), defaults.dap_file_name(tbl['PLT'][s], tbl['IFU'][s], daptype, mode='LOGCUBE'))) # Find any selected spectra in this datacube indx = numpy.where((tbl['PLT'] == tbl['PLT'][s]) & (tbl['IFU'] == tbl['IFU'][s]))[0] if len(indx) == 0: embed(header='could not find pltifu') exit() try: i, j = numpy.array([list(map(lambda x : x[0], numpy.where(dap_hdu['BINID'].data[1] == tbl['BIN'][ii]))) for ii in indx]).T except: embed(header='bad bin selection') exit() wave = drp_hdu['WAVE'].data flux[indx,:] = drp_hdu['FLUX'].data[:,i,j].T ivar[indx,:] = drp_hdu['IVAR'].data[:,i,j].T mask[indx,:] = drp_hdu['MASK'].data[:,i,j].T model[indx,:] = dap_hdu['MODEL'].data[:,i,j].T model_mask[indx,:] = dap_hdu['MODEL_MASK'].data[:,i,j].T emline[indx,:] = dap_hdu['EMLINE'].data[:,i,j].T stellar[indx,:] = dap_hdu['STELLAR'].data[:,i,j].T stellar_mask[indx,:] = dap_hdu['STELLAR_MASK'].data[:,i,j].T lsf[indx,:] = dap_hdu['LSF'].data[:,i,j].T redshift[indx] = tbl['Z'][indx] filled[indx] = True print('{0}/{0}'.format(nspec)) print('All filled: {0}'.format(str(numpy.all(filled)))) fits.HDUList([fits.PrimaryHDU(), fits.ImageHDU(data=wave, name='WAVE'), fits.ImageHDU(data=flux, name='FLUX'), fits.ImageHDU(data=ivar, name='IVAR'), fits.ImageHDU(data=mask, name='MASK'), fits.ImageHDU(data=model, name='MODEL'), fits.ImageHDU(data=model_mask, name='MODEL_MASK'), fits.ImageHDU(data=emline, name='EMLINE'), fits.ImageHDU(data=stellar, name='STELLAR'), fits.ImageHDU(data=stellar_mask, name='STELLAR_MASK'), fits.ImageHDU(data=lsf, name='LSF'), fits.ImageHDU(data=redshift, name='Z')]).writeto(ofile, overwrite=True)
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))