def model_errors(catmag, band, sigma=3., mode='mag', trange=[1, 1600]): """ Give upper and lower expected bounds as a function of the nominal magnitude of a source. Very useful for identifying outliers. :param catmag: Nominal AB magnitude of the source. :type catmag: float :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param sigma: How many sigma out to set the bounds. :type sigma: float :param mode: Units in which to report bounds. Either 'cps' or 'mag'. :type mode: str :param trange: Set of integration times to compute the bounds on, in seconds. :type trange: list :returns: tuple -- A two-element tuple containing the lower and upper bounds, respectively. """ if mode != 'cps' and mode != 'mag': print('mode must be set to "cps" or "mag"') exit(0) x = np.arange(trange[0], trange[1]) cnt = gt.mag2counts(catmag, band) ymin = (cnt * x / x) - sigma * np.sqrt(cnt * x) / x ymax = (cnt * x / x) + sigma * np.sqrt(cnt * x) / x if mode == 'mag': ymin = gt.counts2mag(ymin, band) ymax = gt.counts2mag(ymax, band) return ymin, ymax
def model_errors(catmag, band, sigma=3., mode='mag', trange=[1, 1600]): """ Give upper and lower expected bounds as a function of the nominal magnitude of a source. Very useful for identifying outliers. :param catmag: Nominal AB magnitude of the source. :type catmag: float :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param sigma: How many sigma out to set the bounds. :type sigma: float :param mode: Units in which to report bounds. Either 'cps' or 'mag'. :type mode: str :param trange: Set of integration times to compute the bounds on, in seconds. :type trange: list :returns: tuple -- A two-element tuple containing the lower and upper bounds, respectively. """ if mode != 'cps' and mode != 'mag': print('mode must be set to "cps" or "mag"') exit(0) x = np.arange(trange[0], trange[1]) cnt = gt.mag2counts(catmag, band) ymin = (cnt*x/x)-sigma*np.sqrt(cnt*x)/x ymax = (cnt*x/x)+sigma*np.sqrt(cnt*x)/x if mode == 'mag': ymin = gt.counts2mag(ymin, band) ymax = gt.counts2mag(ymax, band) return ymin, ymax
def get_inff(lc, clipsigma=3, quiet=True, band='NUV', binsize=30.): """ Calculates the Instantaneous Non-Flare Flux values. """ sclip = sigma_clip(np.array(lc['cps']), sigma=clipsigma) inff = np.ma.median(sclip) inff_err = np.sqrt(inff * len(sclip) * binsize) / (len(sclip) * binsize) if inff and not quiet: print('Quiescent at {m} AB mag.'.format(m=gt.counts2mag(inff, band))) return inff, inff_err
def apcorrect_cps(lc, band, aper=gt.aper2deg(7)): """ Apply the aperture correction in units of linear counts-per-second. Aperture correction is linear in magnitude units, so convert the count rate into AB mag, correct it, and then convert it back. """ return (gt.mag2counts( gt.counts2mag(lc['cps'].values, band) - gt.apcorrect1(aper, band), band))
def data_errors(catmag, band, t, sigma=3., mode='mag'): """ Given an array (of counts or mags), return an array of n-sigma error values. :param catmag: Nominal AB magnitude of the source. :type catmag: float :param t: Set of integration times to compute the bounds on, in seconds. :type t: list @CHASE - is this scalar or list? Also, consider trange instead of t to match first method?@ :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param sigma: How many sigma out to set the bounds. :type sigma: float :param mode: Units in which to report bounds. Either 'cps' or 'mag'. :type mode: str :returns: tuple -- A two-element tuple containing the lower and upper uncertainty, respectively. """ if mode != 'cps' and mode != 'mag': print('mode must be set to "cps" or "mag"') exit(0) cnt = gt.mag2counts(catmag, band) ymin = (cnt * t / t) - sigma * np.sqrt(cnt * t) / t ymax = (cnt * t / t) + sigma * np.sqrt(cnt * t) / t if mode == 'mag': ymin = gt.counts2mag(ymin, band) ymax = gt.counts2mag(ymax, band) return ymin, ymax
def data_errors(catmag, band, t, sigma=3., mode='mag'): """ Given an array (of counts or mags), return an array of n-sigma error values. :param catmag: Nominal AB magnitude of the source. :type catmag: float :param t: Set of integration times to compute the bounds on, in seconds. :type t: list @CHASE - is this scalar or list? Also, consider trange instead of t to match first method?@ :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param sigma: How many sigma out to set the bounds. :type sigma: float :param mode: Units in which to report bounds. Either 'cps' or 'mag'. :type mode: str :returns: tuple -- A two-element tuple containing the lower and upper uncertainty, respectively. """ if mode != 'cps' and mode != 'mag': print('mode must be set to "cps" or "mag"') exit(0) cnt = gt.mag2counts(catmag, band) ymin = (cnt*t/t)-sigma*np.sqrt(cnt*t)/t ymax = (cnt*t/t)+sigma*np.sqrt(cnt*t)/t if mode == 'mag': ymin = gt.counts2mag(ymin, band) ymax = gt.counts2mag(ymax, band) return ymin, ymax
def dmag_errors(t, band, sigma=3., mode='mag', mags=np.arange(13, 24, 0.1)): """ Given an exposure time, give dmag error bars at a range of magnitudes. :param t: Set of integration times to compute the bounds on, in seconds. :type t: list @CHASE - is this scalar or list? Also, consider trange instead of t to match first method?@ :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param sigma: How many sigma out to set the bounds. :type sigma: float :param mode: Units in which to report bounds. Either 'cps' or 'mag'. :type mode: str :param mags: Set of magnitudes to compute uncertainties on. :type mags: numpy.ndarray :returns: tuple -- A three-element tuple containing the magnitudes and their lower and upper uncertainties, respectively. """ cnts = gt.mag2counts(mags, band) * t ymin = (cnts - sigma / np.sqrt(cnts)) / t ymax = (cnts + sigma / np.sqrt(cnts)) / t if mode == 'mag': ymin = mags - gt.counts2mag(ymin, band) ymax = mags - gt.counts2mag(ymax, band) return mags, ymin, ymax
def dmag_errors(t, band, sigma=3., mode='mag', mags=np.arange(13, 24, 0.1)): """ Given an exposure time, give dmag error bars at a range of magnitudes. :param t: Set of integration times to compute the bounds on, in seconds. :type t: list @CHASE - is this scalar or list? Also, consider trange instead of t to match first method?@ :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param sigma: How many sigma out to set the bounds. :type sigma: float :param mode: Units in which to report bounds. Either 'cps' or 'mag'. :type mode: str :param mags: Set of magnitudes to compute uncertainties on. :type mags: numpy.ndarray :returns: tuple -- A three-element tuple containing the magnitudes and their lower and upper uncertainties, respectively. """ cnts = gt.mag2counts(mags, band)*t ymin = (cnts-sigma/np.sqrt(cnts))/t ymax = (cnts+sigma/np.sqrt(cnts))/t if mode == 'mag': ymin = mags-gt.counts2mag(ymin, band) ymax = mags-gt.counts2mag(ymax, band) return mags, ymin, ymax
def calculate_flare_energy(lc, frange, distance, binsize=30, band='NUV', effective_widths={ 'NUV': 729.94, 'FUV': 255.45 }, quiescence=None): """ Calculates the energy of a flare in erg. """ if not quiescence: q, _ = get_inff(lc) # Convert to aperture-corrected flux q = gt.mag2counts( gt.counts2mag(q, band) - gt.apcorrect1(gt.aper2deg(6), band), band) else: q = quiescence[0] # Convert from parsecs to cm distance_cm = distance * 3.086e+18 if 'cps_apcorrected' in lc.keys(): # Converting from counts / sec to flux units. flare_flux = (np.array( gt.counts2flux(np.array(lc.iloc[frange]['cps_apcorrected']), band)) - gt.counts2flux(q, band)) else: # Really need to have aperture-corrected counts/sec. raise ValueError("Need aperture-corrected cps fluxes to continue.") # Zero any flux values where the flux is below the INFF so that we don't subtract from the total flux! flare_flux = np.array([0 if f < 0 else f for f in flare_flux]) flare_flux_err = gt.counts2flux(np.array(lc.iloc[frange]['cps_err']), band) tbins = (np.array(lc.iloc[frange]['t1'].values) - np.array(lc.iloc[frange]['t0'].values)) # Caluclate the area under the curve. integrated_flux = (binsize * flare_flux).sum() """ GALEX effective widths from http://svo2.cab.inta-csic.es/svo/theory/fps3/index.php?id=GALEX/GALEX.NUV width = 729.94 A http://svo2.cab.inta-csic.es/svo/theory/fps3/index.php?id=GALEX/GALEX.FUV width = 255.45 A """ # Convert integrated flux to a fluence using the GALEX effective widths. fluence = integrated_flux * effective_widths[band] fluence_err = (np.sqrt( ((gt.counts2flux(lc.iloc[frange]['cps_err'], band) * binsize)** 2).sum()) * effective_widths[band]) energy = (4 * np.pi * (distance_cm**2) * fluence) energy_err = (4 * np.pi * (distance_cm**2) * fluence_err) return energy, energy_err
import gPhoton.galextools as gt magrange = np.arange(14, 24, 1) expt_ratio = 0.8 # Estimate of ration of effective to raw exposure time t_raw = np.arange(1, 1600, 1) t_eff = expt_ratio * t_raw for sigma in [1, 3]: fig = plt.figure(figsize=(8 * 2, 6 * 2)) for i, band in enumerate(['FUV', 'NUV']): plt.subplot(2, 1, i) plt.grid(b=True) plt.semilogx() plt.xlim(1, 1600) plt.title('{b} Detection Threshholds'.format(b=band)) plt.xlabel('Exposure Bin Depth (s)') plt.ylabel('{n} Sigma Error (AB Mag)'.format(n=sigma)) for mag in magrange: cps = gt.mag2counts(mag, band) cps_err = sigma * np.sqrt(cps * t_eff) / t_eff mag_err = mag - gt.counts2mag(cps + cps_err, band) plt.plot(t_raw, mag_err, label=mag) plt.legend() plt.savefig('GALEX {n} Sigma Detection Limits.png'.format(n=sigma))
def quickmag(band, ra0, dec0, tranges, radius, annulus=None, stepsz=None, verbose=0, detsize=1.25, coadd=False): """ Primary wrapper function for generating and synthesizing all of the parameters and calculations necessary to create light curves. :param band: The band being used, either 'FUV' or 'NUV'. :type band: str :param ra0: Right ascension, in degrees, of the target position. :type ra0: float :param dec0: Declination, in degrees, of the target position. :type dec0: float :param tranges: Set of time ranges to query within in GALEX time seconds. :type tranges: list :param radius: The radius of the photometric aperture, in degrees. :type radius: float :param annulus: Radii of the inner and outer extents of the background annulus, in degrees. :type annulus: list :param stepsz: The size of the time bins to use, in seconds. :type stepsz: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param detsize: Effective diameter, in degrees, of the field-of-view. :param coadd: Set to True if calculating a total flux instead of flux from each time bin. :type coadd: bool :returns: dict -- The light curve, including input parameters. """ if verbose: mc.print_inline("Retrieving all of the target events.") searchradius = radius if annulus is None else annulus[1] data = pullphotons(band, ra0, dec0, tranges, searchradius, verbose=verbose, detsize=detsize) if not data: return None if verbose: mc.print_inline("Binning data according to requested depth.") # Multiple ways of defining bins try: trange = [np.array(tranges).min(), np.array(tranges).max()] except ValueError: trange = tranges if coadd: bins = np.array(trange) elif stepsz: bins = np.append(np.arange(trange[0], trange[1], stepsz), max(trange)) else: bins = np.unique(np.array(tranges).flatten()) lcurve = {'params':gphot_params(band, [ra0, dec0], radius, annulus=annulus, verbose=verbose, detsize=detsize, stepsz=stepsz, trange=trange)} # This is equivalent in function to np.digitize(data['t'],bins) except # that it's much, much faster. See numpy issue #2656 at # https://github.com/numpy/numpy/issues/2656 bin_ix = np.searchsorted(bins, data['t'], "right") try: lcurve['t0'] = bins[np.unique(bin_ix)-1] lcurve['t1'] = bins[np.unique(bin_ix)] lcurve['exptime'] = np.array( dbt.compute_exptime(band, tranges if coadd else list(zip( lcurve['t0'], lcurve['t1'])), verbose=verbose, coadd=coadd, detsize=detsize, skypos=[ra0, dec0])) except IndexError: if np.isnan(data['t']): if verbose: mc.print_inline( "No valid data available in {t}".format(t=tranges)) lcurve['t0'] = np.array([np.nan]) lcurve['t1'] = np.array([np.nan]) lcurve['exptime'] = np.array([0]) angSep = mc.angularSeparation(ra0, dec0, data['ra'], data['dec']) aper_ix = np.where(angSep <= radius) lcurve['t0_data'] = reduce_lcurve(bin_ix, aper_ix, data['t'], np.min) lcurve['t1_data'] = reduce_lcurve(bin_ix, aper_ix, data['t'], np.max) lcurve['t_mean'] = reduce_lcurve(bin_ix, aper_ix, data['t'], np.mean) lcurve['q_mean'] = reduce_lcurve(bin_ix, aper_ix, data['q'], np.mean) lcurve['counts'] = reduce_lcurve(bin_ix, aper_ix, data['t'], len) lcurve['flat_counts'] = reduce_lcurve(bin_ix, aper_ix, 1./data['response'], np.sum) lcurve['responses'] = reduce_lcurve(bin_ix, aper_ix, data['response'], np.mean) lcurve['detxs'] = reduce_lcurve(bin_ix, aper_ix, data['col'], np.mean) lcurve['detys'] = reduce_lcurve(bin_ix, aper_ix, data['row'], np.mean) lcurve['detrad'] = mc.distance(lcurve['detxs'], lcurve['detys'], 400, 400) lcurve['racent'] = reduce_lcurve(bin_ix, aper_ix, data['ra'], np.mean) lcurve['deccent'] = reduce_lcurve(bin_ix, aper_ix, data['dec'], np.mean) skybgmcatdata = dbt.get_mcat_data([ra0, dec0], radius) lcurve['mcat_bg'] = lcurve['exptime']*np.array( [dbt.mcat_skybg(band, [ra0, dec0], radius, trange=tr, mcat=skybgmcatdata, verbose=verbose) for tr in zip(lcurve['t0'], lcurve['t1'])]) if annulus is not None: annu_ix = np.where((angSep > annulus[0]) & (angSep <= annulus[1])) lcurve['bg_counts'] = reduce_lcurve(bin_ix, annu_ix, data['t'], len) lcurve['bg_flat_counts'] = reduce_lcurve( bin_ix, annu_ix, data['response'], np.sum) lcurve['bg'] = (mc.area(radius)*lcurve['bg_flat_counts'] / (mc.area(annulus[1])-mc.area(annulus[0]))) else: lcurve['bg_counts'] = np.zeros(len(lcurve['counts'])) lcurve['bg_flat_counts'] = np.zeros(len(lcurve['counts'])) lcurve['bg'] = np.zeros(len(lcurve['counts'])) lcurve['cps'] = lcurve['flat_counts']/lcurve['exptime'] lcurve['cps_err'] = aperture_error(lcurve['flat_counts'], lcurve['exptime']) lcurve['cps_bgsub'] = (lcurve['flat_counts']- lcurve['bg'])/lcurve['exptime'] lcurve['cps_bgsub_err'] = aperture_error( lcurve['flat_counts'], lcurve['exptime'], bgcounts=lcurve['bg']) lcurve['cps_mcatbgsub'] = (lcurve['flat_counts']- lcurve['mcat_bg'])/lcurve['exptime'] lcurve['cps_mcatbgsub_err'] = aperture_error( lcurve['flat_counts'], lcurve['exptime'], bgcounts=lcurve['mcat_bg']) lcurve['flux'] = gxt.counts2flux(lcurve['cps'], band) lcurve['flux_err'] = gxt.counts2flux(lcurve['cps_err'], band) lcurve['flux_bgsub'] = gxt.counts2flux(lcurve['cps_bgsub'], band) lcurve['flux_bgsub_err'] = gxt.counts2flux(lcurve['cps_bgsub_err'], band) lcurve['flux_mcatbgsub'] = gxt.counts2flux(lcurve['cps_mcatbgsub'], band) lcurve['flux_mcatbgsub_err'] = gxt.counts2flux( lcurve['cps_mcatbgsub_err'], band) # NOTE: These conversions to mag can throw logarithm warnings if the # background is brighter than the source, resuling in a negative cps which # then gets propagated as a magnitude of NaN. lcurve['mag'] = gxt.counts2mag(lcurve['cps'], band) lcurve['mag_err_1'] = (lcurve['mag'] - gxt.counts2mag(lcurve['cps'] + lcurve['cps_err'], band)) lcurve['mag_err_2'] = (gxt.counts2mag(lcurve['cps'] - lcurve['cps_err'], band) - lcurve['mag']) lcurve['mag_bgsub'] = gxt.counts2mag(lcurve['cps_bgsub'], band) lcurve['mag_bgsub_err_1'] = (lcurve['mag_bgsub'] - gxt.counts2mag(lcurve['cps_bgsub'] + lcurve['cps_bgsub_err'], band)) lcurve['mag_bgsub_err_2'] = (gxt.counts2mag(lcurve['cps_bgsub'] - lcurve['cps_bgsub_err'], band) - lcurve['mag_bgsub']) lcurve['mag_mcatbgsub'] = gxt.counts2mag(lcurve['cps_mcatbgsub'], band) lcurve['mag_mcatbgsub_err_1'] = (lcurve['mag_mcatbgsub'] - gxt.counts2mag(lcurve['cps_mcatbgsub'] + lcurve['cps_mcatbgsub_err'], band)) lcurve['mag_mcatbgsub_err_2'] = (gxt.counts2mag(lcurve['cps_mcatbgsub'] - lcurve['cps_mcatbgsub_err'], band) - lcurve['mag_mcatbgsub']) lcurve['photons'] = data lcurve['flags'] = getflags(band, bin_ix, lcurve, verbose=verbose) return lcurve
def test_counts2mag_NUV(self): self.assertAlmostEqual(gt.counts2mag(10,'NUV'),-2.5*np.log10(10)+20.08)
def test_counts2mag_FUV(self): self.assertAlmostEqual(gt.counts2mag(10,'FUV'),-2.5*np.log10(10)+18.82)
def quickmag(band, ra0, dec0, tranges, radius, annulus=None, stepsz=None, verbose=0, detsize=1.25, coadd=False): """ Primary wrapper function for generating and synthesizing all of the parameters and calculations necessary to create light curves. :param band: The band being used, either 'FUV' or 'NUV'. :type band: str :param ra0: Right ascension, in degrees, of the target position. :type ra0: float :param dec0: Declination, in degrees, of the target position. :type dec0: float :param tranges: Set of time ranges to query within in GALEX time seconds. :type tranges: list :param radius: The radius of the photometric aperture, in degrees. :type radius: float :param annulus: Radii of the inner and outer extents of the background annulus, in degrees. :type annulus: list :param stepsz: The size of the time bins to use, in seconds. :type stepsz: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param detsize: Effective diameter, in degrees, of the field-of-view. :param coadd: Set to True if calculating a total flux instead of flux from each time bin. :type coadd: bool :returns: dict -- The light curve, including input parameters. """ if verbose: mc.print_inline("Retrieving all of the target events.") searchradius = radius if annulus is None else annulus[1] data = pullphotons(band, ra0, dec0, tranges, searchradius, verbose=verbose, detsize=detsize) if not data: return None if verbose: mc.print_inline("Binning data according to requested depth.") # Multiple ways of defining bins try: trange = [np.array(tranges).min(), np.array(tranges).max()] except ValueError: trange = tranges if coadd: bins = np.array(trange) elif stepsz: bins = np.append(np.arange(trange[0], trange[1], stepsz), max(trange)) else: bins = np.unique(np.array(tranges).flatten()) lcurve = { 'params': gphot_params(band, [ra0, dec0], radius, annulus=annulus, verbose=verbose, detsize=detsize, stepsz=stepsz, trange=trange) } # This is equivalent in function to np.digitize(data['t'],bins) except # that it's much, much faster. See numpy issue #2656 at # https://github.com/numpy/numpy/issues/2656 bin_ix = np.searchsorted(bins, data['t'], "right") try: lcurve['t0'] = bins[np.unique(bin_ix) - 1] lcurve['t1'] = bins[np.unique(bin_ix)] lcurve['exptime'] = np.array( dbt.compute_exptime( band, tranges if coadd else list(zip(lcurve['t0'], lcurve['t1'])), verbose=verbose, coadd=coadd, detsize=detsize, skypos=[ra0, dec0])) except IndexError: if np.isnan(data['t']): if verbose: mc.print_inline( "No valid data available in {t}".format(t=tranges)) lcurve['t0'] = np.array([np.nan]) lcurve['t1'] = np.array([np.nan]) lcurve['exptime'] = np.array([0]) angSep = mc.angularSeparation(ra0, dec0, data['ra'], data['dec']) aper_ix = np.where(angSep <= radius) lcurve['t0_data'] = reduce_lcurve(bin_ix, aper_ix, data['t'], np.min) lcurve['t1_data'] = reduce_lcurve(bin_ix, aper_ix, data['t'], np.max) lcurve['t_mean'] = reduce_lcurve(bin_ix, aper_ix, data['t'], np.mean) lcurve['q_mean'] = reduce_lcurve(bin_ix, aper_ix, data['q'], np.mean) lcurve['counts'] = reduce_lcurve(bin_ix, aper_ix, data['t'], len) lcurve['flat_counts'] = reduce_lcurve(bin_ix, aper_ix, 1. / data['response'], np.sum) lcurve['responses'] = reduce_lcurve(bin_ix, aper_ix, data['response'], np.mean) lcurve['detxs'] = reduce_lcurve(bin_ix, aper_ix, data['col'], np.mean) lcurve['detys'] = reduce_lcurve(bin_ix, aper_ix, data['row'], np.mean) lcurve['detrad'] = mc.distance(lcurve['detxs'], lcurve['detys'], 400, 400) lcurve['racent'] = reduce_lcurve(bin_ix, aper_ix, data['ra'], np.mean) lcurve['deccent'] = reduce_lcurve(bin_ix, aper_ix, data['dec'], np.mean) skybgmcatdata = dbt.get_mcat_data([ra0, dec0], radius) lcurve['mcat_bg'] = lcurve['exptime'] * np.array([ dbt.mcat_skybg(band, [ra0, dec0], radius, trange=tr, mcat=skybgmcatdata, verbose=verbose) for tr in zip(lcurve['t0'], lcurve['t1']) ]) if annulus is not None: annu_ix = np.where((angSep > annulus[0]) & (angSep <= annulus[1])) lcurve['bg_counts'] = reduce_lcurve(bin_ix, annu_ix, data['t'], len) lcurve['bg_flat_counts'] = reduce_lcurve(bin_ix, annu_ix, data['response'], np.sum) lcurve['bg'] = (mc.area(radius) * lcurve['bg_flat_counts'] / (mc.area(annulus[1]) - mc.area(annulus[0]))) else: lcurve['bg_counts'] = np.zeros(len(lcurve['counts'])) lcurve['bg_flat_counts'] = np.zeros(len(lcurve['counts'])) lcurve['bg'] = np.zeros(len(lcurve['counts'])) lcurve['cps'] = lcurve['flat_counts'] / lcurve['exptime'] lcurve['cps_err'] = aperture_error(lcurve['flat_counts'], lcurve['exptime']) lcurve['cps_bgsub'] = (lcurve['flat_counts'] - lcurve['bg']) / lcurve['exptime'] lcurve['cps_bgsub_err'] = aperture_error(lcurve['flat_counts'], lcurve['exptime'], bgcounts=lcurve['bg']) lcurve['cps_mcatbgsub'] = (lcurve['flat_counts'] - lcurve['mcat_bg']) / lcurve['exptime'] lcurve['cps_mcatbgsub_err'] = aperture_error(lcurve['flat_counts'], lcurve['exptime'], bgcounts=lcurve['mcat_bg']) lcurve['flux'] = gxt.counts2flux(lcurve['cps'], band) lcurve['flux_err'] = gxt.counts2flux(lcurve['cps_err'], band) lcurve['flux_bgsub'] = gxt.counts2flux(lcurve['cps_bgsub'], band) lcurve['flux_bgsub_err'] = gxt.counts2flux(lcurve['cps_bgsub_err'], band) lcurve['flux_mcatbgsub'] = gxt.counts2flux(lcurve['cps_mcatbgsub'], band) lcurve['flux_mcatbgsub_err'] = gxt.counts2flux(lcurve['cps_mcatbgsub_err'], band) # NOTE: These conversions to mag can throw logarithm warnings if the # background is brighter than the source, resuling in a negative cps which # then gets propagated as a magnitude of NaN. lcurve['mag'] = gxt.counts2mag(lcurve['cps'], band) lcurve['mag_err_1'] = ( lcurve['mag'] - gxt.counts2mag(lcurve['cps'] + lcurve['cps_err'], band)) lcurve['mag_err_2'] = ( gxt.counts2mag(lcurve['cps'] - lcurve['cps_err'], band) - lcurve['mag']) lcurve['mag_bgsub'] = gxt.counts2mag(lcurve['cps_bgsub'], band) lcurve['mag_bgsub_err_1'] = ( lcurve['mag_bgsub'] - gxt.counts2mag(lcurve['cps_bgsub'] + lcurve['cps_bgsub_err'], band)) lcurve['mag_bgsub_err_2'] = ( gxt.counts2mag(lcurve['cps_bgsub'] - lcurve['cps_bgsub_err'], band) - lcurve['mag_bgsub']) lcurve['mag_mcatbgsub'] = gxt.counts2mag(lcurve['cps_mcatbgsub'], band) lcurve['mag_mcatbgsub_err_1'] = (lcurve['mag_mcatbgsub'] - gxt.counts2mag( lcurve['cps_mcatbgsub'] + lcurve['cps_mcatbgsub_err'], band)) lcurve['mag_mcatbgsub_err_2'] = (gxt.counts2mag( lcurve['cps_mcatbgsub'] - lcurve['cps_mcatbgsub_err'], band) - lcurve['mag_mcatbgsub']) lcurve['photons'] = data lcurve['flags'] = getflags(band, bin_ix, lcurve, verbose=verbose) return lcurve
import gPhoton.galextools as gt magrange = np.arange(14,24,1) expt_ratio = 0.8 # Estimate of ration of effective to raw exposure time t_raw = np.arange(1,1600,1) t_eff = expt_ratio*t_raw for sigma in [1,3]: fig = plt.figure(figsize=(8*2,6*2)) for i,band in enumerate(['FUV','NUV']): plt.subplot(2,1,i) plt.grid(b=True) plt.semilogx() plt.xlim(1,1600) plt.title('{b} Detection Threshholds'.format(b=band)) plt.xlabel('Exposure Bin Depth (s)') plt.ylabel('{n} Sigma Error (AB Mag)'.format(n=sigma)) for mag in magrange: cps = gt.mag2counts(mag,band) cps_err = sigma*np.sqrt(cps*t_eff)/t_eff mag_err = mag-gt.counts2mag(cps+cps_err,band) plt.plot(t_raw,mag_err,label=mag) plt.legend() plt.savefig('GALEX {n} Sigma Detection Limits.png'.format(n=sigma))