def test_rukia_fit(): miles_wave, miles_flux = read_miles( data_test_file('MILES_res2.50_star_m0505V.fits')) miles_flux /= numpy.median(miles_flux) xsl_wave, xsl_flux, _ = read_xsl( data_test_file('xsl_spectrum_X0360_uvb.fits')) xsl_flux /= numpy.ma.median(xsl_flux) # Setup the fitting functions sigma = LegendrePolynomial(1) mulp = LegendrePolynomial(5) r = Rukia(sigma, mul_model=mulp) # Perform the fit r.fit(miles_wave, miles_flux, xsl_wave.data, xsl_flux.data, shift=0.0, fit_shift=True, rejiter=-1) assert numpy.sum(r.gpm) == 2176, 'Change in the number of pixels rejected.' assert numpy.sqrt(numpy.mean(numpy.square((r.flux-r.model(r.par))[r.gpm]))) < 0.01, \ 'Fit quality changed.'
def test_manga_dap(): odir = data_test_file('manga_dap_output') # Clean up previous failure if os.path.isdir(odir): shutil.rmtree(odir) # Run the DAP. The binning in plan.par is set to ALL binning, so # this run of the DAP just analyzes one spectrum and takes about a # minute. manga_dap.main( manga_dap.parse_args([ '-c', data_test_file('datacube.ini'), '-p', data_test_file('plan.par'), '-a', odir ])) # Re-run to use existing files. Takes about 40s. manga_dap.main( manga_dap.parse_args([ '-c', data_test_file('datacube.ini'), '-p', data_test_file('plan.par'), '-a', odir ])) # Clean up shutil.rmtree(odir)
def test_manga_dap_import(): with pytest.raises(ImportError): manga_dap.main( manga_dap.parse_args( ['-c', data_test_file('datacube.ini'), '-m', 'junk'])) with pytest.raises(AttributeError): manga_dap.main( manga_dap.parse_args( ['-c', data_test_file('datacube.ini'), '-o', 'junk']))
def test_write(): directory, ofile = TemplateLibrary.default_paths( 'MILESHC', output_path=data_test_file()) file_name = directory / ofile if file_name.exists(): os.remove(str(file_name)) tpl = TemplateLibrary('MILESHC', match_resolution=False, velscale_ratio=4, spectral_step=1e-4, log=True, output_path=data_test_file(), hardcopy=True) assert file_name.exists(), 'File not written' os.remove(str(file_name))
def test_against_brute_force(): specfile = data_test_file('MaNGA_test_spectra.fits.gz') hdu = fits.open(specfile) # Just test on the first spectrum old_wave = hdu['WAVE'].data old_flux = numpy.ma.MaskedArray(hdu['FLUX'].data[0, :], mask=hdu['MASK'].data[0, :] > 0) old_flux[(old_wave > 5570) & (old_wave < 5586)] = numpy.ma.masked old_ferr = numpy.ma.power(hdu['IVAR'].data[0, :], -0.5) z = hdu['Z'].data[0] # Do the brute force calculation borders = sampling.grid_borders(numpy.array([old_wave[0], old_wave[-1]]), old_wave.size, log=True)[0] _p = numpy.repeat(borders, 2)[1:-1].reshape(-1, 2) new_flux_brute = passband_integral(old_wave / (1 + z), old_flux, passband=_p, log=True) new_flux_brute /= (_p[:, 1] - _p[:, 0]) # Use resample r = sampling.Resample(old_flux, e=old_ferr, x=old_wave / (1 + z), newRange=[old_wave[0], old_wave[-1]], inLog=True, newLog=True) # The two shoule be the same assert numpy.isclose(numpy.mean(numpy.absolute(new_flux_brute-r.outy)), 0.0), \ 'Resampling and brute force calculation should be identical'
def test_pixelmask(): specfile = data_test_file('MaNGA_test_spectra.fits.gz') hdu = fits.open(specfile) pixelmask = SpectralPixelMask(artdb=ArtifactDB.from_key('BADSKY'), emldb=EmissionLineDB.from_key('ELPSCMSK')) assert numpy.sum(pixelmask.boolean(hdu['WAVE'].data, nspec=1)) == 489, \ 'Incorrect number of masked pixels'
def test_drpbitmask(): # 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_multi_read(): plan = AnalysisPlan.from_toml(data_test_file('dr17.toml')) assert len(plan.keys()) == 4, 'Number of example plans changed' assert plan['plan3'][ 'key'] == 'HYB10-MILESHC-MASTARSSP', 'Plan key changed' assert plan.binning['plan1']['key'] == 'SPX', 'Binning changed' assert plan.elfit['plan4'][ 'key'] == 'EFITHC2DB', 'Emission-line fitting key changed'
def test_read(): plan = AnalysisPlan.from_toml(data_test_file('global_bin.toml')) assert len(plan.keys()) == 1, 'Number of example plans changed' assert list(plan.keys())[0] == 'default', 'Name changed' assert plan.binning['default'][ 'key'] == 'ALL', 'Default DRP reduction QA key changed.' assert plan.elfit['default'][ 'key'] == 'EFITSSP', 'Default emission-line fit key changed.'
def test_from_config(): cfg = MaNGAConfig.from_config(data_test_file("datacube.ini")) assert isinstance(cfg.directory_path, Path), 'Directory should be a Path instance' # TODO: This passes locally, but will fail the tox CI tests. Determine how # to perform this in tox? #assert cfg.directory_path == Path(remote_data_file()).resolve(), 'Directory path changed' assert cfg.plate == 7815, 'Plate changed' assert cfg.log, 'Log binning should be true' assert cfg.mode == 'CUBE', 'Should be in CUBE mode' assert cfg.file_name == 'manga-7815-3702-LOGCUBE.fits.gz'
def test_mangaplan(): cfg = MaNGAConfig(7815, 3702) plan = MaNGAAnalysisPlan.from_toml(data_test_file('dr17.toml'), cube=cfg) assert plan.dap_file_root(cfg) == 'manga-7815-3702', 'Bad root' assert plan.dap_file_root(cfg, mode='MAPS', plan_index=0) \ == 'manga-7815-3702-MAPS-SPX-MILESHC-MASTARSSP', 'Bad full root' assert plan.common_path().parts[-2:] == (str(cfg.plate), str(cfg.ifudesign)), \ 'Bad common subdirectories' assert plan.method_path().parts[-2:] == (str(cfg.plate), str(cfg.ifudesign)), \ 'Bad method subdirectories' assert plan.method_path(qa=True).parts[-2:] == (str(cfg.ifudesign), 'qa'), \ 'Bad qa subdirectories'
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_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_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 test_from_config(): cube = MaNGADataCube.from_config(data_test_file('datacube.ini')) assert cube.meta['z'] == 0.0293823, 'Bad config file read' assert cube.meta['ell'] == 0.110844, 'Bad config file read'
def test_read(): plan = AnalysisPlanSet.from_par_file(data_test_file('plan.par')) assert len(plan) == 1, 'Number of example plans changed' assert plan[0]['bin_key'] == 'ALL', 'Binning changed' assert plan[0]['elfit_key'] == 'EFITMPL11HC', 'Emission-line fitting key changed'