예제 #1
0
def stars(page, limit):
    """
    Retrieve requested number of stars of a given page satisfying a condition
    :param page: page number
    :param limit: number of stars in this page
    :return:
    """
    try:
        # TODO: Possible SQL injection due to WHERE clause
        query = "SELECT * FROM star WHERE {} ORDER BY `hip` LIMIT %s OFFSET %s".format(
            request.args.get("query") or "1 = 1")
        db_res = MySQL.execute(DATABASE, query, [limit, page * limit])
        index_of_hip = db_res['columns'].index('hip')
        resp = {
            row[index_of_hip]: dict(
                zip(db_res['columns'],
                    [str(t) if type(t) is bytearray else t for t in row]))
            for row in db_res['rows']
        }
        return jsonify({
            'stars': resp,
            "status": {
                "message": "Fetched %s stars" % (len(resp), )
            }
        })
    except Exception as err:
        logger.exception(err)
        return jsonify({"status": {"message": "Something went wrong"}}), 500
예제 #2
0
 def update(self, connection):
     self.columns.pop(
         'created_at', None
     )  # So that original timestamp is not overwritten with current one
     update_planet_sql = MySQL.update(self.TABLE, self.columns.keys(),
                                      ['hip', 'name'], ['=', '='], ['AND'])
     return super(Planet, self).update(update_planet_sql, connection)
예제 #3
0
def composition_scatter():
    """
    Median composition of requested elements for the requested star considering common catalogs
    POST BODY:
    {
        normalization: [required] the type of solar normalization
        stars: [required] comma separated list of hips
        elements: [required] comma separated list of elements for which compositions are required
        catalogs: [optional] comma separated list of catalogs (author_year column) to exclude if provided, else all will be used
    }
    :return: {hip1: {FeH: {mdn: 0.5, avg: 0.56}, OH: {mdn: -0.07, avg: 0}, ...}, {hip2: {FeH: {mdn: 0.09, avg: 0.1}, ...}}
    """
    try:
        solarnorm = request.json['normalization']
        stars = map(lambda s: s.strip(), request.json['stars'])
        elements = map(lambda e: e.strip(), request.json['elements'])
        catalogs = map(lambda c: c.strip(), request.json.get('catalogs', []))
        query = """SELECT
                      t1.hip,
                      t1.cid,
                      t1.element,
                      t1.value
                    FROM composition t1, catalogue c, composition t2
                      WHERE t1.solarnorm = '%s' AND t2.solarnorm = '%s'
                      AND t1.cid = t2.cid
                      AND t1.element <> t2.element
                      AND t1.hip = t2.hip
                      AND t1.hip IN (%s)
                      AND t1.element IN (%s)
                      AND t2.element IN (%s)
                      AND t1.cid = c.id %s;"""
        in_str_stars = ','.join(['%s'] * len(stars))
        in_str_elems = ','.join(['%s'] * len(elements))
        in_str_cats = ','.join(['%s'] * len(catalogs))
        catalog_query = 'AND c.author_year NOT IN (%s)' % in_str_cats if len(
            catalogs) > 0 else ''
        db_res = MySQL.execute(
            DATABASE, query % (solarnorm, solarnorm, in_str_stars,
                               in_str_elems, in_str_elems, catalog_query),
            stars + elements + elements + catalogs)

        resp = {}
        for row in db_res['rows']:
            upsert_dict_arr(resp, row[0], row[2], row[3])
        for star in resp:
            for e in resp[star]:
                resp[star][e] = {
                    'mdn': median(resp[star][e]),
                    'avg': mean(resp[star][e])
                }
        return jsonify({
            'stars': resp,
            "status": {
                "message": "Fetched %s stars" % len(resp)
            }
        })
    except Exception as err:
        logger.exception(err)
        return jsonify({"status": {"message": "Something went wrong"}}), 500
 def update(self, connection):
     self.columns.pop(
         'created_at', None
     )  # So that original timestamp is not overwritten with current one
     self.columns.pop('id', None)  # ID should not be updated
     update_catalogue = MySQL.update(self.TABLE, self.columns.keys(),
                                     ['author_year'], ['='])
     return super(Catalogue, self).update(update_catalogue, connection)
예제 #5
0
 def update(self, connection):
     self.columns.pop(
         'created_at', None
     )  # So that original timestamp is not overwritten with current one
     update_composition = MySQL.update(
         self.TABLE, self.columns.keys(),
         ['solarnorm', 'hip', 'cid', 'element'], ['=', '=', '=', '='],
         ['AND', 'AND', 'AND'])
     return super(Composition, self).update(update_composition, connection)
