def exp_from_objid(objid): """ Return the effective exposure time, start time, and end time from the MCAT for a given GALEX object ID. :param objid: GALEX object ID. :type objid: int :returns: dict -- The FUV and NUV effective exposure time and start/stop times. """ out = np.array(gQuery.getArray(gQuery.mcat_objid_search(objid))) return { 'NUV': { 'expt': np.array(out[:, 7], dtype='float')[0], 't0': np.array(out[:, 9], dtype='float64')[0] - GPSSECS, 't1': np.array(out[:, 10], dtype='float64')[0] - GPSSECS }, 'FUV': { 'expt': np.array(out[:, 8], dtype='float')[0], 't0': np.array(out[:, 11], dtype='float64')[0] - GPSSECS, 't1': np.array(out[:, 12], dtype='float64')[0] - GPSSECS } }
def caiwarning(band, bin_ix, events, verbose=0): """ Test whether a bin contains data from the first 3 legs of an FUV observation as part of the calibration (CAI) survey. :param band: The band being used, either 'FUV' or 'NUV'. :type band: str :param bin_ix: Array indices designating which events are in the time bin of interest. :type bin_ix: numpy.ndarray :param events: Set of photon events to check if they are near a masked detector region. :type events: dict :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int """ if band == 'FUV': for trange in dbt.distinct_tranges(np.array(events['photons']['t'])[bin_ix]): t = np.median(trange) obsdata = gQuery.getArray(gQuery.obstype_from_t(t)) if not obsdata: continue if (str(obsdata[0][0]) is 'CAI') and (obsdata[0][5] <= 3): return True return False
def caiwarning(band, bin_ix, events, verbose=0): """ Test whether a bin contains data from the first 3 legs of an FUV observation as part of the calibration (CAI) survey. :param band: The band being used, either 'FUV' or 'NUV'. :type band: str :param bin_ix: Array indices designating which events are in the time bin of interest. :type bin_ix: numpy.ndarray :param events: Set of photon events to check if they are near a masked detector region. :type events: dict :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int """ if band == 'FUV': for trange in dbt.distinct_tranges( np.array(events['photons']['t'])[bin_ix]): t = np.median(trange) obsdata = gQuery.getArray(gQuery.obstype_from_t(t)) if not obsdata: continue if (str(obsdata[0][0]) is 'CAI') and (obsdata[0][5] <= 3): return True return False
def obstype(t, obsdata=None): """ Determines the type of dither pattern. """ if not obsdata: obsdata = gQuery.getArray(gQuery.obstype_from_t(t)) try: return str(obsdata[0][0]) except IndexError: return "Unknown"
def legnum(t, obsdata=None): """ Returns the lef number. """ if not obsdata: obsdata = gQuery.getArray(gQuery.obstype_from_t(t)) try: return obsdata[0][5] except IndexError: return "Unknown"
def get_aspect(band, skypos, trange=[6e8, 11e8], verbose=0, detsize=1.25): """ Get aspect solution in a dict() for the given time range. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param skypos: The right ascension and declination, in degrees. :type skypos: list :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param detsize: The effective detector diameter, in degrees. :type detsize: float :returns: dict -- The aspect solution parameters. """ asp = np.array( gQuery.getArray(gQuery.aspect_skypos(skypos[0], skypos[1], detsize=detsize), verbose=verbose)) data = { 'eclipse': np.array(asp[:, 0], dtype='int16'), 'filename': asp[:, 1], 't': np.array(asp[:, 2], dtype='float64') / tscale, 'ra': np.array(asp[:, 3], dtype='float64'), 'dec': np.array(asp[:, 4], dtype='float64'), 'twist': np.array(asp[:, 5], dtype='float64'), 'flag': np.array(asp[:, 6], dtype='int8'), 'ra0': np.array(asp[:, 7], dtype='float64'), 'dec0': np.array(asp[:, 8], dtype='float64'), 'twist0': np.array(asp[:, 9], dtype='float64') } ix = np.where((data['t'] > trange[0]) & (data['t'] < trange[1]) & (angularSeparation(skypos[0], skypos[1], data['ra'], data['dec']) <= detsize / 2.)) for key in list(data.keys()): data[key] = data[key][ix] return data
def avg_sources(band, skypos, radius=0.001, maglimit=20.0, verbose=0, catalog='MCAT'): """ Return the mean position of sources within the search radius. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param skypos: The right ascension and declination, in degrees. :type skypos: list :param radius: The radius within which to search for MCAT sources, in degrees? :type radius: float :param maglimit: The NUV faint limit to return unique sources for. :type maglimit: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param catalog: The name of the catalog to query. :type catalog: str :returns: tuple -- A three-element tuple containing the mean RA, mean DEC, and mean FWHM of sources within the search radius. """ out = np.array( gQuery.getArray(gQuery.mcat_sources(band, skypos[0], skypos[1], radius, maglimit=maglimit), verbose=verbose)) ix = np.where(out[:, -2] > 0) if band == 'NUV' else np.where( out[:, -1] > 0) fwhm = out[ix, -2].mean() if band == 'NUV' else out[ix, -1].mean() return out[ix, 0].mean(), out[ix, 1].mean(), round(fwhm, 4)
def nearest_distinct_source(band, skypos, radius=0.1, maglimit=20.0, verbose=0, catalog='MCAT'): """ Return parameters for the nearest non-targeted source. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param skypos: The right ascension and declination, in degrees. :type skypos: list :param radius: The radius within which to search for the nearest MCAT source, in degrees. :type radius: float :param maglimit: The NUV faint limit to return unique sources for. :type maglimit: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param catalog: The name of the catalog to query. :type catalog: str :returns: numpy.ndarray -- Catalog values for the nearest non-targeted source. """ out = np.array( gQuery.getArray(gQuery.mcat_sources(band, skypos[0], skypos[1], radius, maglimit=maglimit), verbose=verbose)) dist = angularSeparation(out[:, 0], out[:, 1], skypos[0], skypos[1]) ix = np.where(dist > 0.005) return np.array(out)[ix][np.where(dist[ix] == dist[ix].min())][0]
def globalcount_shuttered(band, trange, verbose=0, timestamplist=False): """ Global event counts over the time range, exluding shuttered periods (due to no non-NULL data). :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param timestamplist: Global event time stamps. :type timestamplist: list :returns: int -- Total global counts excluding shuttered periods. """ try: t = (timestamplist if np.array(timestamplist).any() else np.array(gQuery.getArray(gQuery.uniquetimes( band, trange[0], trange[1], flag=True), verbose=verbose), dtype='float64')[:, 0] / gQuery.tscale) except IndexError: # Shutter this whole time range. if verbose: print_inline('No data in {t0},{t1}'.format(t0=trange[0], t1=trange[1])) return 0 times = np.sort(np.unique(np.append(t, trange))) tranges = distinct_tranges(times, maxgap=0.05) nonnullevents, nullevents = 0, 0 for trange in tranges: nullevents += gQuery.getValue(gQuery.deadtime2(band, trange[0], trange[1]), verbose=verbose) nonnullevents += gQuery.getValue(gQuery.deadtime1( band, trange[0], trange[1]), verbose=verbose) return nullevents + nonnullevents
def web_query_aspect(eclipse, retries=20): """ Grabs the aspect data from MAST databases based on eclipse. :param eclipse: The number of the eclipse to retrieve aspect files for. :type eclipse: int :param retries: The number of times to retry a query before giving up. :type retries: int :returns: tuple -- Returns a six-element tuple containing the RA, DEC, twist (roll), time, header, and aspect flags. Each of these EXCEPT for header, are returned as numpy.ndarrays. The header is returned as a dict containing the RA, DEC, and roll from the headers of the aspec files in numpy.ndarrays. """ print("Attempting to query MAST database for aspect records.") entries = gQuery.getArray(gQuery.aspect_ecl(eclipse), retries=retries) n = len(entries) print(' Located '+str(n)+' aspect entries.') if not n: print("No aspect entries for eclipse "+str(eclipse)) return ra, dec, twist, time, flags = [], [], [], [], [] header = {'RA':[], 'DEC':[], 'ROLL':[]} ra0, dec0, twist0 = [], [], [] for i in range(n): # The times are *1000 in the database to integerify time.append(float(entries[i][2])/1000.) ra.append(float(entries[i][3])) dec.append(float(entries[i][4])) twist.append(float(entries[i][5])) flags.append(float(entries[i][6])) ra0.append(float(entries[i][7])) dec0.append(float(entries[i][8])) twist0.append(float(entries[i][9])) # Need to sort the output so that it is time ordered before returning. # Although it should already be ordered by time because that is requested # in the SQL query above. If this is time consuming, remove it. ix = np.argsort(np.array(time)) header = ({'RA':np.array(ra0)[ix], 'DEC':np.array(dec0)[ix], 'ROLL':np.array(twist0)[ix]}) return (np.array(ra)[ix], np.array(dec)[ix], np.array(twist)[ix], np.array(time)[ix], header, np.array(flags)[ix])
def get_aspect(band, skypos, trange=[6e8, 11e8], verbose=0, detsize=1.25): """ Get aspect solution in a dict() for the given time range. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param skypos: The right ascension and declination, in degrees. :type skypos: list :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param detsize: The effective detector diameter, in degrees. :type detsize: float :returns: dict -- The aspect solution parameters. """ asp = np.array(gQuery.getArray(gQuery.aspect_skypos(skypos[0], skypos[1], detsize=detsize), verbose=verbose)) data = {'eclipse':np.array(asp[:, 0], dtype='int16'), 'filename':asp[:, 1], 't':np.array(asp[:, 2], dtype='float64')/tscale, 'ra':np.array(asp[:, 3], dtype='float64'), 'dec':np.array(asp[:, 4], dtype='float64'), 'twist':np.array(asp[:, 5], dtype='float64'), 'flag':np.array(asp[:, 6], dtype='int8'), 'ra0':np.array(asp[:, 7], dtype='float64'), 'dec0':np.array(asp[:, 8], dtype='float64'), 'twist0':np.array(asp[:, 9], dtype='float64')} ix = np.where((data['t'] > trange[0]) & (data['t'] < trange[1]) & (angularSeparation(skypos[0], skypos[1], data['ra'], data['dec']) <= detsize/2.)) for key in list(data.keys()): data[key] = data[key][ix] return data
def stimcount_shuttered(band, trange, verbose=0, timestamplist=False): """ Returns the stim count over a time range, excluding periods that the detector is considered shuttered (because of no non-NULL data). :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param timestamplist: Global detector event timestamps. :type timestamplist: list :returns: int -- Total stim counts excluding shuttered time ranges. """ try: t = (timestamplist if np.array(timestamplist).any() else np.array(gQuery.getArray(gQuery.uniquetimes(band, trange[0], trange[1]), verbose=verbose), dtype='float64')[:, 0]/gQuery.tscale) except IndexError: # Shutter this whole time range. if verbose: print_inline('No data in {t0},{t1}'.format(t0=trange[0], t1=trange[1])) return 0 times = np.sort(np.unique(np.append(t, trange))) tranges = distinct_tranges(times, maxgap=0.05) stimcount = 0 for trange in tranges: stimcount += (gQuery.getValue(gQuery.stimcount(band, trange[0], trange[1]), verbose=verbose) + gQuery.getValue(gQuery.stimcount(band, trange[0], trange[1], null=False), verbose=verbose)) return stimcount
def globalcount_shuttered(band, trange, verbose=0, timestamplist=False): """ Global event counts over the time range, exluding shuttered periods (due to no non-NULL data). :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param timestamplist: Global event time stamps. :type timestamplist: list :returns: int -- Total global counts excluding shuttered periods. """ try: t = (timestamplist if np.array(timestamplist).any() else np.array(gQuery.getArray(gQuery.uniquetimes(band, trange[0], trange[1], flag=True), verbose=verbose), dtype='float64')[:, 0]/gQuery.tscale) except IndexError: # Shutter this whole time range. if verbose: print_inline('No data in {t0},{t1}'.format(t0=trange[0], t1=trange[1])) return 0 times = np.sort(np.unique(np.append(t, trange))) tranges = distinct_tranges(times, maxgap=0.05) nonnullevents, nullevents = 0, 0 for trange in tranges: nullevents += gQuery.getValue( gQuery.deadtime2(band, trange[0], trange[1]), verbose=verbose) nonnullevents += gQuery.getValue(gQuery.deadtime1(band, trange[0], trange[1]), verbose=verbose) return nullevents+nonnullevents
def stimcount_shuttered(band, trange, verbose=0, timestamplist=False): """ Returns the stim count over a time range, excluding periods that the detector is considered shuttered (because of no non-NULL data). :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param timestamplist: Global detector event timestamps. :type timestamplist: list :returns: int -- Total stim counts excluding shuttered time ranges. """ try: t = (timestamplist if np.array(timestamplist).any() else np.array( gQuery.getArray(gQuery.uniquetimes(band, trange[0], trange[1]), verbose=verbose), dtype='float64')[:, 0] / gQuery.tscale) except IndexError: # Shutter this whole time range. if verbose: print_inline('No data in {t0},{t1}'.format(t0=trange[0], t1=trange[1])) return 0 times = np.sort(np.unique(np.append(t, trange))) tranges = distinct_tranges(times, maxgap=0.05) stimcount = 0 for trange in tranges: stimcount += (gQuery.getValue( gQuery.stimcount(band, trange[0], trange[1]), verbose=verbose) + gQuery.getValue(gQuery.stimcount( band, trange[0], trange[1], null=False), verbose=verbose)) return stimcount
def exposure(band, trange, verbose=0): """ Calculate the effective exposure time in a period, in seconds, accounting for shutter and deadtime. Does not account for actual sky coverage of the telescope during the time period queried (see: compute_exptime() below). :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :returns: float -- The effective exposure time, in seconds. """ rawexpt = trange[1] - trange[0] if rawexpt == 0.: return 0. try: t = (np.array(gQuery.getArray(gQuery.uniquetimes( band, trange[0], trange[1], flag=True), verbose=verbose), dtype='float64')[:, 0] / gQuery.tscale) except IndexError: # Shutter this whole time range. if verbose: print_inline('No data in {t0},{t1}'.format(t0=trange[0], t1=trange[1])) return 0. shutter = compute_shutter(band, trange, verbose=verbose, timestamplist=t) deadtime = empirical_deadtime(band, trange, verbose=verbose, timestamplist=t) return (rawexpt - shutter) * (1. - deadtime)
def compute_shutter(band, trange, verbose=0, shutgap=0.05, timestamplist=False): """ :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param shutgap: Amount of time, in seconds, that defines the minimum gap in observation that corresponds to a 'shutter' (not a true exposure time). :type shutgap: float :param timestamplist: Global event time stamps. :type timestamplist: list :returns: numpy.ndarray -- The total shutter time, in seconds, during the specified time range. """ try: t = (timestamplist if np.array(timestamplist).any() else np.array(gQuery.getArray(gQuery.uniquetimes( band, trange[0], trange[1], flag=True), verbose=verbose), dtype='float64')[:, 0] / gQuery.tscale) except IndexError: # Shutter this whole time range if there's no data return trange[1] - trange[0] t = np.sort(np.unique(np.append(t, trange))) ix = np.where(t[1:] - t[:-1] >= shutgap) return np.array(t[1:] - t[:-1])[ix].sum()
def avg_sources(band, skypos, radius=0.001, maglimit=20.0, verbose=0, catalog='MCAT'): """ Return the mean position of sources within the search radius. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param skypos: The right ascension and declination, in degrees. :type skypos: list :param radius: The radius within which to search for MCAT sources, in degrees? :type radius: float :param maglimit: The NUV faint limit to return unique sources for. :type maglimit: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param catalog: The name of the catalog to query. :type catalog: str :returns: tuple -- A three-element tuple containing the mean RA, mean DEC, and mean FWHM of sources within the search radius. """ out = np.array(gQuery.getArray(gQuery.mcat_sources(band, skypos[0], skypos[1], radius, maglimit=maglimit), verbose=verbose)) ix = np.where(out[:, -2] > 0) if band == 'NUV' else np.where(out[:, -1] > 0) fwhm = out[ix, -2].mean() if band == 'NUV' else out[ix, -1].mean() return out[ix, 0].mean(), out[ix, 1].mean(), round(fwhm, 4)
def nearest_distinct_source(band, skypos, radius=0.1, maglimit=20.0, verbose=0, catalog='MCAT'): """ Return parameters for the nearest non-targeted source. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param skypos: The right ascension and declination, in degrees. :type skypos: list :param radius: The radius within which to search for the nearest MCAT source, in degrees. :type radius: float :param maglimit: The NUV faint limit to return unique sources for. :type maglimit: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param catalog: The name of the catalog to query. :type catalog: str :returns: numpy.ndarray -- Catalog values for the nearest non-targeted source. """ out = np.array(gQuery.getArray(gQuery.mcat_sources(band, skypos[0], skypos[1], radius, maglimit=maglimit), verbose=verbose)) dist = angularSeparation(out[:, 0], out[:, 1], skypos[0], skypos[1]) ix = np.where(dist > 0.005) return np.array(out)[ix][np.where(dist[ix] == dist[ix].min())][0]
def obstype_from_objid(objid): """ Return the number of legs and petal value for a given GALEX object ID. :param objid: GALEX object ID. :type objid: int :returns: tuple -- A two-element tuple containing the number of legs and the petal value, which can be used to infer the observation type/strategy. """ out = gQuery.getArray(gQuery.obstype(objid)) (survey, tilename, photoextractid, petal, nlegs, leg, eclipse, img, subvis) = np.array(out)[0] return int(nlegs), int(petal)
def exposure(band, trange, verbose=0): """ Calculate the effective exposure time in a period, in seconds, accounting for shutter and deadtime. Does not account for actual sky coverage of the telescope during the time period queried (see: compute_exptime() below). :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :returns: float -- The effective exposure time, in seconds. """ rawexpt = trange[1]-trange[0] if rawexpt == 0.: return 0. try: t = (np.array(gQuery.getArray( gQuery.uniquetimes(band, trange[0], trange[1], flag=True), verbose=verbose), dtype='float64')[:, 0]/gQuery.tscale) except IndexError: # Shutter this whole time range. if verbose: print_inline('No data in {t0},{t1}'.format(t0=trange[0], t1=trange[1])) return 0. shutter = compute_shutter(band, trange, verbose=verbose, timestamplist=t) deadtime = empirical_deadtime(band, trange, verbose=verbose, timestamplist=t) return (rawexpt-shutter)*(1.-deadtime)
def compute_shutter(band, trange, verbose=0, shutgap=0.05, timestamplist=False): """ :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param shutgap: Amount of time, in seconds, that defines the minimum gap in observation that corresponds to a 'shutter' (not a true exposure time). :type shutgap: float :param timestamplist: Global event time stamps. :type timestamplist: list :returns: numpy.ndarray -- The total shutter time, in seconds, during the specified time range. """ try: t = (timestamplist if np.array(timestamplist).any() else np.array(gQuery.getArray(gQuery.uniquetimes(band, trange[0], trange[1], flag=True), verbose=verbose), dtype='float64')[:, 0]/gQuery.tscale) except IndexError: # Shutter this whole time range if there's no data return trange[1]-trange[0] t = np.sort(np.unique(np.append(t, trange))) ix = np.where(t[1:]-t[:-1] >= shutgap) return np.array(t[1:]-t[:-1])[ix].sum()
def exp_from_objid(objid): """ Return the effective exposure time, start time, and end time from the MCAT for a given GALEX object ID. :param objid: GALEX object ID. :type objid: int :returns: dict -- The FUV and NUV effective exposure time and start/stop times. """ out = np.array(gQuery.getArray(gQuery.mcat_objid_search(objid))) return {'NUV': {'expt':np.array(out[:, 7], dtype='float')[0], 't0':np.array(out[:, 9], dtype='float64')[0]-GPSSECS, 't1':np.array(out[:, 10], dtype='float64')[0]-GPSSECS}, 'FUV':{'expt':np.array(out[:, 8], dtype='float')[0], 't0':np.array(out[:, 11], dtype='float64')[0]-GPSSECS, 't1':np.array(out[:, 12], dtype='float64')[0]-GPSSECS}}
def nearest_source(band, skypos, radius=0.01, maglimit=20.0, verbose=0, catalog='MCAT'): """ Return targeting parameters for the nearest MCAT source to a position. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param skypos: The right ascension and declination, in degrees. :type skypos: list :param radius: The radius within which to search for the nearest MCAT source, in degrees. :type radius: float :param maglimit: The NUV faint limit to return unique sources for. :type maglimit: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param catalog: The name of the catalog to query. :type catalog: str :returns: tuple -- A three-element tuple containing the mean RA, mean DEC, and mean FWHM of the nearest sources within the search radius. """ out = np.array( gQuery.getArray(gQuery.mcat_sources(band, skypos[0], skypos[1], radius, maglimit=maglimit), verbose=verbose)) if not len(out) and band == 'FUV': if verbose: print("No nearby MCAT source found in FUV. Trying NUV...") band = 'NUV' out = np.array( gQuery.getArray(gQuery.mcat_sources(band, skypos[0], skypos[1], radius, maglimit=maglimit), verbose=verbose)) if not len(out) and band == 'NUV': if verbose: print("No nearby MCAT source found. Using input sky position.") return skypos[0], skypos[1], 0.01 dist = angularSeparation(out[:, 0], out[:, 1], skypos[0], skypos[1]) if verbose > 1: print("Finding nearest among " + str(len(dist)) + " nearby sources.") # Note that this doesn't cope with multiple entries for the same source. s = out[np.where(dist == dist.min())][0] return avg_sources(band, [s[0], s[1]], verbose=verbose)
def get_mcat_data(skypos, rad): """ Return visit-level MCAT sources and their catalog values within a give radius of the specified sky position. :param skypos: The right ascension and declination, in degrees, around which to search for MCAT sources. :type skypos: list :param rad: The radius within which to search for MCAT sources, in degrees. :type rad: float :returns: dict -- The MCAT sources within the specified radius. """ # Try once with the default radius. out = np.array(gQuery.getArray(gQuery.mcat_visit_sources(skypos[0], skypos[1], rad))) # If no MCAT sources found, try again with a radius 5 times bigger. if len(out) == 0: out = np.array(gQuery.getArray(gQuery.mcat_visit_sources(skypos[0], skypos[1], rad*5.))) # [Future]: The APER entries should really be generated. try: return {'objid':np.array(out[:, 0], dtype='int64'), 'ra':np.array(out[:, 1], dtype='float32'), 'dec':np.array(out[:, 2], dtype='float32'), 'NUV':{'mag':np.array(out[:, 3], dtype='float32'), 't0':np.array(out[:, 46], dtype='float64')-GPSSECS, 't1':np.array(out[:, 47], dtype='float64')-GPSSECS, 'skybg':np.array(out[:, 6], dtype='float32'), 'expt':np.array(out[:, 11], dtype='float32'), 'fwhm':np.array(out[:, 8], dtype='float32'), 'obssecs':np.array(out[:, 40], dtype='float64'), 'artifact':np.array(out[:, 42], dtype='int32'), 'ra':np.array(out[:, 50], dtype='float32'), 'dec':np.array(out[:, 51], dtype='float32'), 1:{'mag':np.array(out[:, 19], dtype='float32')+zpmag('NUV'), 'err':np.array(out[:, 33], dtype='float32')}, 2:{'mag':np.array(out[:, 20], dtype='float32')+zpmag('NUV'), 'err':np.array(out[:, 34], dtype='float32')}, 3:{'mag':np.array(out[:, 21], dtype='float32')+zpmag('NUV'), 'err':np.array(out[:, 35], dtype='float32')}, 4:{'mag':np.array(out[:, 22], dtype='float32')+zpmag('NUV'), 'err':np.array(out[:, 36], dtype='float32')}, 5:{'mag':np.array(out[:, 23], dtype='float32')+zpmag('NUV'), 'err':np.array(out[:, 37], dtype='float32')}, 6:{'mag':np.array(out[:, 24], dtype='float32')+zpmag('NUV'), 'err':np.array(out[:, 38], dtype='float32')}, 7:{'mag':np.array(out[:, 25], dtype='float32')+zpmag('NUV'), 'err':np.array(out[:, 39], dtype='float32')}}, 'FUV':{'mag':np.array(out[:, 4], dtype='float32'), 't0':np.array(out[:, 44], dtype='float64')-GPSSECS, 't1':np.array(out[:, 45], dtype='float64')-GPSSECS, 'skybg':np.array(out[:, 7], dtype='float32'), 'expt':np.array(out[:, 10], dtype='float32'), 'fwhm':np.array(out[:, 9], dtype='float32'), 'obssecs':np.array(out[:, 41], dtype='float64'), 'artifact':np.array(out[:, 43], dtype='int32'), 'ra':np.array(out[:, 48], dtype='float32'), 'dec':np.array(out[:, 49], dtype='float32'), 1:{'mag':np.array(out[:, 12], dtype='float32')+zpmag('FUV'), 'err':np.array(out[:, 26], dtype='float32')}, 2:{'mag':np.array(out[:, 13], dtype='float32')+zpmag('FUV'), 'err':np.array(out[:, 27], dtype='float32')}, 3:{'mag':np.array(out[:, 14], dtype='float32')+zpmag('FUV'), 'err':np.array(out[:, 28], dtype='float32')}, 4:{'mag':np.array(out[:, 15], dtype='float32')+zpmag('FUV'), 'err':np.array(out[:, 29], dtype='float32')}, 5:{'mag':np.array(out[:, 16], dtype='float32')+zpmag('FUV'), 'err':np.array(out[:, 30], dtype='float32')}, 6:{'mag':np.array(out[:, 17], dtype='float32')+zpmag('FUV'), 'err':np.array(out[:, 31], dtype='float32')}, 7:{'mag':np.array(out[:, 18], dtype='float32')+zpmag('FUV'), 'err':np.array(out[:, 32], dtype='float32')}}} except IndexError: # If there are STILL no detections, then pass a dict with empty values. # A default set of values will then be used. return {'objid':None, 'ra':None, 'dec':None, 'NUV':None, 'FUV':None} except: raise
def query_photons(band, ra0, dec0, tranges, radius, verbose=0, flag=0, detsize=1.25): """ Retrieve photons within an aperture from the database. :param band: Name of the band being used, either 'FUV' or 'NUV'. :type band: str :param ra0: Right ascension of the targeted sky position, in degrees. :type ra0: float :param dec0: Declination of the targeted sky position, in degrees. :type dec0: float :param tranges: Set of time ranges from which to retrieve photon events, in GALEX time units :type tranges: list :param radius: The radius, in degrees, defining a cone on the sky that is centered on ra0 and dec0, from which to extract photons. :type radius: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param flag: Photon list flag value upon which to select. Default of 0 corresponds to nominally corrected data with no issues. NOTE: 'Flag' is not a reliable way to parse data at this time. You should compare timestamps against the aspect file. :type flag: int :returns: dict -- The set of photon events with their properties. """ # [Future]: This should probably be moved to 'dbasetools'. stream = [] if verbose: mc.print_inline( "Retrieving photons within {rad} degrees of [{r}, {d}]".format( rad=radius, r=ra0, d=dec0)) for trange in tranges: if verbose: mc.print_inline(" and between {t0} and {t1}.".format(t0=trange[0], t1=trange[1])) # [Future]: This call to fGetTimeRanges prevents the downloading of # events with bad aspect solutions which currently have incorrect # quality flags (of zero) in the photon database. trs = dbt.fGetTimeRanges(band, [ra0, dec0], trange=trange, detsize=detsize) if not trs.any(): continue for tr in trs: thisstream = gQuery.getArray(gQuery.allphotons(band, ra0, dec0, tr[0], tr[1], radius, flag=flag), verbose=verbose, retries=100) stream.extend(thisstream) stream = np.array(stream, 'f8').T colnames = ['t', 'ra', 'dec', 'xi', 'eta', 'x', 'y', 'flag', 'q'] dtypes = ['f8', 'f8', 'f8', 'f4', 'f4', 'f4', 'f4', 'i4', 'f4'] try: cols = list(map(np.asarray, stream, dtypes)) events = dict(list(zip(colnames, cols))) # Adjust the timestamp by tscale. events['t'] /= tscale return events except TypeError: return None
def get_valid_times(band, skypos, trange=None, detsize=1.1, verbose=0, skyrange=None): """ Given a sky position and (optional) extent, return all of the times periods containing spatially intersecting observations. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param skypos: The right ascension and declination, in degrees. :type skypos: list :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param detsize: The effective detector diameter, in degrees. :type detsize: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param skyrange: Values in degrees RA and Dec of a box around skypos that defines the extent of the region of interest. :type skyrange: list :returns: numpy.ndarray -- A sorted set of unique time stamps. """ if not np.array(trange).tolist(): trange = [1, 1000000000000] if len(np.shape(trange)) == 2: trange = trange[0] # Assembles sky positions on a grid within the targeted region. # [Future]: This is probably not an optimally efficient way to check an # entire region of sky for data, but it's not hugely dumb and does work... skypos_list = [skypos] if skyrange: # This massive construction with the hstack and separate calls to # linspace is to ensure that skypos (i.e. the target position) is # always uniquely searched. # In a perfect world, you would probably divice detsize by 2. The # detsize is divided by 3 to make sure to oversample the search just a # little bit. for r in np.unique( np.hstack([np.linspace(skypos[0], skypos[0]+skyrange[0]/2., np.ceil(skyrange[0]/(detsize/3.)), endpoint=True), np.linspace(skypos[0], skypos[0]-skyrange[0]/2., np.ceil(skyrange[0]/(detsize/3.)), endpoint=True)])): for d in np.unique( np.hstack([np.linspace(skypos[1], skypos[1]+skyrange[1]/2., np.ceil(skyrange[1]/(detsize/3.)), endpoint=True), np.linspace(skypos[1], skypos[1]-skyrange[1]/2., np.ceil(skyrange[1]/(detsize/3.)), endpoint=True)])): skypos_list += [[r, d]] times = [] for skypos in skypos_list: try: times = (list(times) + list(np.array(gQuery.getArray( gQuery.exposure_ranges(band, skypos[0], skypos[1], t0=trange[0], t1=trange[1], detsize=detsize), verbose=verbose), dtype='float64')[:, 0]/tscale)) except IndexError: if verbose: print("No exposure time available at {pos}".format(pos=skypos)) return np.array([], dtype='float64') except TypeError: print("Is one of the inputs malformed?") raise except: raise # The following section should account for the fact that the use of band # in gQuery.exposure_ranges() doesn't seem to work like it should. # Specifically, it often returns time ranges as valid for FUV when there # are not actually any global events recorded by that detector. newtimes = [] try: aspranges = distinct_tranges(np.sort(np.unique(times))) except IndexError: return np.array([], dtype='float64') except: raise for trange in aspranges: photontimes = (np.array(gQuery.getArray( gQuery.uniquetimes(band, trange[0], trange[1], flag=0)), dtype='float64').flatten()/1000.) ix = np.where((photontimes.flatten() >= trange[0]) & (photontimes.flatten() < trange[1]+1)) if len(ix[0]): newtimes += np.arange(trange[0], trange[1]+1).tolist() return np.sort(np.unique(newtimes))
def get_valid_times(band, skypos, trange=None, detsize=1.1, verbose=0, skyrange=None): """ Given a sky position and (optional) extent, return all of the times periods containing spatially intersecting observations. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param skypos: The right ascension and declination, in degrees. :type skypos: list :param trange: Minimum and maximum time (in GALEX time) to consider. :type trange: list :param detsize: The effective detector diameter, in degrees. :type detsize: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param skyrange: Values in degrees RA and Dec of a box around skypos that defines the extent of the region of interest. :type skyrange: list :returns: numpy.ndarray -- A sorted set of unique time stamps. """ if not np.array(trange).tolist(): trange = [1, 1000000000000] if len(np.shape(trange)) == 2: trange = trange[0] # Assembles sky positions on a grid within the targeted region. # [Future]: This is probably not an optimally efficient way to check an # entire region of sky for data, but it's not hugely dumb and does work... skypos_list = [skypos] if skyrange: # This massive construction with the hstack and separate calls to # linspace is to ensure that skypos (i.e. the target position) is # always uniquely searched. # In a perfect world, you would probably divice detsize by 2. The # detsize is divided by 3 to make sure to oversample the search just a # little bit. for r in np.unique( np.hstack([ np.linspace(skypos[0], skypos[0] + skyrange[0] / 2., np.ceil(skyrange[0] / (detsize / 3.)), endpoint=True), np.linspace(skypos[0], skypos[0] - skyrange[0] / 2., np.ceil(skyrange[0] / (detsize / 3.)), endpoint=True) ])): for d in np.unique( np.hstack([ np.linspace(skypos[1], skypos[1] + skyrange[1] / 2., np.ceil(skyrange[1] / (detsize / 3.)), endpoint=True), np.linspace(skypos[1], skypos[1] - skyrange[1] / 2., np.ceil(skyrange[1] / (detsize / 3.)), endpoint=True) ])): skypos_list += [[r, d]] times = [] for skypos in skypos_list: try: times = (list(times) + list( np.array(gQuery.getArray(gQuery.exposure_ranges( band, skypos[0], skypos[1], t0=trange[0], t1=trange[1], detsize=detsize), verbose=verbose), dtype='float64')[:, 0] / tscale)) except IndexError: if verbose: print("No exposure time available at {pos}".format(pos=skypos)) return np.array([], dtype='float64') except TypeError: print("Is one of the inputs malformed?") raise except: raise # The following section should account for the fact that the use of band # in gQuery.exposure_ranges() doesn't seem to work like it should. # Specifically, it often returns time ranges as valid for FUV when there # are not actually any global events recorded by that detector. newtimes = [] try: aspranges = distinct_tranges(np.sort(np.unique(times))) except IndexError: return np.array([], dtype='float64') except: raise for trange in aspranges: photontimes = (np.array(gQuery.getArray( gQuery.uniquetimes(band, trange[0], trange[1], flag=0)), dtype='float64').flatten() / 1000.) ix = np.where((photontimes.flatten() >= trange[0]) & (photontimes.flatten() < trange[1] + 1)) if len(ix[0]): newtimes += np.arange(trange[0], trange[1] + 1).tolist() return np.sort(np.unique(newtimes))
def nearest_source(band, skypos, radius=0.01, maglimit=20.0, verbose=0, catalog='MCAT'): """ Return targeting parameters for the nearest MCAT source to a position. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param skypos: The right ascension and declination, in degrees. :type skypos: list :param radius: The radius within which to search for the nearest MCAT source, in degrees. :type radius: float :param maglimit: The NUV faint limit to return unique sources for. :type maglimit: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param catalog: The name of the catalog to query. :type catalog: str :returns: tuple -- A three-element tuple containing the mean RA, mean DEC, and mean FWHM of the nearest sources within the search radius. """ out = np.array(gQuery.getArray(gQuery.mcat_sources(band, skypos[0], skypos[1], radius, maglimit=maglimit), verbose=verbose)) if not len(out) and band == 'FUV': if verbose: print("No nearby MCAT source found in FUV. Trying NUV...") band = 'NUV' out = np.array(gQuery.getArray(gQuery.mcat_sources(band, skypos[0], skypos[1], radius, maglimit=maglimit), verbose=verbose)) if not len(out) and band == 'NUV': if verbose: print("No nearby MCAT source found. Using input sky position.") return skypos[0], skypos[1], 0.01 dist = angularSeparation(out[:, 0], out[:, 1], skypos[0], skypos[1]) if verbose > 1: print("Finding nearest among "+str(len(dist))+" nearby sources.") # Note that this doesn't cope with multiple entries for the same source. s = out[np.where(dist == dist.min())][0] return avg_sources(band, [s[0], s[1]], verbose=verbose)
def get_mags(band, ra0, dec0, radius, maglimit, mode='coadd', zpmag={'NUV':20.08, 'FUV':18.82}, verbose=1): """ Given RA, Dec and search radius, searches the coadd MCAT for sources. Returns a dict() which contains magnitudes for all of the APER settings. Note: Visit mode returns a lot more sources, more slowly than coadd mode given the same search parameters. You should probably use smaller search radii in visit mode. If you're just trying to find unique sources in a large region, use coadd mode and then pass the result through the parse_unique_sources() function contained in this module. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param ra0: The right ascension, in degrees, around which to search. :type ra0: float :param dec0: The declination, in degrees, around which to search. :type dec0: float :param radius: The size of the search radius for MCAT sources in degrees. :type radius: float :param maglimit: The NUV faint limit to return MCAT sources for. :type maglimit: float :param mode: Specify whether to return MCAT sources from the 'visit' or 'coadd' catalog. :type mode: str :param zpmag: The zero-point magnitude in FUV and NUV. :type zpmag: dict :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :returns: dict -- The set of magnitudes from different apertures for sources in the MCAT, centered around the specified coordinate. """ zpf, zpn = zpmag['FUV'], zpmag['NUV'] if mode == 'coadd': out = np.array(gQuery.getArray(gQuery.mcat_sources(band, ra0, dec0, radius, maglimit=maglimit), verbose=verbose)) if not len(out): if verbose: print("Warning: No sources found!") return None return {'ra':out[:, 0], 'dec':out[:, 1], 'FUV':{'mag':out[:, 3], 1:out[:, 9]+zpf, 2:out[:, 10]+zpf, 3:out[:, 11]+zpf, 4:out[:, 12]+zpf, 5:out[:, 13]+zpf, 6:out[:, 14], 7:out[:, 15]+zpf}, 'NUV':{'mag':out[:, 2], 1:out[:, 16]+zpn, 2:out[:, 17]+zpn, 3:out[:, 18]+zpn, 4:out[:, 19]+zpn, 5:out[:, 20]+zpn, 6:out[:, 21]+zpn, 7:out[:, 22]+zpn}} elif mode == 'visit': return get_mcat_data([ra0, dec0], radius) else: print("mode must be in [coadd,visit]") return None
def get_mcat_data(skypos, rad): """ Return visit-level MCAT sources and their catalog values within a give radius of the specified sky position. :param skypos: The right ascension and declination, in degrees, around which to search for MCAT sources. :type skypos: list :param rad: The radius within which to search for MCAT sources, in degrees. :type rad: float :returns: dict -- The MCAT sources within the specified radius. """ # Try once with the default radius. out = np.array( gQuery.getArray(gQuery.mcat_visit_sources(skypos[0], skypos[1], rad))) # If no MCAT sources found, try again with a radius 5 times bigger. if len(out) == 0: out = np.array( gQuery.getArray( gQuery.mcat_visit_sources(skypos[0], skypos[1], rad * 5.))) # [Future]: The APER entries should really be generated. try: return { 'objid': np.array(out[:, 0], dtype='int64'), 'ra': np.array(out[:, 1], dtype='float32'), 'dec': np.array(out[:, 2], dtype='float32'), 'NUV': { 'mag': np.array(out[:, 3], dtype='float32'), 't0': np.array(out[:, 46], dtype='float64') - GPSSECS, 't1': np.array(out[:, 47], dtype='float64') - GPSSECS, 'skybg': np.array(out[:, 6], dtype='float32'), 'expt': np.array(out[:, 11], dtype='float32'), 'fwhm': np.array(out[:, 8], dtype='float32'), 'obssecs': np.array(out[:, 40], dtype='float64'), 'artifact': np.array(out[:, 42], dtype='int32'), 'ra': np.array(out[:, 50], dtype='float32'), 'dec': np.array(out[:, 51], dtype='float32'), 1: { 'mag': np.array(out[:, 19], dtype='float32') + zpmag('NUV'), 'err': np.array(out[:, 33], dtype='float32') }, 2: { 'mag': np.array(out[:, 20], dtype='float32') + zpmag('NUV'), 'err': np.array(out[:, 34], dtype='float32') }, 3: { 'mag': np.array(out[:, 21], dtype='float32') + zpmag('NUV'), 'err': np.array(out[:, 35], dtype='float32') }, 4: { 'mag': np.array(out[:, 22], dtype='float32') + zpmag('NUV'), 'err': np.array(out[:, 36], dtype='float32') }, 5: { 'mag': np.array(out[:, 23], dtype='float32') + zpmag('NUV'), 'err': np.array(out[:, 37], dtype='float32') }, 6: { 'mag': np.array(out[:, 24], dtype='float32') + zpmag('NUV'), 'err': np.array(out[:, 38], dtype='float32') }, 7: { 'mag': np.array(out[:, 25], dtype='float32') + zpmag('NUV'), 'err': np.array(out[:, 39], dtype='float32') } }, 'FUV': { 'mag': np.array(out[:, 4], dtype='float32'), 't0': np.array(out[:, 44], dtype='float64') - GPSSECS, 't1': np.array(out[:, 45], dtype='float64') - GPSSECS, 'skybg': np.array(out[:, 7], dtype='float32'), 'expt': np.array(out[:, 10], dtype='float32'), 'fwhm': np.array(out[:, 9], dtype='float32'), 'obssecs': np.array(out[:, 41], dtype='float64'), 'artifact': np.array(out[:, 43], dtype='int32'), 'ra': np.array(out[:, 48], dtype='float32'), 'dec': np.array(out[:, 49], dtype='float32'), 1: { 'mag': np.array(out[:, 12], dtype='float32') + zpmag('FUV'), 'err': np.array(out[:, 26], dtype='float32') }, 2: { 'mag': np.array(out[:, 13], dtype='float32') + zpmag('FUV'), 'err': np.array(out[:, 27], dtype='float32') }, 3: { 'mag': np.array(out[:, 14], dtype='float32') + zpmag('FUV'), 'err': np.array(out[:, 28], dtype='float32') }, 4: { 'mag': np.array(out[:, 15], dtype='float32') + zpmag('FUV'), 'err': np.array(out[:, 29], dtype='float32') }, 5: { 'mag': np.array(out[:, 16], dtype='float32') + zpmag('FUV'), 'err': np.array(out[:, 30], dtype='float32') }, 6: { 'mag': np.array(out[:, 17], dtype='float32') + zpmag('FUV'), 'err': np.array(out[:, 31], dtype='float32') }, 7: { 'mag': np.array(out[:, 18], dtype='float32') + zpmag('FUV'), 'err': np.array(out[:, 32], dtype='float32') } } } except IndexError: # If there are STILL no detections, then pass a dict with empty values. # A default set of values will then be used. return { 'objid': None, 'ra': None, 'dec': None, 'NUV': None, 'FUV': None } except: raise
def query_photons(band, ra0, dec0, tranges, radius, verbose=0, flag=0, detsize=1.25): """ Retrieve photons within an aperture from the database. :param band: Name of the band being used, either 'FUV' or 'NUV'. :type band: str :param ra0: Right ascension of the targeted sky position, in degrees. :type ra0: float :param dec0: Declination of the targeted sky position, in degrees. :type dec0: float :param tranges: Set of time ranges from which to retrieve photon events, in GALEX time units :type tranges: list :param radius: The radius, in degrees, defining a cone on the sky that is centered on ra0 and dec0, from which to extract photons. :type radius: float :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :param flag: Photon list flag value upon which to select. Default of 0 corresponds to nominally corrected data with no issues. NOTE: 'Flag' is not a reliable way to parse data at this time. You should compare timestamps against the aspect file. :type flag: int :returns: dict -- The set of photon events with their properties. """ # [Future]: This should probably be moved to 'dbasetools'. stream = [] if verbose: mc.print_inline( "Retrieving photons within {rad} degrees of [{r}, {d}]".format( rad=radius, r=ra0, d=dec0)) for trange in tranges: if verbose: mc.print_inline(" and between {t0} and {t1}.".format(t0=trange[0], t1=trange[1])) # [Future]: This call to fGetTimeRanges prevents the downloading of # events with bad aspect solutions which currently have incorrect # quality flags (of zero) in the photon database. trs = dbt.fGetTimeRanges(band, [ra0, dec0], trange=trange, detsize=detsize) if not trs.any(): continue for tr in trs: thisstream = gQuery.getArray( gQuery.allphotons(band, ra0, dec0, tr[0], tr[1], radius, flag=flag), verbose=verbose, retries=100) stream.extend(thisstream) stream = np.array(stream, 'f8').T colnames = ['t', 'ra', 'dec', 'xi', 'eta', 'x', 'y', 'flag', 'q'] dtypes = ['f8', 'f8', 'f8', 'f4', 'f4', 'f4', 'f4', 'i4', 'f4'] try: cols = list(map(np.asarray, stream, dtypes)) events = dict(list(zip(colnames, cols))) # Adjust the timestamp by tscale. events['t'] /= tscale return events except TypeError: return None
def makemap(band, skypos, trange, skyrange, response=False, verbose=0, detsize=1.1): """ Generate a single image frame. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param skypos: The right ascension and declination, in degrees. :type skypos: list :param trange: Minimum and maximum time to use, in GALEX time seconds. :type trange: list :param skyrange: RA and Dec extent of the region of interest in degrees. :type skyrange: list :param response: Apply the response correction. :type response: bool :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. :type detsize: float :returns: numpy.ndarray - The bi-dimensional histogram of ra and dec. """ imsz = gxt.deg2pix(skypos, skyrange) photons = np.array(gQuery.getArray( gQuery.skyrect(band, skypos[0], skypos[1], trange[0], trange[1], skyrange[0], skyrange[1]), verbose=verbose), dtype='float64') try: events = {'t':photons[:, 0]/tscale, 'ra':photons[:, 1], 'dec':photons[:, 2], 'xi':photons[:, 3], 'eta':photons[:, 4], 'x':photons[:, 5], 'y':photons[:, 6]} except IndexError: if verbose > 2: print('No events found at {s} +/- {r} in {t}.'.format( s=skypos, r=skyrange, t=trange)) return np.zeros(np.array(imsz, dtype='int32')) # Trim the data on detsize col, row = ct.xieta2colrow(events['xi'], events['eta'], band) ix = np.where(gxt.aper2deg(4)*mc.distance(col, row, 400, 400) <= detsize) n = len(ix[0]) m = len(col) if n == 0: return np.zeros(np.int(imsz)) for k in list(events.keys()): events[k] = events[k][ix] events = ct.hashresponse(band, events) wcs = define_wcs(skypos, skyrange) coo = list(zip(events['ra'], events['dec'])) foc = wcs.sip_pix2foc(wcs.wcs_world2pix(coo, 1), 1) weights = 1./events['response'] if response else None H, xedges, yedges = np.histogram2d(foc[:, 1]-0.5, foc[:, 0]-0.5, bins=imsz, range=([[0, imsz[0]], [0, imsz[1]]]), weights=weights) return H
def get_mags(band, ra0, dec0, radius, maglimit, mode='coadd', zpmag={ 'NUV': 20.08, 'FUV': 18.82 }, verbose=1): """ Given RA, Dec and search radius, searches the coadd MCAT for sources. Returns a dict() which contains magnitudes for all of the APER settings. Note: Visit mode returns a lot more sources, more slowly than coadd mode given the same search parameters. You should probably use smaller search radii in visit mode. If you're just trying to find unique sources in a large region, use coadd mode and then pass the result through the parse_unique_sources() function contained in this module. :param band: The band to use, either 'FUV' or 'NUV'. :type band: str :param ra0: The right ascension, in degrees, around which to search. :type ra0: float :param dec0: The declination, in degrees, around which to search. :type dec0: float :param radius: The size of the search radius for MCAT sources in degrees. :type radius: float :param maglimit: The NUV faint limit to return MCAT sources for. :type maglimit: float :param mode: Specify whether to return MCAT sources from the 'visit' or 'coadd' catalog. :type mode: str :param zpmag: The zero-point magnitude in FUV and NUV. :type zpmag: dict :param verbose: Verbosity level, a value of 0 is minimum verbosity. :type verbose: int :returns: dict -- The set of magnitudes from different apertures for sources in the MCAT, centered around the specified coordinate. """ zpf, zpn = zpmag['FUV'], zpmag['NUV'] if mode == 'coadd': out = np.array( gQuery.getArray(gQuery.mcat_sources(band, ra0, dec0, radius, maglimit=maglimit), verbose=verbose)) if not len(out): if verbose: print("Warning: No sources found!") return None return { 'ra': out[:, 0], 'dec': out[:, 1], 'FUV': { 'mag': out[:, 3], 1: out[:, 9] + zpf, 2: out[:, 10] + zpf, 3: out[:, 11] + zpf, 4: out[:, 12] + zpf, 5: out[:, 13] + zpf, 6: out[:, 14], 7: out[:, 15] + zpf }, 'NUV': { 'mag': out[:, 2], 1: out[:, 16] + zpn, 2: out[:, 17] + zpn, 3: out[:, 18] + zpn, 4: out[:, 19] + zpn, 5: out[:, 20] + zpn, 6: out[:, 21] + zpn, 7: out[:, 22] + zpn } } elif mode == 'visit': return get_mcat_data([ra0, dec0], radius) else: print("mode must be in [coadd,visit]") return None