From b7b1250ab16ba542c12a9b588ac8a971c126bd8d Mon Sep 17 00:00:00 2001 From: "michele.maris" Date: Tue, 23 May 2023 22:23:41 +0200 Subject: [PATCH] u --- docs/index.html | 7 + docs/py_artecs.html | 481 +++++++++ {doc => docs}/py_artecs.tex | 0 docs/py_artecs/artecs_map.html | 900 ++++++++++++++++ docs/py_artecs/modelDb.html | 1765 ++++++++++++++++++++++++++++++++ docs/py_artecs/tap.html | 1187 +++++++++++++++++++++ docs/search.js | 46 + 7 files changed, 4386 insertions(+) create mode 100644 docs/index.html create mode 100644 docs/py_artecs.html rename {doc => docs}/py_artecs.tex (100%) create mode 100644 docs/py_artecs/artecs_map.html create mode 100644 docs/py_artecs/modelDb.html create mode 100644 docs/py_artecs/tap.html create mode 100644 docs/search.js diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..a818ab7 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docs/py_artecs.html b/docs/py_artecs.html new file mode 100644 index 0000000..77e54a9 --- /dev/null +++ b/docs/py_artecs.html @@ -0,0 +1,481 @@ + + + + + + + py_artecs API documentation + + + + + + + + + +
+
+

+py_artecs

+ +

A Python3 library to handle contents of ARTECS: Archive of terrestrial-type climate simulations

+ +
http://wwwuser.oats.inaf.it/exobio/climates/
+
+ +

through TAP and the PYVO services.

+ +

Authors: Michele Maris (1), Marco Molinaro (1)

+ +
(1) INAF/Trieste Astronomical Observatory
+
+ +

First Issue: 2019 Nov 20

+ +

Dependencies:

+ +

This package needs: + numpy, scipy, pandas, pyvo

+ +

Installation

+ +

For the latest release:

+ +
+
>>> pip3 install py_artecs
+
+
+ +

for the dev version clone this GitLab repository.

+ +

Files in py_artecs

+ +

__init__.py : the init file

+ +

tap.py : the file with the TAP library

+ +

artecs_map.py : a utility class to handle a local fits file with a Temperature MAP downloaded from the archive

+ +

modelDB.py : a utility class to handle a local csv file with the result of a query, this module is kept for backward compatibility, but its use is deprecated

+ +

Example of session:

+ +

The archive is accessed from the exop_pubblic_tap in py_artecs:

+ +
+
>>> from artecs import exop_pubblic_tap
+
+
+ +

Then instantiate a database object

+ +
+
>>> atap=exop_pubblic_tap()
+
+
+ +

all the queries to ARTECS are made through the methods in atap.

+ +

Queries follows the Astronomical Data Query Language (ADQL) format

+ +
+
>>> ptab=atap.search('power(SMA,1.5)>0.87');
+
+
+ +

see the appendix for further references on the ADQL.

+ +

To know wether the search is successfull:

+ +
+
>>> atap.success()
+True
+
+
+ +

The result of a query is stored in ptab as a PANDAS data_frame.

+ +

In order to save the table as a csv file use the "to_csv" method of pandas data frame:

+ +
+
>>> ptab.to_csv('result.csv',sep=' ')
+
+
+ +

In order to get a map corresponding to the first entry in the ptab use:

+ +
+
>>> TMAP=atap.get_map(ptab.URL[0])
+
+
+ +

the command creates a fits file to rercover the fits filename

+ +
+
>>> print(MAP.filename)
+/tmp/artecs_download_file_669d40064f5bddc8.fits
+
+
+ +

note that the get_map method saved the fits inside the /tmp directory and gives it a dummy name.

+ +

To specify a different name and directory use the outfile keyword in get_map

+ +
+
>>> TMAP=atap.get_map(ptab.URL[0],outfile='./test.fits')
+>>> print(TMAP.filename)
+./test.fits
+
+
+ +

TMAP is an object of class artecs_map, so it contains the temperature MAP in the ARTECS fits file, as well as the other keywords in the original fits file.

+ +

Note that the artecs_map class can be used also local copies of the ARTECS temperature maps.

+ +

At last, to perform a new query reset the old one with:

+ +
+
>>> atap.clear()
+
+
+ +

Appendix A: ADQL Queries

+ +

A query is a string + . SELECTION set of data to be selected + . HOW_MANY elements to select + . WHICH_FIELDS fields to select + . FROM which table + . WHERE condition for selection is true

+ +

Examples of query strings:

+ +
    +
  1. Download all the data:

    + +
    +

    SELECT * FROM exo.EXO

    +
  2. +
  3. Download only the first 10 elements:

    + +
    +

    SELECT TOP 10 * FROM exo.EXO

    +
  4. +
  5. Download only the first 10 elements with SMA in the range 0.9 to 1.1:

    + +
    +

    SELECT TOP 10 * FROM exo.EXO WHERE SMA BETWEEN 0.9 AND 1.1

    +
    + +

    alternativelly

    + +
    +

    SELECT TOP 10 * FROM exo.EXO WHERE (0.9 <= SMA) AND (SMA <= 1.1)

    +
  6. +
  7. Download only the first 10 elements with SMA in the range 0.9 to 1.1 and CONTHAB>=0.5

    + +
    +

    SELECT TOP 10 * FROM exo.EXO WHERE SMA BETWEEN 0.9 AND 1.1 AND CONTHAB>=0.5

    +
  8. +
  9. Arithmetic calculations are allowed if needed for selection so to download the first 10 elements with SMA^1.5 > 0.87

    + +
    +

    SELECT TOP 10 * FROM exo.EXO WHERE power(SMA,1.5)> 0.87

    +
  10. +
  11. returns just columns SMA and CONTHAB from previous example:

    + +
    +

    SELECT TOP 10 SMA,CONTHAB FROM exo.EXO WHERE power(SMA,1.5)> 0.87

    +
  12. +
+ +

Note that the query string is not sensitive to uppercase or lowercase.

+ +

For tutorials see:

+ + + +

A reminder of how to form query strings can be recalled by calling:

+ +
+
>>> atap.EXPLAIN()
+
+
+ +

Appendix B: REFERENCES

+ +

Please quote

+ +

Climate bistability of Earth-like exoplanets

+ +

Murante G., Provenzale A., Vladilo G.,Taffoni G., Silva L., Palazzi E.,von Hardenberg J.,Maris M., Londero E., Knapic C., Zorba C.

+ +

MNRAS 492, 2638–2650 (2020)

+ +

doi: 10.1093/mnras/stz3529

+ +

Appendix C: Example of session with TAP

+ +

It is possible to access the archive directly with TAP

+ +
+
>>> import pyvo as vo
+>>> tap_service = vo.dal.TAPService("http://archives.ia2.inaf.it/vo/tap/exo")
+>>> tap_results = tap_service.search("SELECT top 1 exp_id, url FROM exo.EXO")
+>>> print(tap_results)
+>>>...
+>>> len(tap_results)
+>>>...
+>>> tap_results.getrecord(0)
+>>>...
+
+
+ +

Appendix D: to install pyvo

+ +
+
>>> sudo pip3 install pyvo
+
+
+
+ + + + + +
1"""
+2   .. include:: ../../README.md
+3"""
+4
+5from .modelDb import *
+6from .artecs_map import *
+7from .tap import EXOP_TAP as exop_pubblic_tap
+
+ + +
+
+ + \ No newline at end of file diff --git a/doc/py_artecs.tex b/docs/py_artecs.tex similarity index 100% rename from doc/py_artecs.tex rename to docs/py_artecs.tex diff --git a/docs/py_artecs/artecs_map.html b/docs/py_artecs/artecs_map.html new file mode 100644 index 0000000..b909a1e --- /dev/null +++ b/docs/py_artecs/artecs_map.html @@ -0,0 +1,900 @@ + + + + + + + py_artecs.artecs_map API documentation + + + + + + + + + +
+
+

+py_artecs.artecs_map

+ + + + + + +
  1class artecs_map :
+  2   """
+  3A class to handle a temperature map from ARTECS.
+  4
+  5It reads the artecs_map from a fits file.
+  6
+  7   >>> AMAP=artecs_map("artecs_map.fits")
+  8
+  9Keywords in the map are returned as members of the class or using the method "parameter".
+ 10
+ 11Example:
+ 12
+ 13   >>> AMAP.temp 
+ 14
+ 15returns the temperature map,
+ 16
+ 17   >>> AMAP.parameter('temp')
+ 18   
+ 19returns the temperature map.
+ 20
+ 21
+ 22   >>> AMAP.shape
+ 23
+ 24returns the shape of the map (rows, columns)
+ 25
+ 26
+ 27   """
+ 28   @property 
+ 29   def filename(self) :
+ 30      """ parameter: the filename """
+ 31      return self._filename
+ 32   
+ 33   @property 
+ 34   def p(self) :
+ 35      """ the fits file pointer, normally closed.
+ 36      """
+ 37      return self._p
+ 38   
+ 39   @property 
+ 40   def lst_lat(self) :
+ 41      """ list of latitude bands """
+ 42      return self._lst_lat
+ 43   
+ 44   @property 
+ 45   def lst_year(self) :
+ 46      """ list of time intervals """
+ 47      return self._lst_year
+ 48
+ 49   @property 
+ 50   def shape(self) :
+ 51      """ the shape of the 2D maps """
+ 52      return self._shape
+ 53   
+ 54   @property 
+ 55   def TMGLOB(self) :
+ 56      """ the mean surface temperature """
+ 57      return self._TMGLOB
+ 58   
+ 59   def __init__(self,filename,closeFits=True,verbose=False) :
+ 60      """ To instantiate the class pass the filename from which to load the Temperature map
+ 61      
+ 62      >Keywords: 
+ 63      
+ 64      >>`verbose`: if True verbose output
+ 65      
+ 66      >>`closeFits`: if True the fits file is closed after reading
+ 67      """
+ 68      import numpy
+ 69      try :
+ 70         import pyfits
+ 71      except :
+ 72         from astropy.io import fits as pyfits
+ 73      self._filename=filename
+ 74      self._p=pyfits.open(filename)
+ 75      self._key=[]
+ 76      self._value=[]
+ 77      self._descr=[]
+ 78      mkd=True
+ 79      for cc in self.p[0].header.cards :
+ 80         if cc[0]!='COMMENT' :
+ 81            self._key.append(cc[0])
+ 82            self._value.append(cc[1])
+ 83            self._descr.append(cc[2])
+ 84         else :   
+ 85            if mkd :
+ 86               self._key.append(cc[0])
+ 87               self._value.append('\n'.join(self.p[0].header['COMMENT']))
+ 88               self._descr.append(None)
+ 89               mkd=False
+ 90      
+ 91      #: N of year intervals
+ 92      self.N=self.parameter('N')
+ 93      
+ 94      #: NS number of latitude bands
+ 95      self.NS=self.parameter('NS')
+ 96      
+ 97      #: the shape
+ 98      self._shape=(self.NS,self.N)
+ 99     
+100      self.year=self.p[1].data['year']
+101      self.lat=self.p[1].data['lat']
+102      self.temp=self.p[1].data['temp']      
+103      self.year.shape=self.shape
+104      self.lat.shape=self.shape
+105      self.temp.shape=self.shape
+106      
+107      #: the mean surfscr temperature
+108      self._TMGLOB=self.temp.mean()
+109
+110      self._lst_lat=self.lat[0]
+111      self._lst_year=self.year[:,0].T
+112
+113      if verbose :
+114         print('Successfully opened and readed ',filename)
+115         
+116      if closeFits :
+117         self._p.close()
+118         if verbose :
+119            print('fits file closed ',filename)
+120         
+121      
+122   def keys(self,maps=False) : 
+123      """
+124returns the list of quantities in the map
+125      
+126Keywords: 
+127
+128>`maps` (default False), if True returns just the list of of elements which are 2D maps
+129      """
+130      if maps : 
+131         return ['year','lat','temp']
+132      else :
+133         return self._key
+134   def has_key(self,key) : 
+135      """True if required `key` is in the map"""
+136      return key in self._key
+137   def parameter(self,key) :
+138      """returns a parameter from the fits file from its `key'"""
+139      return self._value[self._key.index(key)]
+140   def description(self,key) :
+141      """returns the description of a parameter in the fits file from its `key'"""
+142      return self._descr[self._key.index(key)]
+143   #def bilinear_interpolation(self,lat,year) :
+144      #"""returns bilinear interpolation of the map (not implemeted yet) """
+145      #raise Exception(
+
+ + +
+
+ +
+ + class + artecs_map: + + + +
+ +
  2class artecs_map :
+  3   """
+  4A class to handle a temperature map from ARTECS.
+  5
+  6It reads the artecs_map from a fits file.
+  7
+  8   >>> AMAP=artecs_map("artecs_map.fits")
+  9
+ 10Keywords in the map are returned as members of the class or using the method "parameter".
+ 11
+ 12Example:
+ 13
+ 14   >>> AMAP.temp 
+ 15
+ 16returns the temperature map,
+ 17
+ 18   >>> AMAP.parameter('temp')
+ 19   
+ 20returns the temperature map.
+ 21
+ 22
+ 23   >>> AMAP.shape
+ 24
+ 25returns the shape of the map (rows, columns)
+ 26
+ 27
+ 28   """
+ 29   @property 
+ 30   def filename(self) :
+ 31      """ parameter: the filename """
+ 32      return self._filename
+ 33   
+ 34   @property 
+ 35   def p(self) :
+ 36      """ the fits file pointer, normally closed.
+ 37      """
+ 38      return self._p
+ 39   
+ 40   @property 
+ 41   def lst_lat(self) :
+ 42      """ list of latitude bands """
+ 43      return self._lst_lat
+ 44   
+ 45   @property 
+ 46   def lst_year(self) :
+ 47      """ list of time intervals """
+ 48      return self._lst_year
+ 49
+ 50   @property 
+ 51   def shape(self) :
+ 52      """ the shape of the 2D maps """
+ 53      return self._shape
+ 54   
+ 55   @property 
+ 56   def TMGLOB(self) :
+ 57      """ the mean surface temperature """
+ 58      return self._TMGLOB
+ 59   
+ 60   def __init__(self,filename,closeFits=True,verbose=False) :
+ 61      """ To instantiate the class pass the filename from which to load the Temperature map
+ 62      
+ 63      >Keywords: 
+ 64      
+ 65      >>`verbose`: if True verbose output
+ 66      
+ 67      >>`closeFits`: if True the fits file is closed after reading
+ 68      """
+ 69      import numpy
+ 70      try :
+ 71         import pyfits
+ 72      except :
+ 73         from astropy.io import fits as pyfits
+ 74      self._filename=filename
+ 75      self._p=pyfits.open(filename)
+ 76      self._key=[]
+ 77      self._value=[]
+ 78      self._descr=[]
+ 79      mkd=True
+ 80      for cc in self.p[0].header.cards :
+ 81         if cc[0]!='COMMENT' :
+ 82            self._key.append(cc[0])
+ 83            self._value.append(cc[1])
+ 84            self._descr.append(cc[2])
+ 85         else :   
+ 86            if mkd :
+ 87               self._key.append(cc[0])
+ 88               self._value.append('\n'.join(self.p[0].header['COMMENT']))
+ 89               self._descr.append(None)
+ 90               mkd=False
+ 91      
+ 92      #: N of year intervals
+ 93      self.N=self.parameter('N')
+ 94      
+ 95      #: NS number of latitude bands
+ 96      self.NS=self.parameter('NS')
+ 97      
+ 98      #: the shape
+ 99      self._shape=(self.NS,self.N)
+100     
+101      self.year=self.p[1].data['year']
+102      self.lat=self.p[1].data['lat']
+103      self.temp=self.p[1].data['temp']      
+104      self.year.shape=self.shape
+105      self.lat.shape=self.shape
+106      self.temp.shape=self.shape
+107      
+108      #: the mean surfscr temperature
+109      self._TMGLOB=self.temp.mean()
+110
+111      self._lst_lat=self.lat[0]
+112      self._lst_year=self.year[:,0].T
+113
+114      if verbose :
+115         print('Successfully opened and readed ',filename)
+116         
+117      if closeFits :
+118         self._p.close()
+119         if verbose :
+120            print('fits file closed ',filename)
+121         
+122      
+123   def keys(self,maps=False) : 
+124      """
+125returns the list of quantities in the map
+126      
+127Keywords: 
+128
+129>`maps` (default False), if True returns just the list of of elements which are 2D maps
+130      """
+131      if maps : 
+132         return ['year','lat','temp']
+133      else :
+134         return self._key
+135   def has_key(self,key) : 
+136      """True if required `key` is in the map"""
+137      return key in self._key
+138   def parameter(self,key) :
+139      """returns a parameter from the fits file from its `key'"""
+140      return self._value[self._key.index(key)]
+141   def description(self,key) :
+142      """returns the description of a parameter in the fits file from its `key'"""
+143      return self._descr[self._key.index(key)]
+144   #def bilinear_interpolation(self,lat,year) :
+145      #"""returns bilinear interpolation of the map (not implemeted yet) """
+146      #raise Exception(
+
+ + +