예제 #6
0
 def find(self, connection, only_one=True):
     """
     Finds in the database for a star by HIP
     :param connection: open connection
     :param only_one: if True, only the first record returned by DB is returned, else all are returned
     :return: record(s) if found, else None
     """
     find_star = MySQL.select(self.TABLE, ['hip'], ['='])
     return super(Star, self).find(find_star, {'hip': self.columns['hip']}, connection, only_one)
 def find(self, connection, only_one=True):
     """
     Finds in the database for a catalogue by author and year
     :param connection: open connection
     :param only_one: if True, only the first record returned by DB is returned, else all are returned
     :return: record(s) if found, else None
     """
     find_catalogue = MySQL.select(self.TABLE, ['author_year'], ['='])
     return super(Catalogue, self).find(find_catalogue,
                                        {'author_year': self.columns['author_year'].strip()}, connection, only_one)
 def find(self, connection, only_one=True):
     """
     Finds in the database for a catalogue by author and year
     :param connection: open connection
     :param only_one: if True, only the first record returned by DB is returned, else all are returned
     :return: record(s) if found, else None
     """
     find_catalogue = MySQL.select(self.TABLE, ['author_year'], ['='])
     return super(Catalogue, self).find(
         find_catalogue,
         {'author_year': self.columns['author_year'].strip()}, connection,
         only_one)
예제 #9
0
def elements_of_star(hip):
    """
    Fetches the elements of a star
    :param hip: hip of the star
    :return:
    """
    try:
        query = "SELECT DISTINCT element FROM composition WHERE hip = %s"
        res = map(lambda e: e[0], MySQL.execute(DATABASE, query, [hip])['rows'])
        return jsonify({'elements': res})
    except Exception as err:
        logger.exception(err)
        return jsonify({"status": {"message": "Something went wrong"}}), 500
 def find(self, connection, only_one=True):
     """
     Finds in the database for this composition
     :param connection: open connection
     :param only_one: if True, only the first record returned by DB is returned, else all are returned
     :return: record(s) if found, else None
     """
     find_composition = MySQL.select(self.TABLE, ['solarnorm', 'hip', 'cid', 'element'],
                                     ['=', '=', '=', '='], ['AND', 'AND', 'AND'])
     return super(Composition, self).find(find_composition,
                                          {'solarnorm': self.columns['solarnorm'], 'hip': self.columns['hip'],
                                           'cid': self.columns['cid'], 'element': self.columns['element'].strip()},
                                          connection, only_one)
예제 #11
0
 def find(self, connection, only_one=True):
     """
     Finds in the database for this planet
     :param connection: open connection
     :param only_one: if True, only the first record returned by DB is returned, else all are returned
     :return: record(s) if found, else None
     """
     find_planet_sql = MySQL.select(self.TABLE, ['hip', 'name'], ['=', '='],
                                    ['AND'])
     return super(Planet, self).find(find_planet_sql, {
         'hip': self.columns['hip'],
         'name': self.columns['name']
     }, connection, only_one)
예제 #12
0
def tuples_as_dict(query, entities, key_col):
    """
    Fetches the tuples and converts to a dictionary based on the key column from the result
    :param query: query as string
    :param entities: input entities. Eg: hips
    :param key_col: index of the key column in the returned tuples
    :return: a dictionary with array of values for each key col
    """
    in_str = ','.join(['%s'] * len(entities))
    db_res = MySQL.execute(DATABASE, query % in_str, entities)
    resp = {}
    for r in db_res['rows']:
        upsert(resp, r[key_col], dict(zip(db_res['columns'], r)))
    return resp
예제 #13
0
def tuples_as_dict(query, entities, key_col):
    """
    Fetches the tuples and converts to a dictionary based on the key column from the result
    :param query: query as string
    :param entities: input entities. Eg: hips
    :param key_col: index of the key column in the returned tuples
    :return: a dictionary with array of values for each key col
    """
    in_str = ','.join(['%s'] * len(entities))
    db_res = MySQL.execute(DATABASE, query % in_str, entities)
    resp = {}
    for r in db_res['rows']:
        upsert(resp, r[key_col], dict(zip(db_res['columns'], r)))
    return resp
예제 #14
0
def elements_of_star(hip):
    """
    Fetches the elements of a star
    :param hip: hip of the star
    :return:
    """
    try:
        query = "SELECT DISTINCT element FROM composition WHERE hip = %s"
        res = map(lambda e: e[0],
                  MySQL.execute(DATABASE, query, [hip])['rows'])
        return jsonify({'elements': res})
    except Exception as err:
        logger.exception(err)
        return jsonify({"status": {"message": "Something went wrong"}}), 500
예제 #15
0
    def save(self, connection):
        """
        saves the changes to in-memory object to disk
        :param connection: open connection to DB. Assumes auto-commit is OFF
        :return: ID of the newly inserted entity
        """
        self.columns['created_at'] = datetime.datetime.today()
        self.columns['updated_at'] = self.columns['created_at']

        add_entity = MySQL.insert(self.TABLE, self.columns.keys())
        c = connection.cursor()
        c.execute(add_entity, self.columns)
        connection.commit()  # TODO: Decide if this is OK as rollbacks can be difficult
        c.close()
        return c.lastrowid
