Source code for admit.util.Tier1DB

""" .. _Tier1DB-api:

    **Tier1DB** --- Tier 1 molecular line database services.
    --------------------------------------------------------

    This module is used to interact with the Tier 1 database.
"""

import logging
import sqlite3 as sql
import os
from admit.util import LineData
from admit.util import utils

[docs]class Tier1DB(object): """ Class for interacting with the Tier 1 database. Methods are supplied to query the database and get restults of the query. See the DOCUMENTATION on the Tier 1 database for specifics. Parameters ---------- None Attributes ---------- conn : sql connection The main sql database connection. cursor : sql cursor The cursor used to interact with the database. """ def __init__(self): # open up the database self.conn = sql.connect(os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "..", "etc", "transitions.db")) # get a cursor self.cursor = self.conn.cursor() self.ishfs = False
[docs] def close(self): """ Method to cleanly close the database connection Parameters ---------- None Returns ------- None """ self.conn.close()
[docs] def add(self, string): """ Method to append to the query string, automatically adding where/and if necessary. Parameters ---------- string : str The string to add to the query Returns ------- None """ # if this is the first one the add where if self.first: self.query += " where" self.first = False # otherwise add an and else: self.query += " and" self.query += string
[docs] def searchtransitions(self, freq=[], eu=[], el=[], linestr=[], species=None): """ Method to construct the query and send it to the database. Parameters ---------- freq : list or float The frequency range to search over. If a list is given it is treated as [min,max]. If a single float is given then it is treated as a maximum allowable frequency. The units are GHz. eu : list or float The upper energy range to search over. If a list is given it is treated as [min,max]. If a single float is given then it is treated as a maximum allowable upper state energy. el : list or float The lower energy range to search over. If a list is given it is treated as [min,max]. If a single float is given then it is treated as a maximum allowable lower state energy. linestr : list or float The line strength range to search over. If a list is given it is treated as [min,max]. If a single float is given then it is treated as a maximum allowable line strength. species : str The species to restrict the search to. It is executed as an sql "like" statement, and thus an exact match is not required. """ # set up the query self.ishfs = False self.first = True self.query = "select SPECIES, NAME, FREQUENCY, QUANTUM_NUMBERS, LINE_STR, LOWER_ENERGY, UPPER_ENERGY, HFS from Transitions" # add any frequency restrictions if isinstance(freq, list): if len(freq) == 2: self.add(" FREQUENCY between %f and %f" % (min(freq[0], freq[1]), max(freq[0], freq[1]))) elif len(freq) == 1: self.add(" FREQUENCY <= %f" % (freq[0])) elif len(freq) == 0: pass else: raise Exception("Invalid number of freq components given, bust be 0, 1, or 2") elif isinstance(freq, float) or isinstance(freq, int): self.add(" FREQUENCY <= %f" % (float(freq))) else: raise Exception("Invalid data type given for freq, must be a list or float") # add any upper energy restrictions if isinstance(eu, list): if len(eu) == 2: self.add(" UPPER_ENERGY between %f and %f" % (min(eu[0], eu[1]), max(eu[0], eu[1]))) elif len(eu) == 1: self.add(" UPPER_ENERGY <= %f" % (eu[0])) elif len(eu) == 0: pass else: raise Exception("Invalid number of eu components given, bust be 0, 1, or 2") elif isinstance(eu, float) or isinstance(eu, int): self.add(" UPPER_ENERGY <= %f" % (float(eu))) else: raise Exception("Invalid data type given for eu, must be a list or float") # add any lower energy restrictions if isinstance(el, list): if len(el) == 2: self.add(" LOWER_ENERGY between %f and %f" % (min(el[0], el[1]), max(el[0], el[1]))) elif len(el) == 1: self.add(" LOWER_ENERGY <= %f" % (el[0])) elif len(el) == 0: pass else: raise Exception("Invalid number of el components given, bust be 0, 1, or 2") elif isinstance(el, float) or isinstance(el, int): self.add(" LOWER_ENERGY <= %f" % (float(el))) else: raise Exception("Invalid data type given for el, must be a list or float") # add and line strength restrictions if isinstance(linestr, list): if len(linestr) == 2: self.add(" LINE_STR between %f and %f" % (min(linestr[0], linestr[1]), max(linestr[0], linestr[1]))) elif len(linestr) == 1: self.add(" LINE_STR <= %f" % (linestr[0])) elif len(linestr) == 0: pass else: raise Exception("Invalid number of linestr components given, bust be 0, 1, or 2") elif isinstance(linestr, float) or isinstance(linestr, int): self.add(" LINE_STR <= %f" % (float(linestr))) else: raise Exception("Invalid data type given for linestr, must be a list or float") # add any species restrictions if species: self.add(" SPECIES like '%%%s%%'" % (species)) self.cursor.execute(self.query)
[docs] def searchhfs(self, hfsid): """ Method to search the HFS table for the requested transitions Parameters ---------- hfsid : int The id of the HFS line to get Returns ------- None """ self.ishfs = True self.cursor.execute("select FREQUENCY, QUANTUM_NUMBERS, LINE_STR, LOWER_ENERGY, UPPER_ENERGY from HFS where TRANSITION=%i" % (hfsid))
[docs] def getall(self): """ Method to get all results from the query Parameters ---------- None Returns ------- List of LineData objects, one for each transition """ results = self.cursor.fetchall() output = [] if self.ishfs: for res in results: output.append(LineData(frequency=res[0], transition=str(res[1]), linestrength=res[2], energies=[res[3], res[4]])) else: for res in results: formula = str(res[0]) output.append(LineData(formula=formula, name=str(res[1]), frequency=res[2], uid=utils.getplain(formula) + "_%.5f" % res[2], energies=[res[5], res[6]], linestrength=res[4], mass=utils.getmass(formula), transition=str(res[3]), plain=utils.getplain(formula), isocount=utils.isotopecount(formula), hfnum=res[7])) return output
[docs] def getone(self): """ Method to get the next result from the query Parameters ---------- None Returns ------- LineData object containing the transition data """ res = self.cursor.fetchone() if self.ishfs: return LineData(frequency=res[0], transition=res[1], linestrength=res[2], energies=[res[3], res[4]]) formula = str(res[0]) return LineData(formula=formula, name=str(res[1]), frequency=res[2], uid=utils.getplain(formula) + "_%.5f" % res[2], energies=[res[5], res[6]], linestrength=res[4], mass=utils.getmass(formula), transition=str(res[3]), plain=utils.getplain(formula), isocount=utils.isotopecount(formula), hfnum=res[7])
[docs] def get(self, num): """ Method to get many results from the query Parameters ---------- num : int The number of results to get Returns ------- A tuple containing the requested results as a list """ return self.cursor.fetchmany(num)
[docs] def query(self, querystring): """ Method to execute the requested query against the transitions database Parameters ---------- query : str The query to perform, no error checking is done Returns ------- None """ self.cursor.execute(querystring)