A class to handle a temperature map from ARTECS.

+ +

It reads the artecs_map from a fits file.

+ +
+
>>> AMAP=artecs_map("artecs_map.fits")
+
+
+ +

Keywords in the map are returned as members of the class or using the method "parameter".

+ +

Example:

+ +
+
>>> AMAP.temp 
+
+
+ +

returns the temperature map,

+ +
+
>>> AMAP.parameter('temp')
+
+
+ +

returns the temperature map.

+ +
+
>>> AMAP.shape
+
+
+ +

returns the shape of the map (rows, columns)

+
+ + +
+ +
+ + artecs_map(filename, closeFits=True, verbose=False) + + + +
+ +
 60   def __init__(self,filename,closeFits=True,verbose=False) :
+ 61      """ To instantiate the class pass the filename from which to load the Temperature map
+ 62      
+ 63      >Keywords: 
+ 64      
+ 65      >>`verbose`: if True verbose output
+ 66      
+ 67      >>`closeFits`: if True the fits file is closed after reading
+ 68      """
+ 69      import numpy
+ 70      try :
+ 71         import pyfits
+ 72      except :
+ 73         from astropy.io import fits as pyfits
+ 74      self._filename=filename
+ 75      self._p=pyfits.open(filename)
+ 76      self._key=[]
+ 77      self._value=[]
+ 78      self._descr=[]
+ 79      mkd=True
+ 80      for cc in self.p[0].header.cards :
+ 81         if cc[0]!='COMMENT' :
+ 82            self._key.append(cc[0])
+ 83            self._value.append(cc[1])
+ 84            self._descr.append(cc[2])
+ 85         else :   
+ 86            if mkd :
+ 87               self._key.append(cc[0])
+ 88               self._value.append('\n'.join(self.p[0].header['COMMENT']))
+ 89               self._descr.append(None)
+ 90               mkd=False
+ 91      
+ 92      #: N of year intervals
+ 93      self.N=self.parameter('N')
+ 94      
+ 95      #: NS number of latitude bands
+ 96      self.NS=self.parameter('NS')
+ 97      
+ 98      #: the shape
+ 99      self._shape=(self.NS,self.N)
+100     
+101      self.year=self.p[1].data['year']
+102      self.lat=self.p[1].data['lat']
+103      self.temp=self.p[1].data['temp']      
+104      self.year.shape=self.shape
+105      self.lat.shape=self.shape
+106      self.temp.shape=self.shape
+107      
+108      #: the mean surfscr temperature
+109      self._TMGLOB=self.temp.mean()
+110
+111      self._lst_lat=self.lat[0]
+112      self._lst_year=self.year[:,0].T
+113
+114      if verbose :
+115         print('Successfully opened and readed ',filename)
+116         
+117      if closeFits :
+118         self._p.close()
+119         if verbose :
+120            print('fits file closed ',filename)
+
+ + +

To instantiate the class pass the filename from which to load the Temperature map

+ +
+

Keywords:

+
+ +
+
+

verbose: if True verbose output

+
+
+ +
+
+

closeFits: if True the fits file is closed after reading

+
+
+
+ + +
+
+
+ filename + + +
+ + +

parameter: the filename

+
+ + +
+
+
+ p + + +
+ + +

the fits file pointer, normally closed.

+
+ + +
+
+
+ lst_lat + + +
+ + +

list of latitude bands

+
+ + +
+
+
+ lst_year + + +
+ + +

list of time intervals

+
+ + +
+
+
+ shape + + +
+ + +

the shape of the 2D maps

+
+ + +
+
+
+ TMGLOB + + +
+ + +

the mean surface temperature

+
+ + +
+
+ +
+ + def + keys(self, maps=False): + + + +
+ +
123   def keys(self,maps=False) : 
+124      """
+125returns the list of quantities in the map
+126      
+127Keywords: 
+128
+129>`maps` (default False), if True returns just the list of of elements which are 2D maps
+130      """
+131      if maps : 
+132         return ['year','lat','temp']
+133      else :
+134         return self._key
+
+ + +

returns the list of quantities in the map

+ +

Keywords:

+ +
+

maps (default False), if True returns just the list of of elements which are 2D maps

+
+
+ + +
+
+ +
+ + def + has_key(self, key): + + + +
+ +
135   def has_key(self,key) : 
+136      """True if required `key` is in the map"""
+137      return key in self._key
+
+ + +

True if required key is in the map

+
+ + +
+
+ +
+ + def + parameter(self, key): + + + +
+ +
138   def parameter(self,key) :
+139      """returns a parameter from the fits file from its `key'"""
+140      return self._value[self._key.index(key)]
+
+ + +

returns a parameter from the fits file from its `key'

+
+ + +
+
+ +
+ + def + description(self, key): + + + +
+ +
141   def description(self,key) :
+142      """returns the description of a parameter in the fits file from its `key'"""
+143      return self._descr[self._key.index(key)]
+144   #def bilinear_interpolation(self,lat,year) :
+145      #"""returns bilinear interpolation of the map (not implemeted yet) """
+146      #raise Exception(
+
+ + +