예제 #16
0
def composition_scatter():
    """
    Median composition of requested elements for the requested star considering common catalogs
    POST BODY:
    {
        normalization: [required] the type of solar normalization
        stars: [required] comma separated list of hips
        elements: [required] comma separated list of elements for which compositions are required
        catalogs: [optional] comma separated list of catalogs (author_year column) to exclude if provided, else all will be used
    }
    :return: {hip1: {FeH: {mdn: 0.5, avg: 0.56}, OH: {mdn: -0.07, avg: 0}, ...}, {hip2: {FeH: {mdn: 0.09, avg: 0.1}, ...}}
    """
    try:
        solarnorm = request.json['normalization']
        stars = map(lambda s: s.strip(), request.json['stars'])
        elements = map(lambda e: e.strip(), request.json['elements'])
        catalogs = map(lambda c: c.strip(), request.json.get('catalogs', []))
        query = """SELECT
                      t1.hip,
                      t1.cid,
                      t1.element,
                      t1.value
                    FROM composition t1, catalogue c, composition t2
                      WHERE t1.solarnorm = '%s' AND t2.solarnorm = '%s'
                      AND t1.cid = t2.cid
                      AND t1.element <> t2.element
                      AND t1.hip = t2.hip
                      AND t1.hip IN (%s)
                      AND t1.element IN (%s)
                      AND t2.element IN (%s)
                      AND t1.cid = c.id %s;"""
        in_str_stars = ','.join(['%s'] * len(stars))
        in_str_elems = ','.join(['%s'] * len(elements))
        in_str_cats = ','.join(['%s'] * len(catalogs))
        catalog_query = 'AND c.author_year NOT IN (%s)' % in_str_cats if len(catalogs) > 0 else ''
        db_res = MySQL.execute(DATABASE, query % (solarnorm, solarnorm, in_str_stars, in_str_elems, in_str_elems,
                                                  catalog_query), stars + elements + elements + catalogs)

        resp = {}
        for row in db_res['rows']:
            upsert_dict_arr(resp, row[0], row[2], row[3])
        for star in resp:
            for e in resp[star]:
                resp[star][e] = {'mdn': median(resp[star][e]), 'avg': mean(resp[star][e])}
        return jsonify({'stars': resp, "status": {"message": "Fetched %s stars" % len(resp)}})
    except Exception as err:
        logger.exception(err)
        return jsonify({"status": {"message": "Something went wrong"}}), 500
예제 #17
0
 def find(self, connection, only_one=True):
     """
     Finds in the database for this composition
     :param connection: open connection
     :param only_one: if True, only the first record returned by DB is returned, else all are returned
     :return: record(s) if found, else None
     """
     find_composition = MySQL.select(self.TABLE,
                                     ['solarnorm', 'hip', 'cid', 'element'],
                                     ['=', '=', '=', '='],
                                     ['AND', 'AND', 'AND'])
     return super(Composition, self).find(
         find_composition, {
             'solarnorm': self.columns['solarnorm'],
             'hip': self.columns['hip'],
             'cid': self.columns['cid'],
             'element': self.columns['element'].strip()
         }, connection, only_one)
예제 #18
0
def stars(page, limit):
    """
    Retrieve requested number of stars of a given page satisfying a condition
    :param page: page number
    :param limit: number of stars in this page
    :return:
    """
    try:
        # TODO: Possible SQL injection due to WHERE clause
        query = "SELECT * FROM star WHERE {} ORDER BY `hip` LIMIT %s OFFSET %s".format(
            request.args.get("query") or "1 = 1")
        db_res = MySQL.execute(DATABASE, query, [limit, page * limit])
        index_of_hip = db_res['columns'].index('hip')
        resp = {row[index_of_hip]: dict(zip(db_res['columns'], [str(t) if type(t) is bytearray else t for t in row]))
                for row in db_res['rows']}
        return jsonify({'stars': resp, "status": {"message": "Fetched %s stars" % (len(resp),)}})
    except Exception as err:
        logger.exception(err)
        return jsonify({"status": {"message": "Something went wrong"}}), 500
예제 #19
0
def compositions_of_star(hip):
    """
    Retrieves composition of a star
    If an element has multiple values from different catalogs, average value is returned
    :param hip: hip of the star
    :return: {FeH: 0.5, OH: -0.6}
    """
    try:
        elements = request.args.getlist('elements')
        in_clause = ','.join(['%s'] * len(elements))
        query = """SELECT element, AVG(value)
                    FROM composition WHERE hip = %s AND element IN ({})
                    GROUP BY element;""".format(in_clause)
        res = {}
        for k, v in MySQL.execute(DATABASE, query, [hip] + elements)['rows']:
            res[k] = v
        return jsonify(res)
    except Exception as err:
        logger.exception(err)
        return jsonify({"status": {"message": "Something went wrong"}}), 500
