def make_4gaussians_image(noise=True): """ Make an example image containing four 2D Gaussians plus a constant background. The background has a mean of 5. If ``noise`` is `True`, then Gaussian noise with a mean of 0 and a standard deviation of 5 is added to the output image. Parameters ---------- noise : bool, optional Whether to include noise in the output image (default is `True`). Returns ------- image : 2D `~numpy.ndarray` Image containing four 2D Gaussian sources. See Also -------- make_100gaussians_image Examples -------- .. plot:: :include-source: from photutils.datasets import make_4gaussians_image image = make_4gaussians_image() plt.imshow(image, origin='lower', interpolation='nearest') """ table = QTable() table['amplitude'] = [50, 70, 150, 210] table['x_mean'] = [160, 25, 150, 90] table['y_mean'] = [70, 40, 25, 60] table['x_stddev'] = [15.2, 5.1, 3., 8.1] table['y_stddev'] = [2.6, 2.5, 3., 4.7] table['theta'] = np.radians(np.array([145., 20., 0., 60.])) shape = (100, 200) data = make_gaussian_sources_image(shape, table) + 5. if noise: rng = np.random.RandomState(12345) data += rng.normal(loc=0., scale=5., size=shape) return data
def _parse_result(self, response, verbose=False): """ internal wrapper to parse queries """ if self._get_raw_response: return response.text # intercept error messages response_txt = response.text.split('\n')[2:-1] if len(response_txt) < 3 and len(response_txt[-1].split('|')) < 21: raise RuntimeError(response_txt[-1]) results = ascii.read(response_txt[1:], delimiter='|', names=response_txt[0].replace( '# ', '').strip().split(' | ')) results = QTable(results) # convert coordinates to degrees coo = SkyCoord(ra=results['RA(h)'], dec=results['DE(deg)'], unit=(u.hourangle, u.deg), frame='icrs') results['RA(h)'] = coo.ra.deg results['DE(deg)'] = coo.dec.deg colnames = results.columns[:] for fieldname in colnames: # apply field name change results.rename_column(fieldname, conf.field_names[fieldname]) # apply unit, if available if conf.field_names[fieldname] in conf.field_units: results[conf.field_names[fieldname]].unit = conf.field_units[ conf.field_names[fieldname]] # convert object numbers to int # unnumbered asteroids return as non numeric values ('-') # this is treated as defaulting to 0, and masking the entry unnumbered_mask = [not str(x).isdigit() for x in results['Number']] numbers = [ int(x) if str(x).isdigit() else 0 for x in results['Number'] ] asteroid_number_col = MaskedColumn(numbers, name='Number', mask=unnumbered_mask) results.replace_column('Number', asteroid_number_col) return results
def test_masked_column_with_unit_in_qtable(): """Test that adding a MaskedColumn with a unit to QTable issues warning""" t = QTable() t['a'] = MaskedColumn([1, 2]) assert isinstance(t['a'], MaskedColumn) t['b'] = MaskedColumn([1, 2], unit=u.m) assert isinstance(t['b'], u.Quantity) with pytest.warns(UserWarning, match="dropping mask in Quantity column 'c'") as w: t['c'] = MaskedColumn([1, 2], unit=u.m, mask=[True, False]) assert len(w) == 1 assert isinstance(t['b'], u.Quantity)
def load_specific_volt_data(path, LST = False): """One volt data file will be loaded into a table example usage: PATH = 'HPM_Data/FAKEDATA_observation_2458180_7314443593_volt_table.csv' volt_data = load_specific_volt_data(PATH)""" names = ['volts', 'times'] table = QTable(ascii.read(path), names = names) table['volts'].unit = u.V table['times' ].unit = u.s if LST == False else u.rad return table
def test_osip_factor(): '''test extreme values that do not depend on CCD resolution''' assert FixedWidthOSIP(0 * u.eV, ccd_redist=ccd_redist).osip_factor([10] * u.Angstrom, -5, -5) == 0 wide = FixedWidthOSIP(10 * u.keV, ccd_redist=ccd_redist) assert np.allclose(wide.osip_factor([10] * u.Angstrom, -5, -5), 1) '''test with fixed sigma''' sig = QTable({'energy': [0, 1, 2] * u.keV, 'sigma': [40, 40, 40] * u.eV}) myosip = FixedWidthOSIP(40 * u.eV, ccd_redist=CCDRedist(sig)) assert np.allclose(myosip.osip_factor([10] * u.Angstrom, -5, -5), 0.6827, rtol=1e-4)
def add_units_to_Table(df, udict=None, _subkey=None): """takes Table and returns QTable dfQ = add_units_to_Table(df, udict) udict: unit dictionary _subkey key for dictionary if loading from JSON str or list of str for nested dict """ def safeget(dct, *keys): """https://stackoverflow.com/a/25833661/5041184""" for key in keys: try: dct = dct[key] except KeyError: return None return dct # Pre-adjusting for JSON udict if udict is None: dirname = os.path.dirname(__file__) udict = os.path.join(dirname, 'gaia_query_defaults.json') _subkey = [ 'units', ] # Now it's a string and will trigger next 'if' # JSON udict if isinstance(udict, str): with open(udict, 'r') as file: defaults = json.load(file) if _subkey is None: pass elif isinstance(_subkey, str): defaults = defaults[_subkey] else: # nested defaults = safeget(defaults, *_subkey) udict = {} for k, v in defaults.items(): if v != '': udict[k] = eval(v) # astropy units else: udict[k] = u.dimensionless_unscaled # Adding Units, if corresponding column in Table for key, unit in udict.items(): if key in df.columns and df[key].unit != unit: setattr(df[key], 'unit', unit) df = QTable(df) return df
def write_output(dense_lc, Tarr, Terr_arr, Rarr, Rerr_arr, my_filters, snname, outdir): ''' Write out the interpolated LC and BB information Parameters ---------- dense_lc : numpy.array GP-interpolated LC T_arr : numpy.array BB temperature array (K) Terr_arr : numpy.array BB radius error array (K) R_arr : numpy.array BB radius array (cm) Rerr_arr : numpy.array BB temperature error array (cm) my_filters : list List of filter names snname : string SN Name outdir : string Output directory Output ------ ''' dense_lc = np.reshape(dense_lc, (len(dense_lc), -1)) tabledata = np.stack( (Tarr / 1e3, Terr_arr / 1e3, Rarr / 1e15, Rerr_arr / 1e15)).T tabledata = np.hstack((-dense_lc, tabledata)).T ufilts = np.unique(my_filters) table_header = [] for filt in ufilts: table_header.append(filt) table_header.append(filt + '_err') table_header.extend( ['Temp./1e3 (K)', 'Temp. Err.', 'Radius/1e15 (cm)', 'Radius Err.']) print(table_header) sys.exit() table = QTable([*tabledata], names={(*table_header)}, meta={'name': 'first table'}) format_dict = {head: '%0.3f' for head in table_header} ascii.write(table, outdir + snname + '.txt', formats=format_dict, overwrite=True) return 1
def __init__(self, aefforder=aefforder, kind='quadratic', fill_value=0., bounds_error=False): # Bug in astropy <=4.2: # need to wrap into extra QTable or sort will fail aefforder = QTable(aefforder, copy=True) aefforder.sort("wave") self.interp = {} self.unit = {} for o in aefforder.colnames[1:]: self.interp[o] = interp1d(aefforder['wave'], aefforder[o], kind=kind, fill_value=fill_value, bounds_error=bounds_error) # interp1d does not conserve unit, so need to keep separately self.unit[o] = aefforder[o].unit
def test_conversion_qtable_table(): """ Test that a table round trips from QTable => Table => QTable """ qt = QTable(MIXIN_COLS) names = qt.colnames for name in names: qt[name].info.description = name t = Table(qt) for name in names: assert t[name].info.description == name if name == 'quantity': assert np.all(t['quantity'] == qt['quantity'].value) assert np.all(t['quantity'].unit is qt['quantity'].unit) assert isinstance(t['quantity'], t.ColumnClass) else: assert_table_name_col_equal(t, name, qt[name]) qt2 = QTable(qt) for name in names: assert qt2[name].info.description == name assert_table_name_col_equal(qt2, name, qt[name])
def propagate_diffuse_foreground(self, target): """ propagate diffuse foreground sources, starting from zodiacal background """ import copy self.debug('diffuse bkg propagation') out = QTable() total_max_signal, total_signal, wl_table, A, qe, omega_pix, transmission = prepare( self.table, self.built_instr, self.description) foregrounds = list(target.foreground.keys()) foregrounds = reversed(foregrounds) for i, frg in enumerate(foregrounds): self.debug('propagating {}'.format(frg)) radiance = copy.deepcopy(target.foreground[frg]) self.debug('{} radiance . {}'.format(frg, radiance.data)) if hasattr(frg, 'transmission'): frg.transmission.spectral_rebin(transmission.wl_grid) transmission.data *= frg.transmission.data self.debug('added {} transmission'.format(frg)) transmission.spectral_rebin(radiance.wl_grid) radiance.data *= transmission.data # for other_el in foregrounds[i+1:]: # if hasattr(target.foreground[other_el], 'transmission'): # self.debug('passing through {}'.format(other_el)) # radiance.data *= target.foreground[other_el].transmission if 'slit_width' in self.built_instr: max_signal_per_pix, signal = convolve_with_slit( self.description, self.built_instr, A, self.table, omega_pix, qe, radiance) else: qe.spectral_rebin(radiance.wl_grid) radiance.data *= omega_pix * A * qe.data * ( qe.wl_grid / const.c / const.h).to( 1. / u.W / u.s) * u.count # try: # signal = np.trapz(radiance.data * self._window_function(radiance), x=radiance.wl_grid).to(u.ct / u.s) # signal *= self.built_instr['window_spatial_width'] # except KeyError: max_signal_per_pix, signal = integrate_light( radiance, radiance.wl_grid, self.built_instr) total_signal = copy.deepcopy(signal) self.debug('sed : {}'.format(total_signal)) total_max_signal = copy.deepcopy(max_signal_per_pix) out['{}_signal'.format(frg)] = total_signal out['{}_MaxSignal_inPixel'.format(frg)] = total_max_signal return out
def create_rad_max_hdu( rad_max, reco_energy_bins, fov_offset_bins, point_like=True, extname="RAD_MAX", **header_cards, ): """ Create a fits binary table HDU in GADF format for the directional cut. See the specification at https://gamma-astro-data-formats.readthedocs.io/en/latest/irfs/full_enclosure/aeff/index.html Parameters ---------- rad_max: astropy.units.Quantity[angle] Array of the directional (theta) cut. Must have shape (n_reco_energy_bins, n_fov_offset_bins) reco_energy_bins: astropy.units.Quantity[energy] Bin edges in reconstructed energy fov_offset_bins: astropy.units.Quantity[angle] Bin edges in the field of view offset. For Point-Like IRFs, only giving a single bin is appropriate. extname: str Name for BinTableHDU **header_cards Additional metadata to add to the header, use this to set e.g. TELESCOP or INSTRUME. """ rad_max_table = QTable() rad_max_table["ENERG_LO"], rad_max_table[ "ENERG_HI"] = binning.split_bin_lo_hi( reco_energy_bins[np.newaxis, :].to(u.TeV)) rad_max_table["THETA_LO"], rad_max_table[ "THETA_HI"] = binning.split_bin_lo_hi( fov_offset_bins[np.newaxis, :].to(u.deg)) # transpose as FITS uses opposite dimension order rad_max_table["RAD_MAX"] = rad_max.T[np.newaxis, ...].to(u.deg) # required header keywords header = DEFAULT_HEADER.copy() header["HDUCLAS1"] = "RESPONSE" header["HDUCLAS2"] = "RAD_MAX" header["HDUCLAS3"] = "POINT-LIKE" header["HDUCLAS4"] = "RAD_MAX_2D" header["DATE"] = Time.now().utc.iso _add_header_cards(header, **header_cards) return BinTableHDU(rad_max_table, header=header, name=extname)
def test_io_ascii_write(): """ Test that table with mixin column can be written by io.ascii for every pure Python writer. No validation of the output is done, this just confirms no exceptions. """ from astropy.io.ascii.connect import _get_connectors_table t = QTable(MIXIN_COLS) for fmt in _get_connectors_table(): if fmt['Format'] == 'ascii.ecsv' and not HAS_YAML: continue if fmt['Write'] and '.fast_' not in fmt['Format']: out = StringIO() t.write(out, format=fmt['Format'])
def test_info_no_copy_numpy(): """Test that getting a single item from Table column object does not copy info. See #10889. """ col = [1, 2] t = QTable([col], names=['col']) t.add_index('col') val = t['col'][0] # Returns a numpy scalar (e.g. np.float64) with no .info assert isinstance(val, np.number) with pytest.raises(AttributeError): val.info val = t['col'][:] assert val.info.indices == []
def test_table_index_does_not_propagate_to_column_slices(col): # They lost contact to the parent table, so they should also not have # information on the indices; this helps prevent large memory usage if, # e.g., a large time column is turned into an object array; see gh-10688. tab = QTable() tab['t'] = col tab.add_index('t') t = tab['t'] assert t.info.indices tx = t[1:] assert not tx.info.indices tabx = tab[1:] t = tabx['t'] assert t.info.indices
def _model_params2table(self, fit_model, star_group): """ Place fitted parameters into an astropy table. Parameters ---------- fit_model : `astropy.modeling.Fittable2DModel` instance PSF or PRF model to fit the data. Could be one of the models in this package like `~photutils.psf.sandbox.DiscretePRF`, `~photutils.psf.IntegratedGaussianPRF`, or any other suitable 2D model. star_group : `~astropy.table.Table` the star group instance. Returns ------- param_tab : `~astropy.table.QTable` A table that contains the fitted parameters. """ param_tab = QTable() for param_tab_name in self._pars_to_output.keys(): param_tab.add_column( Column(name=param_tab_name, data=np.empty(len(star_group)))) if len(star_group) > 1: for i in range(len(star_group)): for param_tab_name, param_name in self._pars_to_output.items(): # get sub_model corresponding to star with index i as name # name was set in utils.get_grouped_psf_model() # we can't use model['name'] here as that only # searches leaves and we might want a intermediate # node of the tree sub_models = [ model for model in fit_model.traverse_postorder() if model.name == i ] if len(sub_models) != 1: raise ValueError('sub_models must have a length of 1') sub_model = sub_models[0] param_tab[param_tab_name][i] = getattr( sub_model, param_name).value else: for param_tab_name, param_name in self._pars_to_output.items(): param_tab[param_tab_name] = getattr(fit_model, param_name).value return param_tab
def get_gc_data(filename): gcs = Table.read(filename, format='ascii') gcs['x'] *= u.arcsec gcs['y'] *= u.arcsec gcs['V_los'] *= u.km / u.s gcs['dV_los'] *= u.km / u.s gcs['g-i'] *= u.mag gcs['dg-i'] *= u.mag gcs = QTable(gcs) n_gcs = len(gcs) gcs['r'] = np.sqrt(gcs['x']**2. + gcs['y']**2) return gcs
def __init__(self, data): self._table = QTable() # self.altkeys = {} # dictionary for alternative column names if (len(data.items()) == 1 and 'table' in data.keys()): # single item provided named 'table' -> already Table object self._table = QTable(data['table']) else: # treat kwargs as dictionary for key, val in data.items(): try: unit = val.unit val = val.value except AttributeError: unit = None # check if val is already list-like try: val[0] except (TypeError, IndexError): val = [val] self._table[key] = Column(val, unit=unit)
def test_table_contains_column(tmpdir): filename = str(tmpdir / 'test.hdf5') tbl = QTable() tbl['a'] = np.arange(10) * u.kpc tbl['b'] = np.arange(10) * u.km / u.s tbl['c'] = np.arange(10) * u.day tbl.write(filename, path=JokerSamples._hdf5_path, serialize_meta=True) with tb.open_file(filename, mode='r') as f: assert table_contains_column(f.root, 'a') assert table_contains_column(f.root, 'b') assert table_contains_column(f.root, 'c') assert not table_contains_column(f.root, 'd')
def test_table_header_to_units(tmpdir): filename = str(tmpdir / 'test.hdf5') tbl = QTable() tbl['a'] = np.arange(10) * u.kpc tbl['b'] = np.arange(10) * u.km / u.s tbl['c'] = np.arange(10) * u.day tbl.write(filename, path='test', serialize_meta=True) with tb.open_file(filename, mode='r') as f: units = table_header_to_units(f.root[meta_path('test')]) for col in tbl.colnames: assert tbl[col].unit == units[col]
def test_insert_row(mixin_cols): """ Test inserting a row, which only works for BaseColumn and Quantity """ t = QTable(mixin_cols) t['m'].info.description = 'd' if isinstance(t['m'], (u.Quantity, Column, time.Time)): t.insert_row(1, t[-1]) assert t[1] == t[-1] assert t['m'].info.description == 'd' else: with pytest.raises(ValueError) as exc: t.insert_row(1, t[-1]) assert "Unable to insert row" in str(exc.value)
def line_stats(self, x): """ Calculate statistics over individual line profiles. Parameters ---------- x : :class:`~u.Quantity` The input dispersion in either wavelength/frequency or velocity space. Returns ------- tab : :class:`~astropy.table.QTable` A table detailing the calculated statistics. """ tab = QTable(names=[ 'name', 'wave', 'col_dens', 'v_dop', 'delta_v', 'delta_lambda', 'ew', 'dv90', 'fwhm' ], dtype=('S10', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8', 'f8')) tab['wave'].unit = u.AA tab['v_dop'].unit = u.km / u.s tab['ew'].unit = u.AA tab['dv90'].unit = u.km / u.s tab['fwhm'].unit = u.AA tab['delta_v'].unit = u.km / u.s tab['delta_lambda'].unit = u.AA for line in self.lines: disp_equiv = u.spectral() + DOPPLER_CONVERT[ self.velocity_convention](line.lambda_0.quantity) with u.set_enabled_equivalencies(disp_equiv): vel = x.to('km/s') wav = x.to('Angstrom') # Generate the spectrum1d object for this line profile ew = equivalent_width(wav, line(wav)) dv90 = delta_v_90(vel, line(wav)) fwhm = full_width_half_max(wav, line(wav)) tab.add_row([ line.name, line.lambda_0, line.column_density, line.v_doppler, line.delta_v, line.delta_lambda, ew, dv90, fwhm ]) return tab
def create_aeff2d_hdu( effective_area, true_energy_bins, fov_offset_bins, extname="EFFECTIVE AREA", point_like=True, **header_cards, ): """ Create a fits binary table HDU in GADF format for effective area. See the specification at https://gamma-astro-data-formats.readthedocs.io/en/latest/irfs/full_enclosure/aeff/index.html Parameters ---------- effective_area: astropy.units.Quantity[area] Effective area array, must have shape (n_energy_bins, n_fov_offset_bins) true_energy_bins: astropy.units.Quantity[energy] Bin edges in true energy fov_offset_bins: astropy.units.Quantity[angle] Bin edges in the field of view offset. For Point-Like IRFs, only giving a single bin is appropriate. point_like: bool If the provided effective area was calculated after applying a direction cut, pass ``True``, else ``False`` for a full-enclosure effective area. extname: str Name for BinTableHDU **header_cards Additional metadata to add to the header, use this to set e.g. TELESCOP or INSTRUME. """ aeff = QTable() aeff["ENERG_LO"] = u.Quantity(true_energy_bins[:-1], ndmin=2).to(u.TeV) aeff["ENERG_HI"] = u.Quantity(true_energy_bins[1:], ndmin=2).to(u.TeV) aeff["THETA_LO"] = u.Quantity(fov_offset_bins[:-1], ndmin=2).to(u.deg) aeff["THETA_HI"] = u.Quantity(fov_offset_bins[1:], ndmin=2).to(u.deg) # transpose because FITS uses opposite dimension order than numpy aeff["EFFAREA"] = effective_area.T[np.newaxis, ...].to(u.m**2) # required header keywords header = DEFAULT_HEADER.copy() header["HDUCLAS1"] = "RESPONSE" header["HDUCLAS2"] = "EFF_AREA" header["HDUCLAS3"] = "POINT-LIKE" if point_like else "FULL-ENCLOSURE" header["HDUCLAS4"] = "AEFF_2D" header["DATE"] = Time.now().utc.iso _add_header_cards(header, **header_cards) return BinTableHDU(aeff, header=header, name=extname)
def get_table(self, cache=True, show_progress=True, table_path=None): """ Download (and optionally cache) the `Exoplanet Orbit Database planets table <http://www.exoplanets.org>`_. Parameters ---------- cache : bool (optional) Cache exoplanet table to local astropy cache? Default is `True`. show_progress : bool (optional) Show progress of exoplanet table download (if no cached copy is available). Default is `True`. table_path : str (optional) Path to a local table file. Default `None` will trigger a download of the table from the internet. Returns ------- table : `~astropy.table.QTable` Table of exoplanet properties. """ if self._table is None: if table_path is None: table_path = download_file(EXOPLANETS_CSV_URL, cache=cache, show_progress=show_progress) exoplanets_table = ascii.read(table_path, fast_reader=False) # Store column of lowercase names for indexing: lowercase_names = [i.lower().replace(" ", "") for i in exoplanets_table['NAME'].data] exoplanets_table['NAME_LOWERCASE'] = lowercase_names exoplanets_table.add_index('NAME_LOWERCASE') # Create sky coordinate mixin column exoplanets_table['sky_coord'] = SkyCoord(ra=exoplanets_table['RA'] * u.hourangle, dec=exoplanets_table['DEC'] * u.deg) # Assign units to columns where possible for col in exoplanets_table.colnames: if col in self.param_units: # Check that unit is implemented in this version of astropy try: exoplanets_table[col].unit = u.Unit(self.param_units[col]) except ValueError: print(f"WARNING: Unit {self.param_units[col]} not recognised") self._table = QTable(exoplanets_table) return self._table
def mk_z1qso_table(milliq=None, outfil=None, only_new=True): """ Generate a binary FITS table of the new sources """ # Outfil if outfil is None: outfil = 'z1qso_new.fits' # Load objects and candidates z1qso, cand = load_z1qso(good_z=True) # New? if only_new: # Load observed targets with JXP cuts if milliq is None: milliq = load_milliq() # Match to known quasars print('Cross matching') mq_rad = SkyCoord(ra=milliq['RA'] * u.degree, dec=milliq['DEC'] * u.degree) zq_rad = SkyCoord(ra=z1qso['RA'] * u.degree, dec=z1qso['DEC'] * u.degree) idx, d2d, d3d = coords.match_coordinates_sky(zq_rad, mq_rad, nthneighbor=1) # New ones newq = d2d.to('arcsec').value > 5. z1qso = z1qso[newq] print('z1qa.mk_z1qso_table: Cleaning up..') # Rename columns, units, QTable z1qso = QTable(z1qso) #z1qso.rename_column('RAD', 'RA') #z1qso.rename_column('DECD', 'DEC') z1qso['RA'].unit = u.degree z1qso['DEC'].unit = u.degree # Clean up the names! for jj, iz1qso in enumerate(z1qso): pdb.set_trace() #z1qso['NAME'][jj] = xrad.dtos1( (iz1qso['RA'], iz1qso['DEC']), fmt=1) # Write print( 'z1qso_analy: Writing {:d} quasars to {:s} and compressing...'.format( len(z1qso), outfil)) xxf.table_to_fits(z1qso, outfil, compress=True, comment='z1QSO New QSOs')
def test_psplupsparser(tmpdir): f = tmpdir.mkdir('ion_sources').join('c_2.psplups') f.write( """ 1 2 2 0.000e+00 5.830e-04 2.900e+02 6.029e-11 5.015e-10 3.796e-09 7.844e-09 1.140e-08 1.433e-08 1.685e-08 1.906e-08 1.883e-08 -1 %filename: c_2.psplups %rates: Foster VJ, Keenan FP, Reid RHG, ADNDT 67, 99, 1997 %energies: From .elvlc file, experimental energies %comment: The rate coefficients are in units cm^3/s. %comment: Fits are valid for temperatures 2e3 to 4e5 K. %produced as part of the Arcetri/Cambridge/NRL 'CHIANTI' atomic data base collaboration % % Peter Young 15-May-2001 -1""") table = QTable( data=[[1], [2], [2], [0.0], [0.000583], [290.0], [ np.array([ 6.029e-11, 5.015e-10, 3.796e-09, 7.844e-09, 1.140e-08, 1.433e-08, 1.685e-08, 1.906e-08, 1.883e-08 ]) ]], names=PsplupsParser.headings, meta={ 'element': 'c', 'ion': 'c_2', 'filename': 'c_2.psplups', 'footer': "filename: c_2.psplups\nrates: Foster VJ, Keenan FP, Reid RHG, ADNDT 67, 99, 1997\nenergies: From .elvlc file, experimental energies\ncomment: The rate coefficients are in units cm^3/s.\ncomment: Fits are valid for temperatures 2e3 to 4e5 K.\nproduced as part of the Arcetri/Cambridge/NRL 'CHIANTI' atomic data base collaboration\nPeter Young 15-May-2001" }) for h, unit in zip(PsplupsParser.headings, PsplupsParser.units): table[h].unit = unit p = PsplupsParser('c_2.psplups', full_path=os.path.join(f.dirname, f.basename)) table_parsed = p.parse() for c in table.colnames: for row, row_parsed in zip(table[c], table_parsed[c]): test = row == row_parsed if isinstance(test, np.ndarray): assert np.all(test) else: assert test for k in ('footer', 'filename', 'element', 'ion'): assert table_parsed.meta[k] == table.meta[k] assert 'chianti_version' in table_parsed.meta assert 'descriptions' in table_parsed.meta
def test_dl3_energy_dependent_cuts(): temp_cuts = DL3Cuts() temp_cuts.gh_max_efficiency = 0.8 temp_cuts.theta_containment = 0.68 temp_cuts.alpha_containment = 0.68 temp_cuts.min_event_p_en_bin = 2 temp_data = QTable({ "gh_score": u.Quantity(np.tile(np.arange(0.35, 0.85, 0.05), 3)), "reco_energy": np.geomspace(50 * u.GeV, 50 * u.TeV, 30), "theta": u.Quantity(np.tile(np.arange(0.05, 0.35, 0.03), 3), unit=u.deg), "alpha": u.Quantity(np.tile(np.arange(5, 85, 8), 3), unit=u.deg), "tel_id": u.Quantity(np.repeat([1, 2, 3], 10)), "mc_type": u.Quantity(np.repeat([0], 30)), }) en_range = u.Quantity([0.01, 0.1, 1, 10, 100, np.inf], unit=u.TeV) theta_cut = temp_cuts.energy_dependent_theta_cuts( temp_data, en_range, ) gh_cut = temp_cuts.energy_dependent_gh_cuts( temp_data, en_range, ) alpha_cut = temp_cuts.energy_dependent_alpha_cuts( temp_data, en_range, ) data_th = temp_cuts.apply_energy_dependent_theta_cuts(temp_data, theta_cut) data_gh = temp_cuts.apply_energy_dependent_gh_cuts(temp_data, gh_cut) data_al = temp_cuts.apply_energy_dependent_alpha_cuts(temp_data, alpha_cut) assert theta_cut["cut"][0] == 0.0908 * u.deg assert gh_cut["cut"][1] == 0.3725 assert alpha_cut["cut"][0] == 15.88 * u.deg assert len(data_th) == 21 assert len(data_gh) == 26 assert len(data_al) == 14
def test_mutable_operations(T1): """ Operations like adding or deleting a row should removing grouping, but adding or removing or renaming a column should retain grouping. """ for masked in (False, True): t1 = QTable(T1, masked=masked) # add row tg = t1.group_by('a') tg.add_row((0, 'a', 3.0, 4, 4 * u.m)) assert np.all(tg.groups.indices == np.array([0, len(tg)])) assert tg.groups.keys is None # remove row tg = t1.group_by('a') tg.remove_row(4) assert np.all(tg.groups.indices == np.array([0, len(tg)])) assert tg.groups.keys is None # add column tg = t1.group_by('a') indices = tg.groups.indices.copy() tg.add_column(Column(name='e', data=np.arange(len(tg)))) assert np.all(tg.groups.indices == indices) assert np.all(tg['e'].groups.indices == indices) assert np.all(tg['e'].groups.keys == tg.groups.keys) # remove column (not key column) tg = t1.group_by('a') tg.remove_column('b') assert np.all(tg.groups.indices == indices) # Still has original key col names assert tg.groups.keys.dtype.names == ('a', ) assert np.all(tg['a'].groups.indices == indices) # remove key column tg = t1.group_by('a') tg.remove_column('a') assert np.all(tg.groups.indices == indices) assert tg.groups.keys.dtype.names == ('a', ) assert np.all(tg['b'].groups.indices == indices) # rename key column tg = t1.group_by('a') tg.rename_column('a', 'aa') assert np.all(tg.groups.indices == indices) assert tg.groups.keys.dtype.names == ('a', ) assert np.all(tg['aa'].groups.indices == indices)
def test_votable_quantity_write(tmpdir): """ Test that table with Quantity mixin column can be round-tripped by io.votable. Note that FITS and HDF5 mixin support are tested (much more thoroughly) in their respective subpackage tests (io/fits/tests/test_connect.py and io/misc/tests/test_hdf5.py). """ t = QTable() t['a'] = u.Quantity([1, 2, 4], unit='Angstrom') filename = str(tmpdir.join('table-tmp')) t.write(filename, format='votable', overwrite=True) qt = QTable.read(filename, format='votable') assert isinstance(qt['a'], u.Quantity) assert qt['a'].unit == 'Angstrom'
def test_rename_mixin_columns(mixin_cols): """ Rename a mixin column. """ t = QTable(mixin_cols) tc = t.copy() t.rename_column('m', 'mm') assert t.colnames == ['i', 'a', 'b', 'mm'] if isinstance(t['mm'], table_helpers.ArrayWrapper): assert np.all(t['mm'].data == tc['m'].data) elif isinstance(t['mm'], coordinates.SkyCoord): assert np.all(t['mm'].ra == tc['m'].ra) assert np.all(t['mm'].dec == tc['m'].dec) else: assert np.all(t['mm'] == tc['m'])
def test_info_no_copy_mixin_with_index(col): """Test that getting a single item from Table column object does not copy info. See #10889. """ t = QTable([col], names=['col']) t.add_index('col') val = t['col'][0] assert 'info' not in val.__dict__ assert val.info.indices == [] val = t['col'][:] assert 'info' in val.__dict__ assert val.info.indices == [] val = t[:]['col'] assert 'info' in val.__dict__ assert isinstance(val.info.indices[0], SlicedIndex)