returns the description of a parameter in the fits file from its `key'

+
+ + +
+
+
+ + \ No newline at end of file diff --git a/docs/py_artecs/modelDb.html b/docs/py_artecs/modelDb.html new file mode 100644 index 0000000..b421a6d --- /dev/null +++ b/docs/py_artecs/modelDb.html @@ -0,0 +1,1765 @@ + + + + + + + py_artecs.modelDb API documentation + + + + + + + + + +
+
+

+py_artecs.modelDb

+ +

DEPRECATED

+
+ + + + + +
  1"""
+  2   **DEPRECATED** 
+  3"""
+  4
+  5class modelDb :
+  6   """
+  7   **DEPRECATED** 
+  8   
+  9Class to handle a local version of the ARTECS DB.
+ 10
+ 11It takes in input a csv file generated from a query of ARTECS and saved in csv format.
+ 12
+ 13See the example in the introductory page.
+ 14
+ 15This module is kept for compatibility with early releases of py_artecs, but it is not maintained so its use is DEPRECATED.
+ 16
+ 17   """
+ 18   def __init__(self,project_name,project_path,csv_name,Verbose=True,csv_sep='!',csv_comment='#',csv_index_col='index',figures_path='png',filterBad=True,new=False,query=None) :
+ 19      import time
+ 20      from collections import OrderedDict
+ 21      from matplotlib import pyplot as plt
+ 22      import numpy as np
+ 23      import pandas
+ 24      import astropy
+ 25      #
+ 26      self.reset()
+ 27      self.reset_plot_status()
+ 28      #
+ 29      self._project_name=project_name
+ 30      self._project_path=project_path
+ 31      self._csv_name=csv_name
+ 32      self._figures_path=figures_path
+ 33      #
+ 34      if new : return
+ 35      #
+ 36      print()
+ 37      print("Reading from csv file ",self._csv_name)
+ 38      tic=time.time()
+ 39      csv=pandas.read_csv(self._project_path+'/'+self._csv_name,sep=csv_sep,comment=csv_comment,index_col=csv_index_col)
+ 40      if not 'TSTART' in csv.keys() : 
+ 41         csv['TSTART']=np.zeros(len(csv))
+ 42         print ("TSTART not found, replaced by a DUMMY")
+ 43      csv['Natm']=csv['p_surface']/csv['GRAV']
+ 44      csv['iclass']=np.array([self.classification_string2numeric(k.strip().lower()) for k in csv.CLASS])
+ 45      csv['peri']=(1-csv.ECC)*csv.SMA
+ 46      csv['aphe']=(1+csv.ECC)*csv.SMA
+ 47      self.flagBad=np.array(csv['iclass']==self._string_class_notfound)*8+np.array(csv.iclass<0)*4+np.array(np.isnan(csv.TMGLOB))*2+np.array(csv.TSTART<0)
+ 48      tic=time.time()-tic
+ 49      print("%d lines in %e sec"%(len(csv),tic))
+ 50      #
+ 51      if not 'SOURCE' in csv.keys() :
+ 52         csv['SOURCE']=np.zeros(len(csv))-1
+ 53      #
+ 54      if filterBad :
+ 55         self.TABLE=csv[self.flagBad==0]
+ 56      else :
+ 57         self.TABLE=csv
+ 58      #
+ 59      if query != None and query!='' :
+ 60         self.TABLE=self.TABLE.query(query)
+ 61      #
+ 62      if Verbose :
+ 63         print()
+ 64         print("In %s, containind %d models, the number of models with "%(csv_name,len(csv)))
+ 65         print("  CLASS  == UNKNOWN                    ",(csv.iclass==-200).sum())
+ 66         print("  CLASS  == SNOWBALL                   ",(csv.iclass==1).sum())
+ 67         print("  CLASS  == WATERBELT                  ",(csv.iclass==2).sum())
+ 68         print("  CLASS  == WARM                       ",(csv.iclass==3).sum())
+ 69         print("  CLASS  == WARM_HOT                   ",(csv.iclass==4).sum())
+ 70         print("  INVALID STRING IN CLASS              ",((self.flagBad>=8)).sum())
+ 71         print()
+ 72         for k in np.unique(csv['SOURCE']) :
+ 73            print("  SOURCE == %d                          %d"%(k,(csv.SOURCE==0).sum()))
+ 74         #print("  SOURCE == 1                          ",(csv.SOURCE==1).sum())
+ 75         print()
+ 76         print("  TMGLOB == NaN                        ",np.isnan(csv.TMGLOB).sum())
+ 77         print("  TSTART<0                             ",(csv.TSTART<0).sum())
+ 78         print("  TMGLOB == NaN and TSTART<0           ",((csv.TSTART<0)&np.isnan(csv.TMGLOB)).sum())
+ 79         print("  TMGLOB == NaN and ZCD == NaN         ",(np.isnan(csv.TMGLOB)&np.isnan(csv.zenithal_column_density)).sum())
+ 80         print("  TMGLOB == NaN and CLASS == UNDEFINED ",(np.isnan(csv.TMGLOB)&(csv.iclass==0)).sum())
+ 81         print()
+ 82      #
+ 83      del csv 
+ 84   def to_csv(self,outFile,COMMENT='') :
+ 85      print("Writing csv into ",outFile)
+ 86      open(outFile,'w').write('#\n#'+outFile+'\n#elaboration of '+self._csv_name+'\n#'+str(COMMENT)+'\n#!BEGIN\n')
+ 87      open(outFile,'a').write(self.TABLE.to_csv(None,sep='!',index_column='index'))
+ 88      open(outFile,'a').write('#!END\n')
+ 89      print("written")
+ 90   def reset(self) :
+ 91      from collections import OrderedDict
+ 92      for k in ['_project_name','_project_path','_csv_name','_figures_path','_project_name','_project_path','TABLE','flagBad','classTable'] :
+ 93         self.__dict__[k]=None
+ 94      self._numeric_classification=OrderedDict()
+ 95      self._numeric_classification['---']=-400
+ 96      self._numeric_classification['unknown']=-200
+ 97      self._numeric_classification['snowball']=1
+ 98      self._numeric_classification['waterbelt']=2
+ 99      self._numeric_classification['warm']=3
+100      self._numeric_classification['warm_hot']=4
+101      self._string_class_notfound=-100000
+102      #
+103      self._classification_labels=self._numeric_classification.keys()
+104      self._ClassNames=['SNOWBALL','WATERBELT','WARM','WARM_HOT']
+105      self._ClassColor={'SNOWBALL':'b','WATERBELT':'g','WARM':'r','WARM_HOT':'y'}
+106      self._ClassMarker={'SNOWBALL':'o:12','WATERBELT':'v:16','WARM':'d:8','WARM_HOT':'s:6'}
+107      #
+108      self.iceTOT_threshold=None
+109   #
+110   def __len__(self) : return len(self.TABLE)
+111   #
+112   def __getitem__(self,this) : return self.TABLE[this]
+113   #
+114   def __setitem__(self,this,that) : self.TABLE[this]=that
+115   #
+116   def copy(self) :
+117      import copy
+118      out=modelDb('slice of '+self._project_name,self._project_path,None,new=True)
+119      out._project_name=self._project_name
+120      out._project_path=self._project_path
+121      out._csv_name=None
+122      out._figures_path=self._figures_path
+123      out.classTable=copy.deepcopy(self.classTable)
+124      return out
+125   #
+126   def unique_values(self) :
+127      import numpy as np
+128      from collections import OrderedDict
+129      import pandas
+130      out=OrderedDict()
+131      for k in self.keys() :
+132         out[k]=np.unique(self.TABLE[k].values)
+133      return out
+134   #
+135   def list_unique_values(self) :
+136      out=self.unique_values()
+137      for k in out.keys() :
+138         print("%s (%d) ="%(k,len(out[k])))
+139      #
+140   def classification_indexes(self,*arg,**karg) :
+141      import numpy as np
+142      from collections import OrderedDict
+143      if len(arg) == 0 : 
+144         _arg=['CLASS','OBLIQ','ECC','SMA','PRESS','SOURCE','GEO','FO_CONST','PROT','P_CO2']
+145      else :
+146         _arg=arg
+147      ipfx=karg['index_pfx'] if karg.has_key('index_pfx') else 'i_'
+148      for k in _arg : 
+149         quit=False
+150         if not k in self.keys() :
+151            print("%s not found "%k)
+152            quit=True
+153      if quit : 
+154         return
+155      classTable=OrderedDict()
+156      for k in arg :
+157         u=self.unique(k)
+158         iu=np.zeros(len(self))
+159         classTable[k]=OrderedDict()
+160         for cu,u in enumerate(self.unique(k)) :
+161            idx=np.where(np.array(self.TABLE[k]==u))[0]
+162            iu[idx]=cu
+163            classTable[k][u]=[cu,len(idx)]
+164         self.TABLE[ipfx+k]=iu
+165      self.classTable=classTable.copy()
+166      return classTable
+167   #
+168   def show_classTable(self) :
+169      for k in DB.classTable.keys() :
+170         print('%10s : %3d = '%(k,len(DB.classTable[k])),end='')
+171         for ij,j in enumerate(DB.classTable[k].keys()) : 
+172            if ij>0 : print ('|',end='')
+173            print('%3d#'%ij,end='')
+174            print('%12s'%str(j),':',end='')
+175            print("%6d "%len(DB.query('i_'+k+'=='+str(ij))),end='')
+176         print()
+177   #
+178   def unique(self,key) : 
+179      import numpy as np
+180      return np.sort(self.TABLE[key].unique())
+181   #
+182   def sort(self,sort_by) :
+183      self.TABLE=self.TABLE.sort(sort_by)
+184   #
+185   def sorted_query(self,sort_by,qstr) :
+186      out=self.copy()
+187      if type(qstr) == type('') :
+188         out.TABLE=self.TABLE.query(qstr)
+189      else :
+190         out.TABLE=self.TABLE[qstr]
+191      out.TABLE=out.TABLE.sort(sort_by)
+192      return out
+193   #
+194   def query(self,qstr) :
+195      out=self.copy()
+196      if type(qstr) == type('') :
+197         out.TABLE=self.TABLE.query(qstr)
+198      else :
+199         out.TABLE=self.TABLE[qstr]
+200      return out
+201   #
+202   def select_by_loc(self,loc_argument) :
+203      out=self.copy()
+204      out.TABLE=self.TABLE.loc[loc_argument]
+205      return out
+206   #
+207   def select_by_iloc(self,iloc_argument) :
+208      out=self.copy()
+209      out.TABLE=self.TABLE.iloc[iloc_argument]
+210      return out
+211   #
+212   def classification_string2numeric(self,strg) :
+213      try :
+214         return self._numeric_classification[strg.lower().strip()]
+215      except :
+216         print("bad strng ",strg)
+217         return self._string_class_notfound
+218   #
+219   def calc_iclass(self,string_classification_array) :
+220      return np.array([self._numeric_classification[k.strip().lower()] for k in string_classification_array])
+221   #
+222   def keys(self) : return list(self.TABLE.keys())
+223   #
+224   def has_key(self,this) : return (this in self.TABLE.keys())
+225   #
+226   def __include__(self,this) : return (this in self.TABLE.keys())
+227   #
+228   def reset_plot_status(self) :
+229      """resets the self._last_plot dictionary where handles from the last plot generated are stored"""
+230      from collections import OrderedDict
+231      self._last_plot=OrderedDict()
+232      self._last_plot['fig']=None
+233      self._last_plot['xlabel']=None
+234      self._last_plot['ylabel']=None
+235      self._last_plot['axe']=None
+236      self._last_plot['legend']=None
+237      self._last_plot['curves']=[]
+238   #
+239   def plot2(self,x,y='MolecularDepth',ylog=True,xlog=False,newfig=True,legend_loc=3,xylim=None,savefig=None,one2one_line=False) :
+240      """creates a 2 axis plot, the handles for the plot objects are stored in self._last_plot"""
+241      from collections import OrderedDict
+242      from matplotlib import pyplot as plt
+243      import numpy as np
+244      import pandas
+245      import astropy
+246      #
+247      self.reset_plot_status()
+248      #
+249      if newfig : 
+250         self._last_plot['fig']=plt.figure()
+251      else :
+252         self._last_plot['fig']=plt.gcf()
+253      #
+254      for k in self._ClassNames :  
+255         smp=self.TABLE.query('CLASS=="%s"'%k)
+256         self._last_plot['curves'].append(plt.plot(smp[x],smp[y],self._ClassColor[k]+self._ClassMarker[k][0],label=k,mew=0,markersize=int(self._ClassMarker[k][2:])))
+257      plt.gca().set_xscale('linear' if xlog==False else 'log')
+258      plt.gca().set_yscale('linear' if ylog==False else 'log')
+259      plt.title(self._project_name,fontsize=20)
+260      if xylim != None : plt.axis(xylim)
+261      #
+262      if one2one_line==True :
+263         a=plt.axis()
+264         x121=np.arange(0,1+0.01,0.01)
+265         x121=a[0]*x121+a[1]*(1-x121)
+266         self._last_plot['1:1']=plt.plot(x121,x121,'k-',lw=1)
+267         self._last_plot['1:1'][0].set_zorder(-10)
+268      #
+269      if x=='Natm' :
+270         a=plt.axis()
+271         self._last_plot['STARTNATMLINES']=[plt.plot(k*np.ones(2),[a[2],a[3]],'k-',lw=2) for k in np.unique(self.TABLE['PRESS']/self.TABLE['GRAV'])]
+272         for k in self._last_plot['STARTNATMLINES'] : k[0].set_zorder(-10)
+273      #
+274      if x=='p_surface' :
+275         a=plt.axis()
+276         self._last_plot['PRESS_LINES']=[plt.plot(k*np.ones(2),[a[2],a[3]],'k-',lw=2) for k in np.unique(self.TABLE['PRESS'])]
+277         for k in self._last_plot['PRESS_LINES'] : k[0].set_zorder(-10)
+278      #
+279      self._last_plot['axe']=plt.gca()
+280      if legend_loc > 0 :
+281         self._last_plot['legend']=plt.legend(loc=legend_loc)
+282      self._last_plot['xlabel']=plt.xlabel(x,fontsize=20)
+283      self._last_plot['ylabel']=plt.ylabel(y,fontsize=20)
+284      plt.gcf().set_figwidth(18.)
+285      plt.gcf().set_figheight(plt.gcf().get_figwidth()*3./4.)
+286      if savefig != None and savefig != False:
+287         if type(savefig)==type('') and savefig!='' :
+288            _savefig=savefig
+289         else :
+290            _savefig=self._project_name+'/'+self._figures_path+'/'+y+'_vz_'+x+'.pdf'
+291         print("Saving in ",_savefig)
+292         plt.savefig(_savefig,dpi=plt.gcf().get_dpi())
+293      plt.show()
+294   #
+295   def set_iceTOT_threshold(self,iceTOT_threshold) :
+296      """ set iceTOT_threshold : the ice coverage over which the planet is considered a snowball
+297suggested values 0.95 or 0.99
+298      """
+299      self.iceTOT_threshold=iceTOT_threshold
+300   #
+301   def flag_class_warm(self) :
+302      """returns Murante's classifications for warm calculated from scratch
+303iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+304suggested values 0.95 or 0.99
+305      """
+306      import numpy as np
+307      if not self.iceTOT_threshold() : return
+308      return (self.TABLE['TMGLOB'] > self.TABLE['Tice']) * (self.TABLE['TMGLOB'] < self.TABLE['Tvap'])
+309      
+310   def flag_class_warm_hot(self) :
+311      """returns Murante's classifications for warm_hot calculated from scratch
+312iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+313suggested values 0.95 or 0.99
+314      """
+315      import numpy as np
+316      if not self.iceTOT_threshold() : return
+317      return (self.TABLE['TMGLOB'] >= self.TABLE['Tvap'])
+318      
+319   def flag_class_snowball(self) :
+320      """returns Murante's classifications for warm_hot calculated from scratch
+321iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+322suggested values 0.95 or 0.99
+323      """
+324      import numpy as np
+325      if not self.iceTOT_threshold() : return
+326      return (self.TABLE['ICE'] > self.iceTOT_threshold)
+327      
+328   def flag_class_waterbelt(self) :
+329      """returns Murante's classifications for warm_hot calculated from scratch
+330iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+331suggested values 0.95 or 0.99
+332      """
+333      import numpy as np
+334      if not self.iceTOT_threshold() : return
+335      return (self.TABLE['TMGLOB'] <= self.TABLE['Tice'])*(self.TABLE['ICE'] <= self.iceTOT_threshold)
+336   
+337   def _testIceTot(self) :
+338      if self.iceTOT_threshold == None :
+339         raise Exception("iceTOT_threshold not set, Set iceTOT_threshold with .set_iceTOT_threshold(x) before")
+340         return False
+341      return True
+
+ + +
+
+ +
+ + class + modelDb: + + + +
+ +
  6class modelDb :
+  7   """
+  8   **DEPRECATED** 
+  9   
+ 10Class to handle a local version of the ARTECS DB.
+ 11
+ 12It takes in input a csv file generated from a query of ARTECS and saved in csv format.
+ 13
+ 14See the example in the introductory page.
+ 15
+ 16This module is kept for compatibility with early releases of py_artecs, but it is not maintained so its use is DEPRECATED.
+ 17
+ 18   """
+ 19   def __init__(self,project_name,project_path,csv_name,Verbose=True,csv_sep='!',csv_comment='#',csv_index_col='index',figures_path='png',filterBad=True,new=False,query=None) :
+ 20      import time
+ 21      from collections import OrderedDict
+ 22      from matplotlib import pyplot as plt
+ 23      import numpy as np
+ 24      import pandas
+ 25      import astropy
+ 26      #
+ 27      self.reset()
+ 28      self.reset_plot_status()
+ 29      #
+ 30      self._project_name=project_name
+ 31      self._project_path=project_path
+ 32      self._csv_name=csv_name
+ 33      self._figures_path=figures_path
+ 34      #
+ 35      if new : return
+ 36      #
+ 37      print()
+ 38      print("Reading from csv file ",self._csv_name)
+ 39      tic=time.time()
+ 40      csv=pandas.read_csv(self._project_path+'/'+self._csv_name,sep=csv_sep,comment=csv_comment,index_col=csv_index_col)
+ 41      if not 'TSTART' in csv.keys() : 
+ 42         csv['TSTART']=np.zeros(len(csv))
+ 43         print ("TSTART not found, replaced by a DUMMY")
+ 44      csv['Natm']=csv['p_surface']/csv['GRAV']
+ 45      csv['iclass']=np.array([self.classification_string2numeric(k.strip().lower()) for k in csv.CLASS])
+ 46      csv['peri']=(1-csv.ECC)*csv.SMA
+ 47      csv['aphe']=(1+csv.ECC)*csv.SMA
+ 48      self.flagBad=np.array(csv['iclass']==self._string_class_notfound)*8+np.array(csv.iclass<0)*4+np.array(np.isnan(csv.TMGLOB))*2+np.array(csv.TSTART<0)
+ 49      tic=time.time()-tic
+ 50      print("%d lines in %e sec"%(len(csv),tic))
+ 51      #
+ 52      if not 'SOURCE' in csv.keys() :
+ 53         csv['SOURCE']=np.zeros(len(csv))-1
+ 54      #
+ 55      if filterBad :
+ 56         self.TABLE=csv[self.flagBad==0]
+ 57      else :
+ 58         self.TABLE=csv
+ 59      #
+ 60      if query != None and query!='' :
+ 61         self.TABLE=self.TABLE.query(query)
+ 62      #
+ 63      if Verbose :
+ 64         print()
+ 65         print("In %s, containind %d models, the number of models with "%(csv_name,len(csv)))
+ 66         print("  CLASS  == UNKNOWN                    ",(csv.iclass==-200).sum())
+ 67         print("  CLASS  == SNOWBALL                   ",(csv.iclass==1).sum())
+ 68         print("  CLASS  == WATERBELT                  ",(csv.iclass==2).sum())
+ 69         print("  CLASS  == WARM                       ",(csv.iclass==3).sum())
+ 70         print("  CLASS  == WARM_HOT                   ",(csv.iclass==4).sum())
+ 71         print("  INVALID STRING IN CLASS              ",((self.flagBad>=8)).sum())
+ 72         print()
+ 73         for k in np.unique(csv['SOURCE']) :
+ 74            print("  SOURCE == %d                          %d"%(k,(csv.SOURCE==0).sum()))
+ 75         #print("  SOURCE == 1                          ",(csv.SOURCE==1).sum())
+ 76         print()
+ 77         print("  TMGLOB == NaN                        ",np.isnan(csv.TMGLOB).sum())
+ 78         print("  TSTART<0                             ",(csv.TSTART<0).sum())
+ 79         print("  TMGLOB == NaN and TSTART<0           ",((csv.TSTART<0)&np.isnan(csv.TMGLOB)).sum())
+ 80         print("  TMGLOB == NaN and ZCD == NaN         ",(np.isnan(csv.TMGLOB)&np.isnan(csv.zenithal_column_density)).sum())
+ 81         print("  TMGLOB == NaN and CLASS == UNDEFINED ",(np.isnan(csv.TMGLOB)&(csv.iclass==0)).sum())
+ 82         print()
+ 83      #
+ 84      del csv 
+ 85   def to_csv(self,outFile,COMMENT='') :
+ 86      print("Writing csv into ",outFile)
+ 87      open(outFile,'w').write('#\n#'+outFile+'\n#elaboration of '+self._csv_name+'\n#'+str(COMMENT)+'\n#!BEGIN\n')
+ 88      open(outFile,'a').write(self.TABLE.to_csv(None,sep='!',index_column='index'))
+ 89      open(outFile,'a').write('#!END\n')
+ 90      print("written")
+ 91   def reset(self) :
+ 92      from collections import OrderedDict
+ 93      for k in ['_project_name','_project_path','_csv_name','_figures_path','_project_name','_project_path','TABLE','flagBad','classTable'] :
+ 94         self.__dict__[k]=None
+ 95      self._numeric_classification=OrderedDict()
+ 96      self._numeric_classification['---']=-400
+ 97      self._numeric_classification['unknown']=-200
+ 98      self._numeric_classification['snowball']=1
+ 99      self._numeric_classification['waterbelt']=2
+100      self._numeric_classification['warm']=3
+101      self._numeric_classification['warm_hot']=4
+102      self._string_class_notfound=-100000
+103      #
+104      self._classification_labels=self._numeric_classification.keys()
+105      self._ClassNames=['SNOWBALL','WATERBELT','WARM','WARM_HOT']
+106      self._ClassColor={'SNOWBALL':'b','WATERBELT':'g','WARM':'r','WARM_HOT':'y'}
+107      self._ClassMarker={'SNOWBALL':'o:12','WATERBELT':'v:16','WARM':'d:8','WARM_HOT':'s:6'}
+108      #
+109      self.iceTOT_threshold=None
+110   #
+111   def __len__(self) : return len(self.TABLE)
+112   #
+113   def __getitem__(self,this) : return self.TABLE[this]
+114   #
+115   def __setitem__(self,this,that) : self.TABLE[this]=that
+116   #
+117   def copy(self) :
+118      import copy
+119      out=modelDb('slice of '+self._project_name,self._project_path,None,new=True)
+120      out._project_name=self._project_name
+121      out._project_path=self._project_path
+122      out._csv_name=None
+123      out._figures_path=self._figures_path
+124      out.classTable=copy.deepcopy(self.classTable)
+125      return out
+126   #
+127   def unique_values(self) :
+128      import numpy as np
+129      from collections import OrderedDict
+130      import pandas
+131      out=OrderedDict()
+132      for k in self.keys() :
+133         out[k]=np.unique(self.TABLE[k].values)
+134      return out
+135   #
+136   def list_unique_values(self) :
+137      out=self.unique_values()
+138      for k in out.keys() :
+139         print("%s (%d) ="%(k,len(out[k])))
+140      #
+141   def classification_indexes(self,*arg,**karg) :
+142      import numpy as np
+143      from collections import OrderedDict
+144      if len(arg) == 0 : 
+145         _arg=['CLASS','OBLIQ','ECC','SMA','PRESS','SOURCE','GEO','FO_CONST','PROT','P_CO2']
+146      else :
+147         _arg=arg
+148      ipfx=karg['index_pfx'] if karg.has_key('index_pfx') else 'i_'
+149      for k in _arg : 
+150         quit=False
+151         if not k in self.keys() :
+152            print("%s not found "%k)
+153            quit=True
+154      if quit : 
+155         return
+156      classTable=OrderedDict()
+157      for k in arg :
+158         u=self.unique(k)
+159         iu=np.zeros(len(self))
+160         classTable[k]=OrderedDict()
+161         for cu,u in enumerate(self.unique(k)) :
+162            idx=np.where(np.array(self.TABLE[k]==u))[0]
+163            iu[idx]=cu
+164            classTable[k][u]=[cu,len(idx)]
+165         self.TABLE[ipfx+k]=iu
+166      self.classTable=classTable.copy()
+167      return classTable
+168   #
+169   def show_classTable(self) :
+170      for k in DB.classTable.keys() :
+171         print('%10s : %3d = '%(k,len(DB.classTable[k])),end='')
+172         for ij,j in enumerate(DB.classTable[k].keys()) : 
+173            if ij>0 : print ('|',end='')
+174            print('%3d#'%ij,end='')
+175            print('%12s'%str(j),':',end='')
+176            print("%6d "%len(DB.query('i_'+k+'=='+str(ij))),end='')
+177         print()
+178   #
+179   def unique(self,key) : 
+180      import numpy as np
+181      return np.sort(self.TABLE[key].unique())
+182   #
+183   def sort(self,sort_by) :
+184      self.TABLE=self.TABLE.sort(sort_by)
+185   #
+186   def sorted_query(self,sort_by,qstr) :
+187      out=self.copy()
+188      if type(qstr) == type('') :
+189         out.TABLE=self.TABLE.query(qstr)
+190      else :
+191         out.TABLE=self.TABLE[qstr]
+192      out.TABLE=out.TABLE.sort(sort_by)
+193      return out
+194   #
+195   def query(self,qstr) :
+196      out=self.copy()
+197      if type(qstr) == type('') :
+198         out.TABLE=self.TABLE.query(qstr)
+199      else :
+200         out.TABLE=self.TABLE[qstr]
+201      return out
+202   #
+203   def select_by_loc(self,loc_argument) :
+204      out=self.copy()
+205      out.TABLE=self.TABLE.loc[loc_argument]
+206      return out
+207   #
+208   def select_by_iloc(self,iloc_argument) :
+209      out=self.copy()
+210      out.TABLE=self.TABLE.iloc[iloc_argument]
+211      return out
+212   #
+213   def classification_string2numeric(self,strg) :
+214      try :
+215         return self._numeric_classification[strg.lower().strip()]
+216      except :
+217         print("bad strng ",strg)
+218         return self._string_class_notfound
+219   #
+220   def calc_iclass(self,string_classification_array) :
+221      return np.array([self._numeric_classification[k.strip().lower()] for k in string_classification_array])
+222   #
+223   def keys(self) : return list(self.TABLE.keys())
+224   #
+225   def has_key(self,this) : return (this in self.TABLE.keys())
+226   #
+227   def __include__(self,this) : return (this in self.TABLE.keys())
+228   #
+229   def reset_plot_status(self) :
+230      """resets the self._last_plot dictionary where handles from the last plot generated are stored"""
+231      from collections import OrderedDict
+232      self._last_plot=OrderedDict()
+233      self._last_plot['fig']=None
+234      self._last_plot['xlabel']=None
+235      self._last_plot['ylabel']=None
+236      self._last_plot['axe']=None
+237      self._last_plot['legend']=None
+238      self._last_plot['curves']=[]
+239   #
+240   def plot2(self,x,y='MolecularDepth',ylog=True,xlog=False,newfig=True,legend_loc=3,xylim=None,savefig=None,one2one_line=False) :
+241      """creates a 2 axis plot, the handles for the plot objects are stored in self._last_plot"""
+242      from collections import OrderedDict
+243      from matplotlib import pyplot as plt
+244      import numpy as np
+245      import pandas
+246      import astropy
+247      #
+248      self.reset_plot_status()
+249      #
+250      if newfig : 
+251         self._last_plot['fig']=plt.figure()
+252      else :
+253         self._last_plot['fig']=plt.gcf()
+254      #
+255      for k in self._ClassNames :  
+256         smp=self.TABLE.query('CLASS=="%s"'%k)
+257         self._last_plot['curves'].append(plt.plot(smp[x],smp[y],self._ClassColor[k]+self._ClassMarker[k][0],label=k,mew=0,markersize=int(self._ClassMarker[k][2:])))
+258      plt.gca().set_xscale('linear' if xlog==False else 'log')
+259      plt.gca().set_yscale('linear' if ylog==False else 'log')
+260      plt.title(self._project_name,fontsize=20)
+261      if xylim != None : plt.axis(xylim)
+262      #
+263      if one2one_line==True :
+264         a=plt.axis()
+265         x121=np.arange(0,1+0.01,0.01)
+266         x121=a[0]*x121+a[1]*(1-x121)
+267         self._last_plot['1:1']=plt.plot(x121,x121,'k-',lw=1)
+268         self._last_plot['1:1'][0].set_zorder(-10)
+269      #
+270      if x=='Natm' :
+271         a=plt.axis()
+272         self._last_plot['STARTNATMLINES']=[plt.plot(k*np.ones(2),[a[2],a[3]],'k-',lw=2) for k in np.unique(self.TABLE['PRESS']/self.TABLE['GRAV'])]
+273         for k in self._last_plot['STARTNATMLINES'] : k[0].set_zorder(-10)
+274      #
+275      if x=='p_surface' :
+276         a=plt.axis()
+277         self._last_plot['PRESS_LINES']=[plt.plot(k*np.ones(2),[a[2],a[3]],'k-',lw=2) for k in np.unique(self.TABLE['PRESS'])]
+278         for k in self._last_plot['PRESS_LINES'] : k[0].set_zorder(-10)
+279      #
+280      self._last_plot['axe']=plt.gca()
+281      if legend_loc > 0 :
+282         self._last_plot['legend']=plt.legend(loc=legend_loc)
+283      self._last_plot['xlabel']=plt.xlabel(x,fontsize=20)
+284      self._last_plot['ylabel']=plt.ylabel(y,fontsize=20)
+285      plt.gcf().set_figwidth(18.)
+286      plt.gcf().set_figheight(plt.gcf().get_figwidth()*3./4.)
+287      if savefig != None and savefig != False:
+288         if type(savefig)==type('') and savefig!='' :
+289            _savefig=savefig
+290         else :
+291            _savefig=self._project_name+'/'+self._figures_path+'/'+y+'_vz_'+x+'.pdf'
+292         print("Saving in ",_savefig)
+293         plt.savefig(_savefig,dpi=plt.gcf().get_dpi())
+294      plt.show()
+295   #
+296   def set_iceTOT_threshold(self,iceTOT_threshold) :
+297      """ set iceTOT_threshold : the ice coverage over which the planet is considered a snowball
+298suggested values 0.95 or 0.99
+299      """
+300      self.iceTOT_threshold=iceTOT_threshold
+301   #
+302   def flag_class_warm(self) :
+303      """returns Murante's classifications for warm calculated from scratch
+304iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+305suggested values 0.95 or 0.99
+306      """
+307      import numpy as np
+308      if not self.iceTOT_threshold() : return
+309      return (self.TABLE['TMGLOB'] > self.TABLE['Tice']) * (self.TABLE['TMGLOB'] < self.TABLE['Tvap'])
+310      
+311   def flag_class_warm_hot(self) :
+312      """returns Murante's classifications for warm_hot calculated from scratch
+313iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+314suggested values 0.95 or 0.99
+315      """
+316      import numpy as np
+317      if not self.iceTOT_threshold() : return
+318      return (self.TABLE['TMGLOB'] >= self.TABLE['Tvap'])
+319      
+320   def flag_class_snowball(self) :
+321      """returns Murante's classifications for warm_hot calculated from scratch
+322iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+323suggested values 0.95 or 0.99
+324      """
+325      import numpy as np
+326      if not self.iceTOT_threshold() : return
+327      return (self.TABLE['ICE'] > self.iceTOT_threshold)
+328      
+329   def flag_class_waterbelt(self) :
+330      """returns Murante's classifications for warm_hot calculated from scratch
+331iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+332suggested values 0.95 or 0.99
+333      """
+334      import numpy as np
+335      if not self.iceTOT_threshold() : return
+336      return (self.TABLE['TMGLOB'] <= self.TABLE['Tice'])*(self.TABLE['ICE'] <= self.iceTOT_threshold)
+337   
+338   def _testIceTot(self) :
+339      if self.iceTOT_threshold == None :
+340         raise Exception("iceTOT_threshold not set, Set iceTOT_threshold with .set_iceTOT_threshold(x) before")
+341         return False
+342      return True
+
+ + +

DEPRECATED

+ +

Class to handle a local version of the ARTECS DB.

+ +

It takes in input a csv file generated from a query of ARTECS and saved in csv format.

+ +

See the example in the introductory page.

+ +

This module is kept for compatibility with early releases of py_artecs, but it is not maintained so its use is DEPRECATED.

+
+ + +
+ +
+ + modelDb( project_name, project_path, csv_name, Verbose=True, csv_sep='!', csv_comment='#', csv_index_col='index', figures_path='png', filterBad=True, new=False, query=None) + + + +
+ +
19   def __init__(self,project_name,project_path,csv_name,Verbose=True,csv_sep='!',csv_comment='#',csv_index_col='index',figures_path='png',filterBad=True,new=False,query=None) :
+20      import time
+21      from collections import OrderedDict
+22      from matplotlib import pyplot as plt
+23      import numpy as np
+24      import pandas
+25      import astropy
+26      #
+27      self.reset()
+28      self.reset_plot_status()
+29      #
+30      self._project_name=project_name
+31      self._project_path=project_path
+32      self._csv_name=csv_name
+33      self._figures_path=figures_path
+34      #
+35      if new : return
+36      #
+37      print()
+38      print("Reading from csv file ",self._csv_name)
+39      tic=time.time()
+40      csv=pandas.read_csv(self._project_path+'/'+self._csv_name,sep=csv_sep,comment=csv_comment,index_col=csv_index_col)
+41      if not 'TSTART' in csv.keys() : 
+42         csv['TSTART']=np.zeros(len(csv))
+43         print ("TSTART not found, replaced by a DUMMY")
+44      csv['Natm']=csv['p_surface']/csv['GRAV']
+45      csv['iclass']=np.array([self.classification_string2numeric(k.strip().lower()) for k in csv.CLASS])
+46      csv['peri']=(1-csv.ECC)*csv.SMA
+47      csv['aphe']=(1+csv.ECC)*csv.SMA
+48      self.flagBad=np.array(csv['iclass']==self._string_class_notfound)*8+np.array(csv.iclass<0)*4+np.array(np.isnan(csv.TMGLOB))*2+np.array(csv.TSTART<0)
+49      tic=time.time()-tic
+50      print("%d lines in %e sec"%(len(csv),tic))
+51      #
+52      if not 'SOURCE' in csv.keys() :
+53         csv['SOURCE']=np.zeros(len(csv))-1
+54      #
+55      if filterBad :
+56         self.TABLE=csv[self.flagBad==0]
+57      else :
+58         self.TABLE=csv
+59      #
+60      if query != None and query!='' :
+61         self.TABLE=self.TABLE.query(query)
+62      #
+63      if Verbose :
+64         print()
+65         print("In %s, containind %d models, the number of models with "%(csv_name,len(csv)))
+66         print("  CLASS  == UNKNOWN                    ",(csv.iclass==-200).sum())
+67         print("  CLASS  == SNOWBALL                   ",(csv.iclass==1).sum())
+68         print("  CLASS  == WATERBELT                  ",(csv.iclass==2).sum())
+69         print("  CLASS  == WARM                       ",(csv.iclass==3).sum())
+70         print("  CLASS  == WARM_HOT                   ",(csv.iclass==4).sum())
+71         print("  INVALID STRING IN CLASS              ",((self.flagBad>=8)).sum())
+72         print()
+73         for k in np.unique(csv['SOURCE']) :
+74            print("  SOURCE == %d                          %d"%(k,(csv.SOURCE==0).sum()))
+75         #print("  SOURCE == 1                          ",(csv.SOURCE==1).sum())
+76         print()
+77         print("  TMGLOB == NaN                        ",np.isnan(csv.TMGLOB).sum())
+78         print("  TSTART<0                             ",(csv.TSTART<0).sum())
+79         print("  TMGLOB == NaN and TSTART<0           ",((csv.TSTART<0)&np.isnan(csv.TMGLOB)).sum())
+80         print("  TMGLOB == NaN and ZCD == NaN         ",(np.isnan(csv.TMGLOB)&np.isnan(csv.zenithal_column_density)).sum())
+81         print("  TMGLOB == NaN and CLASS == UNDEFINED ",(np.isnan(csv.TMGLOB)&(csv.iclass==0)).sum())
+82         print()
+83      #
+84      del csv 
+
+ + + + +
+
+ +
+ + def + to_csv(self, outFile, COMMENT=''): + + + +
+ +
85   def to_csv(self,outFile,COMMENT='') :
+86      print("Writing csv into ",outFile)
+87      open(outFile,'w').write('#\n#'+outFile+'\n#elaboration of '+self._csv_name+'\n#'+str(COMMENT)+'\n#!BEGIN\n')
+88      open(outFile,'a').write(self.TABLE.to_csv(None,sep='!',index_column='index'))
+89      open(outFile,'a').write('#!END\n')
+90      print("written")
+
+ + + + +
+
+ +
+ + def + reset(self): + + + +
+ +
 91   def reset(self) :
+ 92      from collections import OrderedDict
+ 93      for k in ['_project_name','_project_path','_csv_name','_figures_path','_project_name','_project_path','TABLE','flagBad','classTable'] :
+ 94         self.__dict__[k]=None
+ 95      self._numeric_classification=OrderedDict()
+ 96      self._numeric_classification['---']=-400
+ 97      self._numeric_classification['unknown']=-200
+ 98      self._numeric_classification['snowball']=1
+ 99      self._numeric_classification['waterbelt']=2
+100      self._numeric_classification['warm']=3
+101      self._numeric_classification['warm_hot']=4
+102      self._string_class_notfound=-100000
+103      #
+104      self._classification_labels=self._numeric_classification.keys()
+105      self._ClassNames=['SNOWBALL','WATERBELT','WARM','WARM_HOT']
+106      self._ClassColor={'SNOWBALL':'b','WATERBELT':'g','WARM':'r','WARM_HOT':'y'}
+107      self._ClassMarker={'SNOWBALL':'o:12','WATERBELT':'v:16','WARM':'d:8','WARM_HOT':'s:6'}
+108      #
+109      self.iceTOT_threshold=None
+
+ + + + +
+
+ +
+ + def + copy(self): + + + +
+ +
117   def copy(self) :
+118      import copy
+119      out=modelDb('slice of '+self._project_name,self._project_path,None,new=True)
+120      out._project_name=self._project_name
+121      out._project_path=self._project_path
+122      out._csv_name=None
+123      out._figures_path=self._figures_path
+124      out.classTable=copy.deepcopy(self.classTable)
+125      return out
+
+ + + + +
+
+ +
+ + def + unique_values(self): + + + +
+ +
127   def unique_values(self) :
+128      import numpy as np
+129      from collections import OrderedDict
+130      import pandas
+131      out=OrderedDict()
+132      for k in self.keys() :
+133         out[k]=np.unique(self.TABLE[k].values)
+134      return out
+
+ + + + +
+
+ +
+ + def + list_unique_values(self): + + + +
+ +
136   def list_unique_values(self) :
+137      out=self.unique_values()
+138      for k in out.keys() :
+139         print("%s (%d) ="%(k,len(out[k])))
+140      #
+
+ + + + +
+
+ +
+ + def + classification_indexes(self, *arg, **karg): + + + +
+ +
141   def classification_indexes(self,*arg,**karg) :
+142      import numpy as np
+143      from collections import OrderedDict
+144      if len(arg) == 0 : 
+145         _arg=['CLASS','OBLIQ','ECC','SMA','PRESS','SOURCE','GEO','FO_CONST','PROT','P_CO2']
+146      else :
+147         _arg=arg
+148      ipfx=karg['index_pfx'] if karg.has_key('index_pfx') else 'i_'
+149      for k in _arg : 
+150         quit=False
+151         if not k in self.keys() :
+152            print("%s not found "%k)
+153            quit=True
+154      if quit : 
+155         return
+156      classTable=OrderedDict()
+157      for k in arg :
+158         u=self.unique(k)
+159         iu=np.zeros(len(self))
+160         classTable[k]=OrderedDict()
+161         for cu,u in enumerate(self.unique(k)) :
+162            idx=np.where(np.array(self.TABLE[k]==u))[0]
+163            iu[idx]=cu
+164            classTable[k][u]=[cu,len(idx)]
+165         self.TABLE[ipfx+k]=iu
+166      self.classTable=classTable.copy()
+167      return classTable
+
+ + + + +
+
+ +
+ + def + show_classTable(self): + + + +
+ +
169   def show_classTable(self) :
+170      for k in DB.classTable.keys() :
+171         print('%10s : %3d = '%(k,len(DB.classTable[k])),end='')
+172         for ij,j in enumerate(DB.classTable[k].keys()) : 
+173            if ij>0 : print ('|',end='')
+174            print('%3d#'%ij,end='')
+175            print('%12s'%str(j),':',end='')
+176            print("%6d "%len(DB.query('i_'+k+'=='+str(ij))),end='')
+177         print()
+
+ + + + +
+
+ +
+ + def + unique(self, key): + + + +
+ +
179   def unique(self,key) : 
+180      import numpy as np
+181      return np.sort(self.TABLE[key].unique())
+
+ + + + +
+
+ +
+ + def + sort(self, sort_by): + + + +
+ +
183   def sort(self,sort_by) :
+184      self.TABLE=self.TABLE.sort(sort_by)
+
+ + + + +
+
+ +
+ + def + sorted_query(self, sort_by, qstr): + + + +
+ +
186   def sorted_query(self,sort_by,qstr) :
+187      out=self.copy()
+188      if type(qstr) == type('') :
+189         out.TABLE=self.TABLE.query(qstr)
+190      else :
+191         out.TABLE=self.TABLE[qstr]
+192      out.TABLE=out.TABLE.sort(sort_by)
+193      return out
+
+ + + + +
+
+ +
+ + def + query(self, qstr): + + + +
+ +
195   def query(self,qstr) :
+196      out=self.copy()
+197      if type(qstr) == type('') :
+198         out.TABLE=self.TABLE.query(qstr)
+199      else :
+200         out.TABLE=self.TABLE[qstr]
+201      return out
+
+ + + + +
+
+ +
+ + def + select_by_loc(self, loc_argument): + + + +
+ +
203   def select_by_loc(self,loc_argument) :
+204      out=self.copy()
+205      out.TABLE=self.TABLE.loc[loc_argument]
+206      return out
+
+ + + + +
+
+ +
+ + def + select_by_iloc(self, iloc_argument): + + + +
+ +
208   def select_by_iloc(self,iloc_argument) :
+209      out=self.copy()
+210      out.TABLE=self.TABLE.iloc[iloc_argument]
+211      return out
+
+ + + + +
+
+ +
+ + def + classification_string2numeric(self, strg): + + + +
+ +
213   def classification_string2numeric(self,strg) :
+214      try :
+215         return self._numeric_classification[strg.lower().strip()]
+216      except :
+217         print("bad strng ",strg)
+218         return self._string_class_notfound
+
+ + + + +
+
+ +
+ + def + calc_iclass(self, string_classification_array): + + + +
+ +
220   def calc_iclass(self,string_classification_array) :
+221      return np.array([self._numeric_classification[k.strip().lower()] for k in string_classification_array])
+
+ + + + +
+
+ +
+ + def + keys(self): + + + +
+ +
223   def keys(self) : return list(self.TABLE.keys())
+
+ + + + +
+
+ +
+ + def + has_key(self, this): + + + +
+ +
225   def has_key(self,this) : return (this in self.TABLE.keys())
+
+ + + + +
+
+ +
+ + def + reset_plot_status(self): + + + +
+ +
229   def reset_plot_status(self) :
+230      """resets the self._last_plot dictionary where handles from the last plot generated are stored"""
+231      from collections import OrderedDict
+232      self._last_plot=OrderedDict()
+233      self._last_plot['fig']=None
+234      self._last_plot['xlabel']=None
+235      self._last_plot['ylabel']=None
+236      self._last_plot['axe']=None
+237      self._last_plot['legend']=None
+238      self._last_plot['curves']=[]
+
+ + +

resets the self._last_plot dictionary where handles from the last plot generated are stored

+
+ + +
+
+ +
+ + def + plot2( self, x, y='MolecularDepth', ylog=True, xlog=False, newfig=True, legend_loc=3, xylim=None, savefig=None, one2one_line=False): + + + +
+ +
240   def plot2(self,x,y='MolecularDepth',ylog=True,xlog=False,newfig=True,legend_loc=3,xylim=None,savefig=None,one2one_line=False) :
+241      """creates a 2 axis plot, the handles for the plot objects are stored in self._last_plot"""
+242      from collections import OrderedDict
+243      from matplotlib import pyplot as plt
+244      import numpy as np
+245      import pandas
+246      import astropy
+247      #
+248      self.reset_plot_status()
+249      #
+250      if newfig : 
+251         self._last_plot['fig']=plt.figure()
+252      else :
+253         self._last_plot['fig']=plt.gcf()
+254      #
+255      for k in self._ClassNames :  
+256         smp=self.TABLE.query('CLASS=="%s"'%k)
+257         self._last_plot['curves'].append(plt.plot(smp[x],smp[y],self._ClassColor[k]+self._ClassMarker[k][0],label=k,mew=0,markersize=int(self._ClassMarker[k][2:])))
+258      plt.gca().set_xscale('linear' if xlog==False else 'log')
+259      plt.gca().set_yscale('linear' if ylog==False else 'log')
+260      plt.title(self._project_name,fontsize=20)
+261      if xylim != None : plt.axis(xylim)
+262      #
+263      if one2one_line==True :
+264         a=plt.axis()
+265         x121=np.arange(0,1+0.01,0.01)
+266         x121=a[0]*x121+a[1]*(1-x121)
+267         self._last_plot['1:1']=plt.plot(x121,x121,'k-',lw=1)
+268         self._last_plot['1:1'][0].set_zorder(-10)
+269      #
+270      if x=='Natm' :
+271         a=plt.axis()
+272         self._last_plot['STARTNATMLINES']=[plt.plot(k*np.ones(2),[a[2],a[3]],'k-',lw=2) for k in np.unique(self.TABLE['PRESS']/self.TABLE['GRAV'])]
+273         for k in self._last_plot['STARTNATMLINES'] : k[0].set_zorder(-10)
+274      #
+275      if x=='p_surface' :
+276         a=plt.axis()
+277         self._last_plot['PRESS_LINES']=[plt.plot(k*np.ones(2),[a[2],a[3]],'k-',lw=2) for k in np.unique(self.TABLE['PRESS'])]
+278         for k in self._last_plot['PRESS_LINES'] : k[0].set_zorder(-10)
+279      #
+280      self._last_plot['axe']=plt.gca()
+281      if legend_loc > 0 :
+282         self._last_plot['legend']=plt.legend(loc=legend_loc)
+283      self._last_plot['xlabel']=plt.xlabel(x,fontsize=20)
+284      self._last_plot['ylabel']=plt.ylabel(y,fontsize=20)
+285      plt.gcf().set_figwidth(18.)
+286      plt.gcf().set_figheight(plt.gcf().get_figwidth()*3./4.)
+287      if savefig != None and savefig != False:
+288         if type(savefig)==type('') and savefig!='' :
+289            _savefig=savefig
+290         else :
+291            _savefig=self._project_name+'/'+self._figures_path+'/'+y+'_vz_'+x+'.pdf'
+292         print("Saving in ",_savefig)
+293         plt.savefig(_savefig,dpi=plt.gcf().get_dpi())
+294      plt.show()
+
+ + +

creates a 2 axis plot, the handles for the plot objects are stored in self._last_plot

+
+ + +
+
+ +
+ + def + set_iceTOT_threshold(self, iceTOT_threshold): + + + +
+ +
296   def set_iceTOT_threshold(self,iceTOT_threshold) :
+297      """ set iceTOT_threshold : the ice coverage over which the planet is considered a snowball
+298suggested values 0.95 or 0.99
+299      """
+300      self.iceTOT_threshold=iceTOT_threshold
+
+ + +

set iceTOT_threshold : the ice coverage over which the planet is considered a snowball +suggested values 0.95 or 0.99

+
+ + +
+
+ +
+ + def + flag_class_warm(self): + + + +
+ +
302   def flag_class_warm(self) :
+303      """returns Murante's classifications for warm calculated from scratch
+304iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+305suggested values 0.95 or 0.99
+306      """
+307      import numpy as np
+308      if not self.iceTOT_threshold() : return
+309      return (self.TABLE['TMGLOB'] > self.TABLE['Tice']) * (self.TABLE['TMGLOB'] < self.TABLE['Tvap'])
+
+ + +

returns Murante's classifications for warm calculated from scratch +iceTOT_threshold is the ice coverage over which the planet is considered a snowball +suggested values 0.95 or 0.99

+
+ + +
+
+ +
+ + def + flag_class_warm_hot(self): + + + +
+ +
311   def flag_class_warm_hot(self) :
+312      """returns Murante's classifications for warm_hot calculated from scratch
+313iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+314suggested values 0.95 or 0.99
+315      """
+316      import numpy as np
+317      if not self.iceTOT_threshold() : return
+318      return (self.TABLE['TMGLOB'] >= self.TABLE['Tvap'])
+
+ + +

returns Murante's classifications for warm_hot calculated from scratch +iceTOT_threshold is the ice coverage over which the planet is considered a snowball +suggested values 0.95 or 0.99

+
+ + +
+
+ +
+ + def + flag_class_snowball(self): + + + +
+ +
320   def flag_class_snowball(self) :
+321      """returns Murante's classifications for warm_hot calculated from scratch
+322iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+323suggested values 0.95 or 0.99
+324      """
+325      import numpy as np
+326      if not self.iceTOT_threshold() : return
+327      return (self.TABLE['ICE'] > self.iceTOT_threshold)
+
+ + +

returns Murante's classifications for warm_hot calculated from scratch +iceTOT_threshold is the ice coverage over which the planet is considered a snowball +suggested values 0.95 or 0.99

+
+ + +
+
+ +
+ + def + flag_class_waterbelt(self): + + + +
+ +
329   def flag_class_waterbelt(self) :
+330      """returns Murante's classifications for warm_hot calculated from scratch
+331iceTOT_threshold is the ice coverage over which the planet is considered a snowball
+332suggested values 0.95 or 0.99
+333      """
+334      import numpy as np
+335      if not self.iceTOT_threshold() : return
+336      return (self.TABLE['TMGLOB'] <= self.TABLE['Tice'])*(self.TABLE['ICE'] <= self.iceTOT_threshold)
+
+ + +

returns Murante's classifications for warm_hot calculated from scratch +iceTOT_threshold is the ice coverage over which the planet is considered a snowball +suggested values 0.95 or 0.99

+
+ + +
+
+
+ + \ No newline at end of file diff --git a/docs/py_artecs/tap.html b/docs/py_artecs/tap.html new file mode 100644 index 0000000..dfb4d84 --- /dev/null +++ b/docs/py_artecs/tap.html @@ -0,0 +1,1187 @@ + + + + + + + py_artecs.tap API documentation + + + + + + + + + +
+
+

+py_artecs.tap

+ + + + + + +
  1__DESCRIPTION__="""
+  2
+  3TAP services for ARTECS
+  4
+  5By M.Maris 1.1 - 2019 Nov 15 - 
+  6Ported to python3
+  7Needs pyvo 
+  8
+  9
+ 10
+ 11Example:
+ 12   >>> import artecs
+ 13   >>> atap=artecs.exop_pubblic_tap()
+ 14   
+ 15   >>> atap.EXPLAIN()
+ 16   
+ 17   >>> atap.keys()
+ 18
+ 19
+ 20   >>> tab=atap.search('(0.7 <= SMA) and (SMA <=3.)')
+ 21
+ 22   >>> tab.FO_CONST.unique()
+ 23
+ 24   >>> tab.to_csv('/tmp/pippo.csv',sep=' ')
+ 25
+ 26   >>> MAP=atap.get_map(tab.URL[0])
+ 27
+ 28"""
+ 29
+ 30try :
+ 31   import pyvo
+ 32   BAD=False
+ 33except :
+ 34   print("PYVO not found, to install pyvo : \n\t>sudo pip install pyvo\n%s EXOP_TAP class will not work properly"%("/".join(__file__.split('/')[-2:])))
+ 35   BAD=True
+ 36
+ 37#if BAD : 
+ 38   #import sys
+ 39   #sys.exit(1)
+ 40#del BAD
+ 41
+ 42class EXOP_TAP :
+ 43   def __init__(self,tap_url="http://archives.ia2.inaf.it/vo/tap/exo",table_name="exo.EXO",temporary_files_path='/tmp') :
+ 44      import pyvo
+ 45      #
+ 46      #creates empty object
+ 47      self._empty()
+ 48      #
+ 49      self._temporary_files_path=temporary_files_path+'/' if temporary_files_path!='' and temporary_files_path!=None else ''
+ 50      #
+ 51      #connects to db 
+ 52      self._url=tap_url
+ 53      self._table_name=table_name
+ 54      #
+ 55      #template for query_string, two fields: <QUERY> <FIELDS>
+ 56      self._template_query="SELECT %s %s FROM "+self._table_name
+ 57      #
+ 58      try :
+ 59         self._tap_service = pyvo.dal.TAPService(tap_url)
+ 60      except :
+ 61         print ("Error, unable to connect to TAP_URL '"+tap_url+"'")
+ 62      #
+ 63      #from db gets fields description
+ 64      self._get_field_description()
+ 65   #
+ 66   def _empty(self) :
+ 67      self._url=None
+ 68      self._table_name=None
+ 69      self._tap_service = None
+ 70      self._elapsed_time=0.
+ 71      self._search_result=None
+ 72      self._field_description=None
+ 73      self._field_names=None
+ 74      self._search_success=None
+ 75      self._template_query=None
+ 76      self._download_success=None
+ 77   #
+ 78   def _get_field_description(self) :
+ 79      self.adql_search('SELECT TOP 1 * FROM '+self._table_name)
+ 80      self._field_description=self._search_result.fielddescs
+ 81      self._field_names=self._search_result.fieldnames
+ 82      self.clean()
+ 83   #
+ 84   def keys(self) :
+ 85      """list of fields in the database"""
+ 86      return self._field_names
+ 87   #
+ 88   def has_key(self,this) :
+ 89      """has_key"""
+ 90      return this in self._field_names
+ 91   #
+ 92   def __include__(self,this) :
+ 93      """this in object"""
+ 94      return this in self._field_names
+ 95   #
+ 96   def success(self) : 
+ 97      """returns True if last search was successfull"""
+ 98      return self._search_success==True
+ 99   #
+100   def clean(self) :
+101      """cleans information from last search"""
+102      self._search_success=None
+103      self._search_result=None
+104   #
+105   def adql_search(self,adql_string) :
+106      """search on database using ADQL string """
+107      import time
+108      self.clean()
+109      self._search_success=False
+110      self._elapsed_time=time.time()
+111      self._search_result=self._tap_service.search(adql_string)
+112      self._elapsed_time=time.time()-self._elapsed_time
+113      self._search_success=True
+114   #
+115   def search_string(self,SELECTION,TOP,FIELDS,WHERE,SORT) :
+116      """creates a properly formatted adql query_string"""
+117      adql='SELECT' 
+118      adql+='' if type(SELECTION)==type(None) else ' '+SELECT
+119      adql+=' TOP %d'%TOP if type(TOP)==type(1) else '' 
+120      adql+=' *' if type(FIELDS)==type(None) else ' '+FIELDS
+121      adql+=' FROM '+self._table_name 
+122      adql+='' if WHERE=='' or WHERE==None else ' WHERE '+WHERE
+123      adql+='' if SORT=='' or SORT==None else ' SORT BY '+SORT
+124      return adql
+125   #
+126   def search(self,WHERE,SELECTION=None,FIELDS=None,TOP=None,SORT=None,as_astropy=False,as_votable=False) :
+127      """download a table from the database
+128         search('') or search(WHERE='') returns all the data in the database
+129         
+130         the table can be returned as :
+131            pandas dataframe (default)
+132            astropy table (as_astropy = True)
+133            votable (as_votable=True)
+134      """
+135      import time
+136      #
+137      adql=self.search_string(SELECTION,TOP,FIELDS,WHERE,SORT)
+138      self.adql_search(adql)
+139      #
+140      if as_astropy :
+141         return self._search_result.table
+142      elif as_votable :
+143         return self._search_result.votable
+144      else :
+145         return self._search_result.table.to_pandas()
+146   #
+147   def get_map(self,_URL,outfile=None) :
+148      """gets a map """
+149      import numpy as np
+150      import time
+151      from .artecs_map import artecs_map
+152      try :
+153         from urllib2 import urlopen
+154      except :
+155         from urllib.request import urlopen
+156      import requests
+157      import gzip
+158      import os
+159      try :
+160         from StringIO import StringIO
+161      except :
+162         from io import StringIO
+163      if type(_URL) == type("") :
+164         URL=_URL+''
+165      else :
+166         URL=_URL.decode("utf-8")
+167      #
+168      if type(outfile) != type('') :
+169         #if out file not specified creates a unique temporary name and reserves it
+170         flag = True
+171         while flag :
+172            tmp=URL+' '+time.asctime()
+173            tmp=tmp+' '+str(np.random.randint(1000000))
+174            tmp=abs(hash(tmp))
+175            tmp=hex( tmp )[2:]
+176            _o=self._temporary_files_path+'artecs_download_file_'+tmp+'.fits'
+177            flag=os.path.isfile(_o)
+178            open(_o,'w').write('a') #this is to reserve the file name
+179      else :
+180         _o=outfile
+181      #
+182      tic=time.time()
+183      request=requests.Request(URL)
+184      #response = urlopen(request)
+185      try :
+186         response = urlopen(URL)
+187      except :
+188         print("URL %s not found"%URL)
+189         if type(outfile) != type('') :
+190            os.remove(_o)
+191         self._download_success=False
+192         return
+193      #buf = StringIO(response.read())
+194      buf = response
+195      f = gzip.GzipFile(fileobj=buf)
+196      data=f.read()
+197      open(_o,'wb').write(data)
+198      tic=time.time()-tic
+199      #
+200      amap=artecs_map(_o)
+201      amap.url=URL
+202      if type(outfile) != type('') :
+203         os.remove(_o)
+204      self._download_success=True
+205      return amap
+206   #
+207   def download_map(self,URL,outfile=None,path=None) :
+208      """download the fits file corresponding at a given URL
+209      if outfile is not specified the fits file name from the URL is used
+210      if path is not specified the current file is stored in the current path
+211      """
+212      _path='' if type(path) != type('') else path+'/'
+213      if type(outfile)!=type('') :
+214         _o=URL.split('/')[-1].split('.gz')[0]
+215         _o=_path+_o
+216      else :
+217         _o=outfile
+218      self.get_map(URL,outfile=_o)
+219   # 
+220   def EXPLAIN(self) :
+221      """print a short introduction on the query language"""
+222      print ("""
+223ADQL = Astronomical Data Query Language
+224
+225A query is a string 
+226- SELECTION set of data to be selected
+227- HOW_MANY elements to select
+228- WHICH_FIELDS fields to select
+229- FROM which table
+230- WHERE condition for selection is true
+231
+232Example:
+233
+2341. Download all the data
+235   SELECT * FROM exo.EXO
+236   
+2372. Download only the first 10 elements
+238   SELECT TOP 10 * FROM exo.EXO
+239
+2403. Download only the first 10 elements with SMA in the range 0.9 to 1.1
+241   SELECT TOP 10 * FROM exo.EXO WHERE SMA BETWEEN 0.9 AND 1.1
+242   
+243   alternativelly
+244
+245   SELECT TOP 10 * FROM exo.EXO WHERE (0.9 <= SMA) AND (SMA <= 1.1)
+246
+2474. Download only the first 10 elements with SMA in the range 0.9 to 1.1 and CONTHAB>=0.5
+248   SELECT TOP 10 * FROM exo.EXO WHERE SMA BETWEEN 0.9 AND 1.1 AND CONTHAB>=0.5
+249
+2505. Arithmetic calculations are allowed if needed for selection so to download the first 10 elements with SMA^1.5 > 0.87 
+251   SELECT TOP 10 * FROM exo.EXO WHERE power(SMA,1.5)> 0.87 
+252   
+2536. returns just columns SMA and CONTHAB from previous example:
+254   SELECT TOP 10 SMA,CONTHAB FROM exo.EXO WHERE power(SMA,1.5)> 0.87 
+255   
+256Note that the query is not sensitive to uppercase or lowercase.
+257
+258Tutorials: 
+259   http://www.g-vo.org/tutorials/gaia-mock-tap.pdf
+260   http://www.ivoa.net/documents/REC/ADQL/ADQL-20081030.pdf
+261   http://www.ivoa.net/documents/
+262
+263""")
+264
+265      
+
+ + +
+
+ +
+ + class + EXOP_TAP: + + + +
+ +
 43class EXOP_TAP :
+ 44   def __init__(self,tap_url="http://archives.ia2.inaf.it/vo/tap/exo",table_name="exo.EXO",temporary_files_path='/tmp') :
+ 45      import pyvo
+ 46      #
+ 47      #creates empty object
+ 48      self._empty()
+ 49      #
+ 50      self._temporary_files_path=temporary_files_path+'/' if temporary_files_path!='' and temporary_files_path!=None else ''
+ 51      #
+ 52      #connects to db 
+ 53      self._url=tap_url
+ 54      self._table_name=table_name
+ 55      #
+ 56      #template for query_string, two fields: <QUERY> <FIELDS>
+ 57      self._template_query="SELECT %s %s FROM "+self._table_name
+ 58      #
+ 59      try :
+ 60         self._tap_service = pyvo.dal.TAPService(tap_url)
+ 61      except :
+ 62         print ("Error, unable to connect to TAP_URL '"+tap_url+"'")
+ 63      #
+ 64      #from db gets fields description
+ 65      self._get_field_description()
+ 66   #
+ 67   def _empty(self) :
+ 68      self._url=None
+ 69      self._table_name=None
+ 70      self._tap_service = None
+ 71      self._elapsed_time=0.
+ 72      self._search_result=None
+ 73      self._field_description=None
+ 74      self._field_names=None
+ 75      self._search_success=None
+ 76      self._template_query=None
+ 77      self._download_success=None
+ 78   #
+ 79   def _get_field_description(self) :
+ 80      self.adql_search('SELECT TOP 1 * FROM '+self._table_name)
+ 81      self._field_description=self._search_result.fielddescs
+ 82      self._field_names=self._search_result.fieldnames
+ 83      self.clean()
+ 84   #
+ 85   def keys(self) :
+ 86      """list of fields in the database"""
+ 87      return self._field_names
+ 88   #
+ 89   def has_key(self,this) :
+ 90      """has_key"""
+ 91      return this in self._field_names
+ 92   #
+ 93   def __include__(self,this) :
+ 94      """this in object"""
+ 95      return this in self._field_names
+ 96   #
+ 97   def success(self) : 
+ 98      """returns True if last search was successfull"""
+ 99      return self._search_success==True
+100   #
+101   def clean(self) :
+102      """cleans information from last search"""
+103      self._search_success=None
+104      self._search_result=None
+105   #
+106   def adql_search(self,adql_string) :
+107      """search on database using ADQL string """
+108      import time
+109      self.clean()
+110      self._search_success=False
+111      self._elapsed_time=time.time()
+112      self._search_result=self._tap_service.search(adql_string)
+113      self._elapsed_time=time.time()-self._elapsed_time
+114      self._search_success=True
+115   #
+116   def search_string(self,SELECTION,TOP,FIELDS,WHERE,SORT) :
+117      """creates a properly formatted adql query_string"""
+118      adql='SELECT' 
+119      adql+='' if type(SELECTION)==type(None) else ' '+SELECT
+120      adql+=' TOP %d'%TOP if type(TOP)==type(1) else '' 
+121      adql+=' *' if type(FIELDS)==type(None) else ' '+FIELDS
+122      adql+=' FROM '+self._table_name 
+123      adql+='' if WHERE=='' or WHERE==None else ' WHERE '+WHERE
+124      adql+='' if SORT=='' or SORT==None else ' SORT BY '+SORT
+125      return adql
+126   #
+127   def search(self,WHERE,SELECTION=None,FIELDS=None,TOP=None,SORT=None,as_astropy=False,as_votable=False) :
+128      """download a table from the database
+129         search('') or search(WHERE='') returns all the data in the database
+130         
+131         the table can be returned as :
+132            pandas dataframe (default)
+133            astropy table (as_astropy = True)
+134            votable (as_votable=True)
+135      """
+136      import time
+137      #
+138      adql=self.search_string(SELECTION,TOP,FIELDS,WHERE,SORT)
+139      self.adql_search(adql)
+140      #
+141      if as_astropy :
+142         return self._search_result.table
+143      elif as_votable :
+144         return self._search_result.votable
+145      else :
+146         return self._search_result.table.to_pandas()
+147   #
+148   def get_map(self,_URL,outfile=None) :
+149      """gets a map """
+150      import numpy as np
+151      import time
+152      from .artecs_map import artecs_map
+153      try :
+154         from urllib2 import urlopen
+155      except :
+156         from urllib.request import urlopen
+157      import requests
+158      import gzip
+159      import os
+160      try :
+161         from StringIO import StringIO
+162      except :
+163         from io import StringIO
+164      if type(_URL) == type("") :
+165         URL=_URL+''
+166      else :
+167         URL=_URL.decode("utf-8")
+168      #
+169      if type(outfile) != type('') :
+170         #if out file not specified creates a unique temporary name and reserves it
+171         flag = True
+172         while flag :
+173            tmp=URL+' '+time.asctime()
+174            tmp=tmp+' '+str(np.random.randint(1000000))
+175            tmp=abs(hash(tmp))
+176            tmp=hex( tmp )[2:]
+177            _o=self._temporary_files_path+'artecs_download_file_'+tmp+'.fits'
+178            flag=os.path.isfile(_o)
+179            open(_o,'w').write('a') #this is to reserve the file name
+180      else :
+181         _o=outfile
+182      #
+183      tic=time.time()
+184      request=requests.Request(URL)
+185      #response = urlopen(request)
+186      try :
+187         response = urlopen(URL)
+188      except :
+189         print("URL %s not found"%URL)
+190         if type(outfile) != type('') :
+191            os.remove(_o)
+192         self._download_success=False
+193         return
+194      #buf = StringIO(response.read())
+195      buf = response
+196      f = gzip.GzipFile(fileobj=buf)
+197      data=f.read()
+198      open(_o,'wb').write(data)
+199      tic=time.time()-tic
+200      #
+201      amap=artecs_map(_o)
+202      amap.url=URL
+203      if type(outfile) != type('') :
+204         os.remove(_o)
+205      self._download_success=True
+206      return amap
+207   #
+208   def download_map(self,URL,outfile=None,path=None) :
+209      """download the fits file corresponding at a given URL
+210      if outfile is not specified the fits file name from the URL is used
+211      if path is not specified the current file is stored in the current path
+212      """
+213      _path='' if type(path) != type('') else path+'/'
+214      if type(outfile)!=type('') :
+215         _o=URL.split('/')[-1].split('.gz')[0]
+216         _o=_path+_o
+217      else :
+218         _o=outfile
+219      self.get_map(URL,outfile=_o)
+220   # 
+221   def EXPLAIN(self) :
+222      """print a short introduction on the query language"""
+223      print ("""
+224ADQL = Astronomical Data Query Language
+225
+226A query is a string 
+227- SELECTION set of data to be selected
+228- HOW_MANY elements to select
+229- WHICH_FIELDS fields to select
+230- FROM which table
+231- WHERE condition for selection is true
+232
+233Example:
+234
+2351. Download all the data
+236   SELECT * FROM exo.EXO
+237   
+2382. Download only the first 10 elements
+239   SELECT TOP 10 * FROM exo.EXO
+240
+2413. Download only the first 10 elements with SMA in the range 0.9 to 1.1
+242   SELECT TOP 10 * FROM exo.EXO WHERE SMA BETWEEN 0.9 AND 1.1
+243   
+244   alternativelly
+245
+246   SELECT TOP 10 * FROM exo.EXO WHERE (0.9 <= SMA) AND (SMA <= 1.1)
+247
+2484. Download only the first 10 elements with SMA in the range 0.9 to 1.1 and CONTHAB>=0.5
+249   SELECT TOP 10 * FROM exo.EXO WHERE SMA BETWEEN 0.9 AND 1.1 AND CONTHAB>=0.5
+250
+2515. Arithmetic calculations are allowed if needed for selection so to download the first 10 elements with SMA^1.5 > 0.87 
+252   SELECT TOP 10 * FROM exo.EXO WHERE power(SMA,1.5)> 0.87 
+253   
+2546. returns just columns SMA and CONTHAB from previous example:
+255   SELECT TOP 10 SMA,CONTHAB FROM exo.EXO WHERE power(SMA,1.5)> 0.87 
+256   
+257Note that the query is not sensitive to uppercase or lowercase.
+258
+259Tutorials: 
+260   http://www.g-vo.org/tutorials/gaia-mock-tap.pdf
+261   http://www.ivoa.net/documents/REC/ADQL/ADQL-20081030.pdf
+262   http://www.ivoa.net/documents/
+263
+264""")
+
+ + + + +
+ +
+ + EXOP_TAP( tap_url='http://archives.ia2.inaf.it/vo/tap/exo', table_name='exo.EXO', temporary_files_path='/tmp') + + + +
+ +
44   def __init__(self,tap_url="http://archives.ia2.inaf.it/vo/tap/exo",table_name="exo.EXO",temporary_files_path='/tmp') :
+45      import pyvo
+46      #
+47      #creates empty object
+48      self._empty()
+49      #
+50      self._temporary_files_path=temporary_files_path+'/' if temporary_files_path!='' and temporary_files_path!=None else ''
+51      #
+52      #connects to db 
+53      self._url=tap_url
+54      self._table_name=table_name
+55      #
+56      #template for query_string, two fields: <QUERY> <FIELDS>
+57      self._template_query="SELECT %s %s FROM "+self._table_name
+58      #
+59      try :
+60         self._tap_service = pyvo.dal.TAPService(tap_url)
+61      except :
+62         print ("Error, unable to connect to TAP_URL '"+tap_url+"'")
+63      #
+64      #from db gets fields description
+65      self._get_field_description()
+
+ + + + +
+
+ +
+ + def + keys(self): + + + +
+ +
85   def keys(self) :
+86      """list of fields in the database"""
+87      return self._field_names
+
+ + +

list of fields in the database

+
+ + +
+
+ +
+ + def + has_key(self, this): + + + +
+ +
89   def has_key(self,this) :
+90      """has_key"""
+91      return this in self._field_names
+
+ + +

has_key

+
+ + +
+
+ +
+ + def + success(self): + + + +
+ +
97   def success(self) : 
+98      """returns True if last search was successfull"""
+99      return self._search_success==True
+
+ + +

returns True if last search was successfull

+
+ + +
+
+ +
+ + def + clean(self): + + + +
+ +
101   def clean(self) :
+102      """cleans information from last search"""
+103      self._search_success=None
+104      self._search_result=None
+
+ + +

cleans information from last search

+
+ + +
+ +
+ +
+ + def + search_string(self, SELECTION, TOP, FIELDS, WHERE, SORT): + + + +
+ +
116   def search_string(self,SELECTION,TOP,FIELDS,WHERE,SORT) :
+117      """creates a properly formatted adql query_string"""
+118      adql='SELECT' 
+119      adql+='' if type(SELECTION)==type(None) else ' '+SELECT
+120      adql+=' TOP %d'%TOP if type(TOP)==type(1) else '' 
+121      adql+=' *' if type(FIELDS)==type(None) else ' '+FIELDS
+122      adql+=' FROM '+self._table_name 
+123      adql+='' if WHERE=='' or WHERE==None else ' WHERE '+WHERE
+124      adql+='' if SORT=='' or SORT==None else ' SORT BY '+SORT
+125      return adql
+
+ + +

creates a properly formatted adql query_string

+
+ + +
+
+ +
+ + def + search( self, WHERE, SELECTION=None, FIELDS=None, TOP=None, SORT=None, as_astropy=False, as_votable=False): + + + +
+ +
127   def search(self,WHERE,SELECTION=None,FIELDS=None,TOP=None,SORT=None,as_astropy=False,as_votable=False) :
+128      """download a table from the database
+129         search('') or search(WHERE='') returns all the data in the database
+130         
+131         the table can be returned as :
+132            pandas dataframe (default)
+133            astropy table (as_astropy = True)
+134            votable (as_votable=True)
+135      """
+136      import time
+137      #
+138      adql=self.search_string(SELECTION,TOP,FIELDS,WHERE,SORT)
+139      self.adql_search(adql)
+140      #
+141      if as_astropy :
+142         return self._search_result.table
+143      elif as_votable :
+144         return self._search_result.votable
+145      else :
+146         return self._search_result.table.to_pandas()
+
+ + +

download a table from the database +search('') or search(WHERE='') returns all the data in the database

+ +

the table can be returned as : + pandas dataframe (default) + astropy table (as_astropy = True) + votable (as_votable=True)

+
+ + +
+
+ +
+ + def + get_map(self, _URL, outfile=None): + + + +
+ +
148   def get_map(self,_URL,outfile=None) :
+149      """gets a map """
+150      import numpy as np
+151      import time
+152      from .artecs_map import artecs_map
+153      try :
+154         from urllib2 import urlopen
+155      except :
+156         from urllib.request import urlopen
+157      import requests
+158      import gzip
+159      import os
+160      try :
+161         from StringIO import StringIO
+162      except :
+163         from io import StringIO
+164      if type(_URL) == type("") :
+165         URL=_URL+''
+166      else :
+167         URL=_URL.decode("utf-8")
+168      #
+169      if type(outfile) != type('') :
+170         #if out file not specified creates a unique temporary name and reserves it
+171         flag = True
+172         while flag :
+173            tmp=URL+' '+time.asctime()
+174            tmp=tmp+' '+str(np.random.randint(1000000))
+175            tmp=abs(hash(tmp))
+176            tmp=hex( tmp )[2:]
+177            _o=self._temporary_files_path+'artecs_download_file_'+tmp+'.fits'
+178            flag=os.path.isfile(_o)
+179            open(_o,'w').write('a') #this is to reserve the file name
+180      else :
+181         _o=outfile
+182      #
+183      tic=time.time()
+184      request=requests.Request(URL)
+185      #response = urlopen(request)
+186      try :
+187         response = urlopen(URL)
+188      except :
+189         print("URL %s not found"%URL)
+190         if type(outfile) != type('') :
+191            os.remove(_o)
+192         self._download_success=False
+193         return
+194      #buf = StringIO(response.read())
+195      buf = response
+196      f = gzip.GzipFile(fileobj=buf)
+197      data=f.read()
+198      open(_o,'wb').write(data)
+199      tic=time.time()-tic
+200      #
+201      amap=artecs_map(_o)
+202      amap.url=URL
+203      if type(outfile) != type('') :
+204         os.remove(_o)
+205      self._download_success=True
+206      return amap
+
+ + +

gets a map

+
+ + +
+
+ +
+ + def + download_map(self, URL, outfile=None, path=None): + + + +
+ +
208   def download_map(self,URL,outfile=None,path=None) :
+209      """download the fits file corresponding at a given URL
+210      if outfile is not specified the fits file name from the URL is used
+211      if path is not specified the current file is stored in the current path
+212      """
+213      _path='' if type(path) != type('') else path+'/'
+214      if type(outfile)!=type('') :
+215         _o=URL.split('/')[-1].split('.gz')[0]
+216         _o=_path+_o
+217      else :
+218         _o=outfile
+219      self.get_map(URL,outfile=_o)
+
+ + +

download the fits file corresponding at a given URL +if outfile is not specified the fits file name from the URL is used +if path is not specified the current file is stored in the current path

+
+ + +
+
+ +
+ + def + EXPLAIN(self): + + + +
+ +
221   def EXPLAIN(self) :
+222      """print a short introduction on the query language"""
+223      print ("""
+224ADQL = Astronomical Data Query Language
+225
+226A query is a string 
+227- SELECTION set of data to be selected
+228- HOW_MANY elements to select
+229- WHICH_FIELDS fields to select
+230- FROM which table
+231- WHERE condition for selection is true
+232
+233Example:
+234
+2351. Download all the data
+236   SELECT * FROM exo.EXO
+237   
+2382. Download only the first 10 elements
+239   SELECT TOP 10 * FROM exo.EXO
+240
+2413. Download only the first 10 elements with SMA in the range 0.9 to 1.1
+242   SELECT TOP 10 * FROM exo.EXO WHERE SMA BETWEEN 0.9 AND 1.1
+243   
+244   alternativelly
+245
+246   SELECT TOP 10 * FROM exo.EXO WHERE (0.9 <= SMA) AND (SMA <= 1.1)
+247
+2484. Download only the first 10 elements with SMA in the range 0.9 to 1.1 and CONTHAB>=0.5
+249   SELECT TOP 10 * FROM exo.EXO WHERE SMA BETWEEN 0.9 AND 1.1 AND CONTHAB>=0.5
+250
+2515. Arithmetic calculations are allowed if needed for selection so to download the first 10 elements with SMA^1.5 > 0.87 
+252   SELECT TOP 10 * FROM exo.EXO WHERE power(SMA,1.5)> 0.87 
+253   
+2546. returns just columns SMA and CONTHAB from previous example:
+255   SELECT TOP 10 SMA,CONTHAB FROM exo.EXO WHERE power(SMA,1.5)> 0.87 
+256   
+257Note that the query is not sensitive to uppercase or lowercase.
+258
+259Tutorials: 
+260   http://www.g-vo.org/tutorials/gaia-mock-tap.pdf
+261   http://www.ivoa.net/documents/REC/ADQL/ADQL-20081030.pdf
+262   http://www.ivoa.net/documents/
+263
+264""")
+
+ + +

print a short introduction on the query language

+
+ + +
+
+
+ + \ No newline at end of file diff --git a/docs/search.js b/docs/search.js new file mode 100644 index 0000000..9acf963 --- /dev/null +++ b/docs/search.js @@ -0,0 +1,46 @@ +window.pdocSearch = (function(){ +/** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();oA Python3 library to handle contents of ARTECS: Archive of terrestrial-type climate simulations

\n\n
http://wwwuser.oats.inaf.it/exobio/climates/\n
\n\n

through TAP and the PYVO services.

\n\n

Authors: Michele Maris (1), Marco Molinaro (1)

\n\n
(1) INAF/Trieste Astronomical Observatory\n
\n\n

First Issue: 2019 Nov 20

\n\n

Dependencies:

\n\n

This package needs: \n numpy, scipy, pandas, pyvo

\n\n

Installation

\n\n

For the latest release:

\n\n
\n
>>> pip3 install py_artecs\n
\n
\n\n

for the dev version clone this GitLab repository.

\n\n

Files in py_artecs

\n\n

__init__.py : the init file

\n\n

tap.py : the file with the TAP library

\n\n

artecs_map.py : a utility class to handle a local fits file with a Temperature MAP downloaded from the archive

\n\n

modelDB.py : a utility class to handle a local csv file with the result of a query, this module is kept for backward compatibility, but its use is deprecated

\n\n

Example of session:

\n\n

The archive is accessed from the exop_pubblic_tap in py_artecs:

\n\n
\n
>>> from artecs import exop_pubblic_tap\n
\n
\n\n

Then instantiate a database object

\n\n
\n
>>> atap=exop_pubblic_tap()\n
\n
\n\n

all the queries to ARTECS are made through the methods in atap.

\n\n

Queries follows the Astronomical Data Query Language (ADQL) format

\n\n
\n
>>> ptab=atap.search('power(SMA,1.5)>0.87');\n
\n
\n\n

see the appendix for further references on the ADQL.

\n\n

To know wether the search is successfull:

\n\n
\n
>>> atap.success()\nTrue\n
\n
\n\n

The result of a query is stored in ptab as a PANDAS data_frame.

\n\n

In order to save the table as a csv file use the \"to_csv\" method of pandas data frame:

\n\n
\n
>>> ptab.to_csv('result.csv',sep=' ')\n
\n
\n\n

In order to get a map corresponding to the first entry in the ptab use:

\n\n
\n
>>> TMAP=atap.get_map(ptab.URL[0])\n
\n
\n\n

the command creates a fits file to rercover the fits filename

\n\n
\n
>>> print(MAP.filename)\n/tmp/artecs_download_file_669d40064f5bddc8.fits\n
\n
\n\n

note that the get_map method saved the fits inside the /tmp directory and gives it a dummy name.

\n\n

To specify a different name and directory use the outfile keyword in get_map

\n\n
\n
>>> TMAP=atap.get_map(ptab.URL[0],outfile='./test.fits')\n>>> print(TMAP.filename)\n./test.fits\n
\n
\n\n

TMAP is an object of class artecs_map, so it contains the temperature MAP in the ARTECS fits file, as well as the other keywords in the original fits file.

\n\n

Note that the artecs_map class can be used also local copies of the ARTECS temperature maps.

\n\n

At last, to perform a new query reset the old one with:

\n\n
\n
>>> atap.clear()\n
\n
\n\n

Appendix A: ADQL Queries

\n\n

A query is a string \n . SELECTION set of data to be selected\n . HOW_MANY elements to select\n . WHICH_FIELDS fields to select\n . FROM which table\n . WHERE condition for selection is true

\n\n

Examples of query strings:

\n\n
    \n
  1. Download all the data:

    \n\n
    \n

    SELECT * FROM exo.EXO

    \n
  2. \n
  3. Download only the first 10 elements:

    \n\n
    \n

    SELECT TOP 10 * FROM exo.EXO

    \n
  4. \n
  5. Download only the first 10 elements with SMA in the range 0.9 to 1.1:

    \n\n
    \n

    SELECT TOP 10 * FROM exo.EXO WHERE SMA BETWEEN 0.9 AND 1.1

    \n
    \n\n

    alternativelly

    \n\n
    \n

    SELECT TOP 10 * FROM exo.EXO WHERE (0.9 <= SMA) AND (SMA <= 1.1)

    \n
  6. \n
  7. Download only the first 10 elements with SMA in the range 0.9 to 1.1 and CONTHAB>=0.5

    \n\n
    \n

    SELECT TOP 10 * FROM exo.EXO WHERE SMA BETWEEN 0.9 AND 1.1 AND CONTHAB>=0.5

    \n
  8. \n
  9. Arithmetic calculations are allowed if needed for selection so to download the first 10 elements with SMA^1.5 > 0.87

    \n\n
    \n

    SELECT TOP 10 * FROM exo.EXO WHERE power(SMA,1.5)> 0.87

    \n
  10. \n
  11. returns just columns SMA and CONTHAB from previous example:

    \n\n
    \n

    SELECT TOP 10 SMA,CONTHAB FROM exo.EXO WHERE power(SMA,1.5)> 0.87

    \n
  12. \n
\n\n

Note that the query string is not sensitive to uppercase or lowercase.

\n\n

For tutorials see:

\n\n\n\n

A reminder of how to form query strings can be recalled by calling:

\n\n
\n
>>> atap.EXPLAIN()\n
\n
\n\n

Appendix B: REFERENCES

\n\n

Please quote

\n\n

Climate bistability of Earth-like exoplanets

\n\n

Murante G., Provenzale A., Vladilo G.,Taffoni G., Silva L., Palazzi E.,von Hardenberg J.,Maris M., Londero E., Knapic C., Zorba C.

\n\n

MNRAS 492, 2638\u20132650 (2020)

\n\n

doi: 10.1093/mnras/stz3529

\n\n

Appendix C: Example of session with TAP

\n\n

It is possible to access the archive directly with TAP

\n\n
\n
>>> import pyvo as vo\n>>> tap_service = vo.dal.TAPService("http://archives.ia2.inaf.it/vo/tap/exo")\n>>> tap_results = tap_service.search("SELECT top 1 exp_id, url FROM exo.EXO")\n>>> print(tap_results)\n>>>...\n>>> len(tap_results)\n>>>...\n>>> tap_results.getrecord(0)\n>>>...\n
\n
\n\n

Appendix D: to install pyvo

\n\n
\n
>>> sudo pip3 install pyvo\n
\n
\n"}, {"fullname": "py_artecs.artecs_map", "modulename": "py_artecs.artecs_map", "kind": "module", "doc": "

\n"}, {"fullname": "py_artecs.artecs_map.artecs_map", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map", "kind": "class", "doc": "

A class to handle a temperature map from ARTECS.

\n\n

It reads the artecs_map from a fits file.

\n\n
\n
>>> AMAP=artecs_map("artecs_map.fits")\n
\n
\n\n

Keywords in the map are returned as members of the class or using the method \"parameter\".

\n\n

Example:

\n\n
\n
>>> AMAP.temp \n
\n
\n\n

returns the temperature map,

\n\n
\n
>>> AMAP.parameter('temp')\n
\n
\n\n

returns the temperature map.

\n\n
\n
>>> AMAP.shape\n
\n
\n\n

returns the shape of the map (rows, columns)

\n"}, {"fullname": "py_artecs.artecs_map.artecs_map.__init__", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map.__init__", "kind": "function", "doc": "

To instantiate the class pass the filename from which to load the Temperature map

\n\n
\n

Keywords:

\n
\n\n
\n
\n

verbose: if True verbose output

\n
\n
\n\n
\n
\n

closeFits: if True the fits file is closed after reading

\n
\n
\n", "signature": "(filename, closeFits=True, verbose=False)"}, {"fullname": "py_artecs.artecs_map.artecs_map.filename", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map.filename", "kind": "variable", "doc": "

parameter: the filename

\n"}, {"fullname": "py_artecs.artecs_map.artecs_map.p", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map.p", "kind": "variable", "doc": "

the fits file pointer, normally closed.

\n"}, {"fullname": "py_artecs.artecs_map.artecs_map.lst_lat", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map.lst_lat", "kind": "variable", "doc": "

list of latitude bands

\n"}, {"fullname": "py_artecs.artecs_map.artecs_map.lst_year", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map.lst_year", "kind": "variable", "doc": "

list of time intervals

\n"}, {"fullname": "py_artecs.artecs_map.artecs_map.shape", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map.shape", "kind": "variable", "doc": "

the shape of the 2D maps

\n"}, {"fullname": "py_artecs.artecs_map.artecs_map.TMGLOB", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map.TMGLOB", "kind": "variable", "doc": "

the mean surface temperature

\n"}, {"fullname": "py_artecs.artecs_map.artecs_map.keys", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map.keys", "kind": "function", "doc": "

returns the list of quantities in the map

\n\n

Keywords:

\n\n
\n

maps (default False), if True returns just the list of of elements which are 2D maps

\n
\n", "signature": "(self, maps=False):", "funcdef": "def"}, {"fullname": "py_artecs.artecs_map.artecs_map.has_key", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map.has_key", "kind": "function", "doc": "

True if required key is in the map

\n", "signature": "(self, key):", "funcdef": "def"}, {"fullname": "py_artecs.artecs_map.artecs_map.parameter", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map.parameter", "kind": "function", "doc": "

returns a parameter from the fits file from its `key'

