Source code for exorad.models.targetlist

import re

import numpy as np
import xlrd

xlrd.xlsx.ensure_elementtree_imported(False, None)
xlrd.xlsx.Element_has_iter = True

from astropy import units as u
from astropy.io import ascii

from exorad.log import Logger
from exorad.models.target import Target

compactString = lambda string: string.replace(" ", "").replace("-", "").lower()
stripUnitString = lambda string: string.replace("[", "").replace("]", "")


[docs] class BaseTargetList(Logger): """ Target list base class """ def __init__(self): self.set_log_name() self.read_data() self._targets = self.create_target_list()
[docs] def star_keys(self): raise NotImplementedError
[docs] def star_data(self): raise NotImplementedError
[docs] def read_data(self): raise NotImplementedError
[docs] def create_target_list(self): star_keys = self.star_keys() star_data = self.star_data() # print(planet_data) # print(type(planet_data)) # quit() planet_data = None planet_keys = None try: planet_keys = self.planet_keys() planet_data = self.planet_data() except: pass target_list = [] if planet_data: for i, (star, planet) in enumerate(zip(star_data, planet_data)): target = Target() target.planet = Target() target.star = Target() planet_dict = dict(zip(planet_keys, planet)) target.planet.__dict__.update(planet_dict) star_dict = dict(zip(star_keys, star)) target.star.__dict__.update(star_dict) target.name = target.planet.name target.id = i target_list.append(target) else: for i, star in enumerate(star_data): target = Target() target.star = Target() target.id = i star_dict = dict(zip(star_keys, star)) target.star.__dict__.update(star_dict) target.name = target.star.name target_list.append(target) return target_list
@property def target(self): return self._targets
[docs] def searchTarget(self, name): # method inspired from similar functionality in ExoData searchName = compactString(name) returnList = [] for target in self.target: if re.search( searchName, compactString(str(target.star.name)) ) or re.search(searchName, compactString(str(target.planet.name))): returnList.append(target) return returnList
[docs] class XLXSTargetList(BaseTargetList): """ It parses a .xlsx file into a :class:`BaseTargetList` class """ star_data_columns = (1, 6) planet_data_columns = (8, 18) number_to_be_observed_column = 20 data_row0 = 4 units_row = 3 def __init__(self, filename): self.filename = filename super().__init__() def __parseData__(self, col_range): Sheet = self.tmpSheet keys = Sheet.row_values(2)[col_range[0] : col_range[1] + 1] keys[0] = "name" obj = {} for key, col in zip(keys, list(range(col_range[0], col_range[1] + 1))): str_unit = Sheet.cell_value(rowx=self.units_row, colx=col) if len(str_unit) > 0: try: dim = u.Unit(stripUnitString(str_unit)) except ValueError: self.warning("Unrecognised physical units") dim = 1 else: dim = 1 obj[key] = Sheet.col_values(col)[self.data_row0 :] * dim return obj
[docs] def planet_keys(self): return self.planet.keys()
[docs] def star_keys(self): return self.star.keys()
[docs] def planet_data(self): planet_list = list(self.planet.values()) return list(map(list, zip(*planet_list)))
[docs] def star_data(self): star_list = list(self.star.values()) return list(map(list, zip(*star_list)))
[docs] def read_data(self): xl_workbook = xlrd.open_workbook(self.filename) self.tmpSheet = xl_workbook.sheet_by_name("Sheet1") self.planet = self.__parseData__(col_range=self.planet_data_columns) self.planet["Nobs"] = self.tmpSheet.col_values( self.number_to_be_observed_column )[self.data_row0 :] self.star = self.__parseData__(col_range=self.star_data_columns)
[docs] class CSVTargetList(BaseTargetList): """ It parses a csv file into a :class:`BaseTargetList` class """ def __init__(self, filename): self.filename = filename super().__init__()
[docs] def read_data(self): self.tmpTab = ascii.read(self.filename, format="csv")
[docs] def star_keys(self): s_col = [k for k in self.tmpTab.keys() if "star" in k] return [k.split(" ")[1] for k in s_col]
[docs] def star_data(self): star_k = [k for k in self.tmpTab.keys() if "star" in k] units = [] for n, k in enumerate(star_k): if len(k.split(" ")) == 3: un = k.split(" ")[2] units.append(1 * u.Unit(stripUnitString(un))) else: units.append(None) dat = [] for i in range(len(self.tmpTab[star_k])): val = list(self.tmpTab[star_k][i]) for n in range(len(val)): if units[n] is not None: val[n] = val[n] * units[n] dat.append([str(x) if isinstance(x, np.str_) else x for x in val]) return dat
[docs] def planet_keys(self): s_col = [k for k in self.tmpTab.keys() if "planet" in k] return [k.split(" ")[1] for k in s_col]
[docs] def planet_data(self): planet_k = [k for k in self.tmpTab.keys() if "planet" in k] units = [] for n, k in enumerate(planet_k): if len(k.split(" ")) == 3: un = k.split(" ")[2] units.append(1 * u.Unit(stripUnitString(un))) else: units.append(None) dat = [] for i in range(len(self.tmpTab[planet_k])): val = list(self.tmpTab[planet_k][i]) for n in range(len(val)): if units[n] is not None: val[n] = val[n] * units[n] dat.append([str(x) if isinstance(x, np.str_) else x for x in val]) return dat
[docs] class CSVTargetListMRS(BaseTargetList): """ It parses a csv file into a :class:`BaseTargetList` class """ def __init__(self, filename): self.filename = filename super().__init__()
[docs] def read_data(self): self.tmpTab = ascii.read(self.filename, format="csv")
[docs] def star_keys(self): s_col = [k for k in self.tmpTab.keys() if "star" in k.lower()] s_col = [ k.split(" ", 1)[1].lower() for k in s_col if "error" not in k.lower() ] return [ self.check_keys(k[0 : k.find("[") - 1]) if "[" in k else self.check_keys(k) for k in s_col ]
[docs] def star_data(self): star_k = [ k for k in self.tmpTab.keys() if "star" in k.lower() and "error" not in k.lower() ] units = [] for n, k in enumerate(star_k): if "[" in k: units.append( 1 * u.Unit( self.check_units(k[k.find("[") + 1 : k.find("]")]) ) ) else: units.append(None) dat = [] for i in range(len(self.tmpTab[star_k])): val = list(self.tmpTab[star_k][i]) for n in range(len(val)): if isinstance(val[n], str): if ( "," in val[n] ): # for some reason, comma are used instead of dots sometimes val[n] = val[n].replace(",", ".") try: float(val[n]) except ValueError: val[n] if units[n] is not None: val[n] = val[n] * units[n] dat.append([str(x) if isinstance(x, np.str_) else x for x in val]) return dat
[docs] def planet_keys(self): s_col = [k for k in self.tmpTab.keys() if "planet" in k.lower()] s_col = [ k.split(" ", 1)[1].lower() for k in s_col if "error" not in k.lower() ] return [ self.check_keys(k[0 : k.find("[") - 1]) if "[" in k else self.check_keys(k) for k in s_col ]
[docs] def planet_data(self): planet_k = [ k for k in self.tmpTab.keys() if "planet" in k.lower() and "error" not in k.lower() ] units = [] for n, k in enumerate(planet_k): if "[" in k: units.append( 1 * u.Unit( self.check_units(k[k.find("[") + 1 : k.find("]")]) ) ) else: units.append(None) dat = [] for i in range(len(self.tmpTab[planet_k])): val = list(self.tmpTab[planet_k][i]) for n in range(len(val)): if isinstance(val[n], str): if ( "," in val[n] ): # for some reason, comma are used instead of dots sometimes val[n] = val[n].replace(",", ".") try: float(val[n]) except ValueError: val[n] if units[n] is not None: val[n] = val[n] * units[n] dat.append([str(x) if isinstance(x, np.str_) else x for x in val]) return dat
[docs] @staticmethod def check_units(unit): if unit == "Rs": return "R_sun" if unit == "Ms": return "M_sun" if unit == "Re": return "R_earth" if unit == "Me": return "M_earth" if unit == "Rj": return "R_jupiter" if unit == "Mj": return "M_jupiter" if unit == "days": return "day" else: return unit
[docs] @staticmethod def check_keys(key): if key == "mass": return "M" if key == "radius": return "R" if key == "temperature": return "Teff" if key == "distance": return "D" if key == "period": return "P" if key == "molecular weight": return "mmw" if key == "semi-major axis": return "a" if key == "impact parameter": return "b" if key == "heat redistribution factor": return "Gamma" if key == "transit duration": return "T14" else: return key
[docs] class OldExcelTargetList(Logger): """ It parses an .xls file into a :class:`BaseTargetList` class """ star_data_columns = (1, 6) number_to_be_observed_column = 20 data_row0 = 4 units_row = 3 def __init__(self, filename): self.set_log_name() if filename.endswith(".xlsx"): xl_workbook = xlrd.open_workbook(filename) tmpSheet = xl_workbook.sheet_by_name("Sheet1") tmpSheet = tmpSheet star = self.__parseData__( tmpSheet, col_range=self.star_data_columns ) key0 = list(star.keys())[0] n_targets = len(star[key0]) self.target = [Target() for k in range(n_targets)] for k, target in enumerate(self.target): setattr(target, "star", Target()) for key in list(star.keys()): setattr(target.star, key, star[key][k]) else: self.error("Wrong target list format") raise OSError("Wrong target list format") def __parseData__(self, Sheet, col_range): keys = Sheet.row_values(2)[col_range[0] : col_range[1] + 1] keys[0] = "name" obj = {} for key, col in zip(keys, list(range(col_range[0], col_range[1] + 1))): str_unit = Sheet.cell_value(rowx=self.units_row, colx=col) if len(str_unit) > 0: try: dim = u.Unit(stripUnitString(str_unit)) except ValueError: self.warning("Unrecognised physical units") dim = 1 else: dim = 1 obj[key] = Sheet.col_values(col)[self.data_row0 :] * dim return obj
[docs] def searchTarget(self, name): # method inspired from similar functionality in ExoData searchName = compactString(name) returnList = [] for target in self.target: if re.search( searchName, compactString(str(target.star.name)) ) or re.search(searchName, compactString(str(target.planet.name))): returnList.append(target) return returnList
[docs] class QTableTargetList(BaseTargetList): """ It parses an :class:`astropy.table.QTable` into a :class:`BaseTargetList` class """ def __init__(self, table): self.input_table = table super().__init__()
[docs] def read_data(self): self.tmpTab = self.input_table
[docs] def star_keys(self): s_col = [k for k in self.tmpTab.keys() if "star" in k] return [k.split(" ")[1] for k in s_col]
[docs] def star_data(self): star_k = [k for k in self.tmpTab.keys() if "star" in k] dat = [] for i in range(len(self.tmpTab[star_k])): val = list(self.tmpTab[star_k][i]) self._check_quantities(val) dat.append([str(x) if isinstance(x, np.str_) else x for x in val]) return dat
[docs] def planet_keys(self): s_col = [k for k in self.tmpTab.keys() if "planet" in k] return [k.split(" ")[1] for k in s_col]
[docs] def planet_data(self): star_k = [k for k in self.tmpTab.keys() if "planet" in k] dat = [] for i in range(len(self.tmpTab[star_k])): val = list(self.tmpTab[star_k][i]) self._check_quantities(val) dat.append([str(x) if isinstance(x, np.str_) else x for x in val]) return dat
def _check_quantities(self, val): for v in val: if not isinstance(v, np.str_): if not hasattr(v, "unit"): self.error( "Wrong target list format: Quantities are required" ) raise TypeError( "Wrong target list format: Quantities are required" )