Source code for lcc.db_tier.vizier_tap_base

import requests

from lcc.db_tier.TAP_query import TapClient
from lcc.entities.exceptions import QueryInputError
from lcc.entities.light_curve import LightCurve
from lcc.entities.star import Star


[docs]class VizierTapBase(TapClient): ''' Base class for all tap connectors using VizieR database. In the most situations new connectors will contain just few class attributes and there will not be need to write new or overwrite current methods. Attributes ----------- TAP_URL : str Url to tap server FILES_URL : str Path to light curve files storage TABLE : str Name of queried table RA : str Name of right ascension column. It should be in degrees, anyway it is necessary to convert them DEC : str Name of declination column. It should be in degrees, anyway it is necessary to convert them NAME : preformated str Preformated string with dictionary keys. EXAMPLE -------- "{Field}.{Tile}.{Seqn}" Keys represent name of columns LC_FILE : str Column name which can be used for obtaining light curve files. By default it is set to None that means that is not necessary to include any other column in order to get light curves LC_META : dict Meta data for light curve. Example -------- {"xlabel" : "Terrestrial time", "xlabel_unit" : "days", "ylabel" : "Flux", "ylabel_unit" : "Electrons per second", "color" : "N/A", "invert_yaxis" : False} Light curve is expected by default (magnitudes and Julian days) TIME_COL : int Number (starts with 0) of times column in data file MAG_COL : int Number (starts with 0) of magnitudes column in data file ERR_COL : int Number (starts with 0) of errors column in data file ERR_MAG_RATIO : float: Ratio between error and magnitude values Note: Added because of Corot Archive of Faint Stars. IDENT_MAP : ordered dict Ordered dictionary of "name of database" : "column name/s of identifiers" Example -------- IDENT_MAP = {"MachoDb" : ("Field", "Tile", "Seqn") } This allows NAME attribute to access these keys (see above) and construct unique identifier for the star. For one item dictionaries can be used simple dictionary, because there is no need to keep order of items. MORE_MAP : ordered dict Ordered dictionary of "column names" : "key in new dictionary which is be stored in Star object" Example -------- MORE_MAP = collections.OrderedDict((("Per", "period"), ("Class" , "var_type"), ("Jmag" , "j_mag"), ("Kmag" , "k_mag"), ("Hmag" , "h_mag"))) Methods -------- This class inherits TapClient which brings methods for creating, posting and returning tap queries. Methods of this class manage results and create Star objects and light curves. There is no need overwrite methods in inherited classes in the most cases. Anyway obtaining light curves can be different for many databases. In this case it would be sufficient to just implement new _getLightCurve method. Brief description of methods can be found below at their declaration. ''' # Common attribute for all vizier tap connectors TAP_URL = "http://tapvizier.u-strasbg.fr/TAPVizieR/tap" # Most common attributes - can be overwritten # RA = "RAJ2000" DEC = "DEJ2000" LC_FILE = None TIME_COL = 0 MAG_COL = 1 ERR_COL = 2 ERR_MAG_RATIO = 1. # Split at any number of white spaces DELIM = None def __init__(self, queries): ''' Parameters ----------- queries : list, dict List of queries. Each query is dictionary of query parameters and its values ''' # Case of just one query if isinstance(queries, dict): queries = [queries] self.queries = queries
[docs] def getStars(self, lc=False, **kwargs): ''' Get star objects Parameters ---------- lc : bool Star is appended by light curve if True Returns ------- list List of stars ''' select = set([self.RA, self.DEC, self.LC_FILE] + self.MORE_MAP.keys()) for val in self.IDENT_MAP.values(): if isinstance(val, (tuple, list, set)): for it in val: select.add(it) else: select.add(val) select = [s for s in select if s] select = list(select) raw_stars = [] for _que in self.queries: que = _que.copy() if "ra" in que and "dec" in que: que[self.RA] = que.pop("ra") que[self.DEC] = que.pop("dec") if "delta" in que: delta = que.pop("delta") que[self.RA], que[self.DEC] = self._areaSearch( que[self.RA], que[self.DEC], delta) conditions = [] for key, value in que.iteritems(): if isinstance(value, (list, tuple)): if len(value) == 2: conditions.append((key, value[0], value[1])) else: raise QueryInputError("Invalid query range") else: if key != "nearest": conditions.append((key, value)) query_inp = {"table": self.TABLE, "select": select, "conditions": conditions, "URL": self.TAP_URL} res = self.postQuery(query_inp) if res: raw_stars += res return self._createStar(raw_stars, select, lc, **kwargs)
[docs] def getStarsWithCurves(self, **kwargs): ''' Get star objects with light curves Parameters ---------- kwargs : dict Optional parameters which have effect just if certain database provides this option. For example CoRoT archive contains very large light curves, so the dimension of light curve can be reduced by `max_bins` keyword. Returns -------- list List of stars with their light curves ''' return self.getStars(lc=True, **kwargs)
def _createStar(self, data, keys, lc_opt, **kwargs): """ Create Star objects from query result Parameters ---------- data : list Result from query keys : list Name of columns of data lc_opt : bool Obtain light curves if True Returns -------- list List of Star objects """ stars = [] for raw_star in data: ident = {} for key, value in self.IDENT_MAP.iteritems(): db_ident = {} if isinstance(value, (list, tuple)): for ide in value: db_ident[ide] = raw_star[keys.index(ide)] name = self.NAME.format(**db_ident) else: name = raw_star[keys.index(value)] if not db_ident: db_ident = None ident[key] = {"name": name, "db_ident": db_ident} more = {} for key, value in self.MORE_MAP.iteritems(): more_item = raw_star[keys.index(key)] more[value] = more_item raw_star_dict = dict(zip(keys, raw_star)) star = Star(name=self.NAME.format(**raw_star_dict), coo=(raw_star_dict[self.RA], raw_star_dict[self.DEC]), ident=ident, more=more) if lc_opt: star.putLightCurve(self._getLightCurve(star=star, file_name=raw_star_dict.get( self.LC_FILE, None), **kwargs)) stars.append(star) return stars def _getLightCurve(self, star, do_per=False, period_key="period", **kwargs): """ Obtain the light curve Parameters ----------- star : Star instance Star boy object constructed from query looking for his light curve :) do_per : bool If True phase curve is returned instead period_key : str Key in star.more dictionary for value of period length Returns ------- tuple Tuple of times, mags, errors lists """ if do_per: period = star.more.get(period_key, None) if period: self.LC_META = {"xlabel": "Period", "xlabel_unit": "phase"} else: period = 0 url = self.LC_URL.format(macho_name=star.name, period=period) response = requests.get(url) time = [] mag = [] err = [] lcs = [] for line in response.iter_lines(): line = line.strip() if not line.startswith((" ", "#")): parts = line.split(self.DELIM) if len(parts) == 3: time.append(float(parts[self.TIME_COL])) mag.append(float(parts[self.MAG_COL])) err.append(float(parts[self.ERR_COL]) / self.ERR_MAG_RATIO) else: if line.startswith("# m = -1"): meta = self.LC_META.copy() meta["color"] = "B" elif line.startswith("# m = -2"): lcs.append(LightCurve([time, mag, err], meta)) time, mag, err = [], [], [] meta = self.LC_META.copy() meta["color"] = "R" lcs.append(LightCurve([time, mag, err], meta)) return lcs