\n", "signature": "(self, key):", "funcdef": "def"}, {"fullname": "py_artecs.artecs_map.artecs_map.description", "modulename": "py_artecs.artecs_map", "qualname": "artecs_map.description", "kind": "function", "doc": "

returns the description of a parameter in the fits file from its `key'

\n", "signature": "(self, key):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb", "modulename": "py_artecs.modelDb", "kind": "module", "doc": "

DEPRECATED

\n"}, {"fullname": "py_artecs.modelDb.modelDb", "modulename": "py_artecs.modelDb", "qualname": "modelDb", "kind": "class", "doc": "

DEPRECATED

\n\n

Class to handle a local version of the ARTECS DB.

\n\n

It takes in input a csv file generated from a query of ARTECS and saved in csv format.

\n\n

See the example in the introductory page.

\n\n

This module is kept for compatibility with early releases of py_artecs, but it is not maintained so its use is DEPRECATED.

\n"}, {"fullname": "py_artecs.modelDb.modelDb.__init__", "modulename": "py_artecs.modelDb", "qualname": "modelDb.__init__", "kind": "function", "doc": "

\n", "signature": "(\tproject_name,\tproject_path,\tcsv_name,\tVerbose=True,\tcsv_sep='!',\tcsv_comment='#',\tcsv_index_col='index',\tfigures_path='png',\tfilterBad=True,\tnew=False,\tquery=None)"}, {"fullname": "py_artecs.modelDb.modelDb.to_csv", "modulename": "py_artecs.modelDb", "qualname": "modelDb.to_csv", "kind": "function", "doc": "

\n", "signature": "(self, outFile, COMMENT=''):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.reset", "modulename": "py_artecs.modelDb", "qualname": "modelDb.reset", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.copy", "modulename": "py_artecs.modelDb", "qualname": "modelDb.copy", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.unique_values", "modulename": "py_artecs.modelDb", "qualname": "modelDb.unique_values", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.list_unique_values", "modulename": "py_artecs.modelDb", "qualname": "modelDb.list_unique_values", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.classification_indexes", "modulename": "py_artecs.modelDb", "qualname": "modelDb.classification_indexes", "kind": "function", "doc": "

\n", "signature": "(self, *arg, **karg):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.show_classTable", "modulename": "py_artecs.modelDb", "qualname": "modelDb.show_classTable", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.unique", "modulename": "py_artecs.modelDb", "qualname": "modelDb.unique", "kind": "function", "doc": "

\n", "signature": "(self, key):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.sort", "modulename": "py_artecs.modelDb", "qualname": "modelDb.sort", "kind": "function", "doc": "

\n", "signature": "(self, sort_by):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.sorted_query", "modulename": "py_artecs.modelDb", "qualname": "modelDb.sorted_query", "kind": "function", "doc": "

\n", "signature": "(self, sort_by, qstr):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.query", "modulename": "py_artecs.modelDb", "qualname": "modelDb.query", "kind": "function", "doc": "

\n", "signature": "(self, qstr):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.select_by_loc", "modulename": "py_artecs.modelDb", "qualname": "modelDb.select_by_loc", "kind": "function", "doc": "

\n", "signature": "(self, loc_argument):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.select_by_iloc", "modulename": "py_artecs.modelDb", "qualname": "modelDb.select_by_iloc", "kind": "function", "doc": "

\n", "signature": "(self, iloc_argument):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.classification_string2numeric", "modulename": "py_artecs.modelDb", "qualname": "modelDb.classification_string2numeric", "kind": "function", "doc": "

\n", "signature": "(self, strg):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.calc_iclass", "modulename": "py_artecs.modelDb", "qualname": "modelDb.calc_iclass", "kind": "function", "doc": "

\n", "signature": "(self, string_classification_array):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.keys", "modulename": "py_artecs.modelDb", "qualname": "modelDb.keys", "kind": "function", "doc": "

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.has_key", "modulename": "py_artecs.modelDb", "qualname": "modelDb.has_key", "kind": "function", "doc": "

\n", "signature": "(self, this):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.reset_plot_status", "modulename": "py_artecs.modelDb", "qualname": "modelDb.reset_plot_status", "kind": "function", "doc": "

resets the self._last_plot dictionary where handles from the last plot generated are stored

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.plot2", "modulename": "py_artecs.modelDb", "qualname": "modelDb.plot2", "kind": "function", "doc": "

creates a 2 axis plot, the handles for the plot objects are stored in self._last_plot

\n", "signature": "(\tself,\tx,\ty='MolecularDepth',\tylog=True,\txlog=False,\tnewfig=True,\tlegend_loc=3,\txylim=None,\tsavefig=None,\tone2one_line=False):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.set_iceTOT_threshold", "modulename": "py_artecs.modelDb", "qualname": "modelDb.set_iceTOT_threshold", "kind": "function", "doc": "

set iceTOT_threshold : the ice coverage over which the planet is considered a snowball\nsuggested values 0.95 or 0.99

\n", "signature": "(self, iceTOT_threshold):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.flag_class_warm", "modulename": "py_artecs.modelDb", "qualname": "modelDb.flag_class_warm", "kind": "function", "doc": "

returns Murante's classifications for warm calculated from scratch\niceTOT_threshold is the ice coverage over which the planet is considered a snowball\nsuggested values 0.95 or 0.99

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.flag_class_warm_hot", "modulename": "py_artecs.modelDb", "qualname": "modelDb.flag_class_warm_hot", "kind": "function", "doc": "

returns Murante's classifications for warm_hot calculated from scratch\niceTOT_threshold is the ice coverage over which the planet is considered a snowball\nsuggested values 0.95 or 0.99

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.flag_class_snowball", "modulename": "py_artecs.modelDb", "qualname": "modelDb.flag_class_snowball", "kind": "function", "doc": "

returns Murante's classifications for warm_hot calculated from scratch\niceTOT_threshold is the ice coverage over which the planet is considered a snowball\nsuggested values 0.95 or 0.99

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.modelDb.modelDb.flag_class_waterbelt", "modulename": "py_artecs.modelDb", "qualname": "modelDb.flag_class_waterbelt", "kind": "function", "doc": "

returns Murante's classifications for warm_hot calculated from scratch\niceTOT_threshold is the ice coverage over which the planet is considered a snowball\nsuggested values 0.95 or 0.99

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.tap", "modulename": "py_artecs.tap", "kind": "module", "doc": "

\n"}, {"fullname": "py_artecs.tap.EXOP_TAP", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP", "kind": "class", "doc": "

\n"}, {"fullname": "py_artecs.tap.EXOP_TAP.__init__", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP.__init__", "kind": "function", "doc": "

\n", "signature": "(\ttap_url='http://archives.ia2.inaf.it/vo/tap/exo',\ttable_name='exo.EXO',\ttemporary_files_path='/tmp')"}, {"fullname": "py_artecs.tap.EXOP_TAP.keys", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP.keys", "kind": "function", "doc": "

list of fields in the database

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.tap.EXOP_TAP.has_key", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP.has_key", "kind": "function", "doc": "

has_key

\n", "signature": "(self, this):", "funcdef": "def"}, {"fullname": "py_artecs.tap.EXOP_TAP.success", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP.success", "kind": "function", "doc": "

returns True if last search was successfull

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.tap.EXOP_TAP.clean", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP.clean", "kind": "function", "doc": "

cleans information from last search

\n", "signature": "(self):", "funcdef": "def"}, {"fullname": "py_artecs.tap.EXOP_TAP.adql_search", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP.adql_search", "kind": "function", "doc": "

search on database using ADQL string

\n", "signature": "(self, adql_string):", "funcdef": "def"}, {"fullname": "py_artecs.tap.EXOP_TAP.search_string", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP.search_string", "kind": "function", "doc": "

creates a properly formatted adql query_string

\n", "signature": "(self, SELECTION, TOP, FIELDS, WHERE, SORT):", "funcdef": "def"}, {"fullname": "py_artecs.tap.EXOP_TAP.search", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP.search", "kind": "function", "doc": "

download a table from the database\nsearch('') or search(WHERE='') returns all the data in the database

\n\n

the table can be returned as :\n pandas dataframe (default)\n astropy table (as_astropy = True)\n votable (as_votable=True)

\n", "signature": "(\tself,\tWHERE,\tSELECTION=None,\tFIELDS=None,\tTOP=None,\tSORT=None,\tas_astropy=False,\tas_votable=False):", "funcdef": "def"}, {"fullname": "py_artecs.tap.EXOP_TAP.get_map", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP.get_map", "kind": "function", "doc": "

gets a map

\n", "signature": "(self, _URL, outfile=None):", "funcdef": "def"}, {"fullname": "py_artecs.tap.EXOP_TAP.download_map", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP.download_map", "kind": "function", "doc": "

download the fits file corresponding at a given URL\nif outfile is not specified the fits file name from the URL is used\nif path is not specified the current file is stored in the current path

\n", "signature": "(self, URL, outfile=None, path=None):", "funcdef": "def"}, {"fullname": "py_artecs.tap.EXOP_TAP.EXPLAIN", "modulename": "py_artecs.tap", "qualname": "EXOP_TAP.EXPLAIN", "kind": "function", "doc": "

print a short introduction on the query language

\n", "signature": "(self):", "funcdef": "def"}]; + + // mirrored in build-search-index.js (part 1) + // Also split on html tags. this is a cheap heuristic, but good enough. + elasticlunr.tokenizer.setSeperator(/[\s\-.;&_'"=,()]+|<[^>]*>/); + + let searchIndex; + if (docs._isPrebuiltIndex) { + console.info("using precompiled search index"); + searchIndex = elasticlunr.Index.load(docs); + } else { + console.time("building search index"); + // mirrored in build-search-index.js (part 2) + searchIndex = elasticlunr(function () { + this.pipeline.remove(elasticlunr.stemmer); + this.pipeline.remove(elasticlunr.stopWordFilter); + this.addField("qualname"); + this.addField("fullname"); + this.addField("annotation"); + this.addField("default_value"); + this.addField("signature"); + this.addField("bases"); + this.addField("doc"); + this.setRef("fullname"); + }); + for (let doc of docs) { + searchIndex.addDoc(doc); + } + console.timeEnd("building search index"); + } + + return (term) => searchIndex.search(term, { + fields: { + qualname: {boost: 4}, + fullname: {boost: 2}, + annotation: {boost: 2}, + default_value: {boost: 2}, + signature: {boost: 2}, + bases: {boost: 2}, + doc: {boost: 1}, + }, + expand: true + }); +})(); \ No newline at end of file -- GitLab