예제 #20
0
def compositions_of_star(hip):
    """
    Retrieves composition of a star
    If an element has multiple values from different catalogs, average value is returned
    :param hip: hip of the star
    :return: {FeH: 0.5, OH: -0.6}
    """
    try:
        elements = request.args.getlist('elements')
        in_clause = ','.join(['%s'] * len(elements))
        query = """SELECT element, AVG(value)
                    FROM composition WHERE hip = %s AND element IN ({})
                    GROUP BY element;""".format(in_clause)
        res = {}
        for k, v in MySQL.execute(DATABASE, query, [hip] + elements)['rows']:
            res[k] = v
        return jsonify(res)
    except Exception as err:
        logger.exception(err)
        return jsonify({"status": {"message": "Something went wrong"}}), 500
예제 #21
0
def upload():
    """
    Imports a file and saves to DB
    :return:
    """
    datafile = request.files['file']
    c = MySQL.get_connection(DATABASE)
    if datafile:
        try:
            logfile = os.path.splitext(datafile.filename)[0] + str(
                int(time.time())) + '.log'  # given name + current timestamp
            f = logging.FileHandler(os.path.join(LOG_DIR, logfile), 'w')
            Config.setup_logging(f)

            filepath = os.path.join(UPLOADS_DIR, datafile.filename)
            datafile.save(filepath)  # to file system
            Importer.run(filepath, c, {"normalization": request.form['normalization']})

            logger.removeHandler(f)
            f.close()
            return jsonify({"name": datafile.filename, 'log': logfile})
        finally:
            c.close()
예제 #22
0
def upload():
    """
    Imports a file and saves to DB
    :return:
    """
    datafile = request.files['file']
    c = MySQL.get_connection(DATABASE)
    if datafile:
        try:
            logfile = os.path.splitext(datafile.filename)[0] + str(
                int(time.time())) + '.log'  # given name + current timestamp
            f = logging.FileHandler(os.path.join(LOG_DIR, logfile), 'w')
            Config.setup_logging(f)

            filepath = os.path.join(UPLOADS_DIR, datafile.filename)
            datafile.save(filepath)  # to file system
            Importer.run(filepath, c,
                         {"normalization": request.form['normalization']})

            logger.removeHandler(f)
            f.close()
            return jsonify({"name": datafile.filename, 'log': logfile})
        finally:
            c.close()
예제 #23
0
def main():
    Config.setup_logging()
    c = MySQL.get_connection('astronomy_test')
    # run('./Assets/test_inp.txt', c, {"normalization": "Lodders et al. (2009)"})
    run('./Assets/exo_test_inp.txt', c,
        {"normalization": "Lodders et al. (2009)"})
def main():
    Config.setup_logging()
    c = MySQL.get_connection('astronomy_test')
    # run('./Assets/test_inp.txt', c, {"normalization": "Lodders et al. (2009)"})
    run('./Assets/exo_test_inp.txt', c, {"normalization": "Lodders et al. (2009)"})
예제 #25
0
 def update(self, connection):
     self.columns.pop('created_at', None)  # So that original timestamp is not overwritten with current one
     update_star = MySQL.update(self.TABLE, self.columns.keys(), ['hip'], ['='])
     return super(Star, self).update(update_star, connection)
예제 #26
0
def _catalogs_for_ids(ids):
    query = "SELECT id, author_year FROM catalogue WHERE id IN (%s);"
    in_str = ','.join(['%s'] * len(ids))
    db_res = MySQL.execute(DATABASE, query % in_str, ids)['rows']
    return db_res
 def update(self, connection):
     self.columns.pop('created_at', None)  # So that original timestamp is not overwritten with current one
     self.columns.pop('id', None)  # ID should not be updated
     update_catalogue = MySQL.update(self.TABLE, self.columns.keys(), ['author_year'], ['='])
     return super(Catalogue, self).update(update_catalogue, connection)
예제 #28
0
def _catalogs_for_ids(ids):
    query = "SELECT id, author_year FROM catalogue WHERE id IN (%s);"
    in_str = ','.join(['%s'] * len(ids))
    db_res = MySQL.execute(DATABASE, query % in_str, ids)['rows']
    return db_res
 def update(self, connection):
     self.columns.pop('created_at', None)  # So that original timestamp is not overwritten with current one
     update_composition = MySQL.update(self.TABLE, self.columns.keys(), ['solarnorm', 'hip', 'cid', 'element'],
                                       ['=', '=', '=', '='], ['AND', 'AND', 'AND'])
     return super(Composition, self).update(update_composition, connection)