Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement credentials #3

Merged
merged 4 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/source/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ Lists
Lists are accepted only by the :python:`calibrator`, :python:`converter`, and :python:`generator`. These lists have to correspond to a list of source IDs. Both lists of strings and lists of long are accepted.

When a list is passed to one of the tools, the function will internally request the required data for the given sources from the Gaia Archive (currently geapre), ask for
credentials (username and password), execute the function, and return the results.
Cosmos credentials (username and password), execute the function, and return the results.

ADQL queries
------------
ADQL queries are accepted only by the :python:`calibrator`, :python:`converter`, and :python:`generator`. Queries need to be passed as strings (e.g.: :python:`"select TOP 100 source_id from user_dr3int6.gaia_source where has_xp_continuous = 'True'"`).

Queries are sent to the Gaia Archive (geapre), and executed after requesting credentials (username and password).
Queries are sent to the Gaia Archive (geapre), and executed after requesting Cosmos credentials (username and password).

DataFrames
----------
Expand Down
16 changes: 12 additions & 4 deletions gaiaxpy/calibrator/calibrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ def calibrate(
output_path='.',
output_file='output_spectra',
output_format=None,
save_file=True):
save_file=True,
username=None,
password=None):
"""
Calibration utility: calibrates the input internally-calibrated
continuously-represented mean spectra to the absolute system. An absolute
Expand All @@ -55,6 +57,8 @@ def calibrate(
input file.
save_file (bool): Whether to save the output in a file. If false, output_format
and output_file are ignored.
username (str): Cosmos username.
password (str): Cosmos password.

Returns:
(tuple): tuple containing:
Expand All @@ -70,7 +74,9 @@ def calibrate(
output_path,
output_file,
output_format,
save_file)
save_file,
username=username,
password=password)


def _calibrate(
Expand All @@ -82,7 +88,9 @@ def _calibrate(
output_format=None,
save_file=True,
bp_model='v375wi',
rp_model='v142r'):
rp_model='v142r',
username=None,
password=None):
"""
Internal method of the calibration utility. Refer to "calibrate".

Expand All @@ -99,7 +107,7 @@ def _calibrate(
"""
_validate_wl_sampling(sampling)
_validate_arguments(_calibrate.__defaults__[3], output_file, save_file)
parsed_input_data, extension = InputReader(input_object, _calibrate)._read()
parsed_input_data, extension = InputReader(input_object, _calibrate, username, password)._read()
label = 'calibrator'

xp_design_matrices, xp_merge = _generate_xp_matrices_and_merge(label, sampling, bp_model, rp_model)
Expand Down
8 changes: 6 additions & 2 deletions gaiaxpy/converter/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ def convert(
output_path='.',
output_file='output_spectra',
output_format=None,
save_file=True):
save_file=True,
username=None,
password=None):
"""
Conversion utility: converts the input internally calibrated mean
spectra from the continuous representation to a sampled form. The
Expand All @@ -60,6 +62,8 @@ def convert(
input file.
save_file (bool): Whether to save the output in a file. If false, output_format
and output_file are ignored.
username (str): Cosmos username.
password (str): Cosmos password.

Returns:
(tuple): tuple containing:
Expand All @@ -72,7 +76,7 @@ def convert(
# Check sampling
_validate_pwl_sampling(sampling)
_validate_arguments(convert.__defaults__[3], output_file, save_file)
parsed_input_data, extension = InputReader(input_object, convert)._read()
parsed_input_data, extension = InputReader(input_object, convert, username, password)._read()
config_df = load_config(config_file)
# Union of unique ids as sets
unique_bases_ids = get_unique_basis_ids(parsed_input_data)
Expand Down
2 changes: 1 addition & 1 deletion gaiaxpy/file_parser/parse_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def parse(self, file_path):

Returns:
DataFrame: Pandas DataFrame representing the file.
str: File extension ('.avro', '.csv', '.fits', or '.xml').
str: File extension ('.csv', '.fits', or '.xml').
"""
extension = _get_file_extension(file_path)
parser = self.get_parser(extension)
Expand Down
8 changes: 6 additions & 2 deletions gaiaxpy/generator/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ def generate(
output_file='output_synthetic_photometry',
output_format=None,
save_file=True,
error_correction=False):
error_correction=False,
username=None,
password=None):
"""
Synthetic photometry utility: generates synthetic photometry in a set of
available systems from the input internally-calibrated
Expand All @@ -39,6 +41,8 @@ def generate(
error_correction (bool): Whether to apply to the photometric errors the tabulated
factors to mitigate underestimated errors (see Montegriffo et al., 2022, for
more details).
username (str): Cosmos username.
password (str): Cosmos password.

Returns:
DataFrame: A DataFrame of all synthetic photometry results.
Expand All @@ -56,7 +60,7 @@ def generate(
else:
raise ValueError('Parameter photometric_system must be either a PhotometricSystem or a list.')
# Load data
parsed_input_data, extension = InputReader(input_object, generate)._read()
parsed_input_data, extension = InputReader(input_object, generate, username, password)._read()
gaia_system = PhotometricSystem.Gaia_DR3_Vega
# Create multi generator
gaia_initially_in_systems = bool(gaia_system in int_photometric_system)
Expand Down
16 changes: 16 additions & 0 deletions gaiaxpy/input_reader/archive_reader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from astroquery.gaia import GaiaClass

class ArchiveReader(object):

def __init__(self, function, user, password):
self.function = function
self.user = user
self.password = password

def _login(self, gaia):
user = self.user
password = self.password
if user and password:
gaia.login(user=user, password=password)
else:
gaia.login()
10 changes: 7 additions & 3 deletions gaiaxpy/input_reader/dataframe_reader.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from numpy import ndarray
from pandas import isnull
from .dataframe_numpy_array_reader import DataFrameNumPyArrayReader
from .dataframe_string_array_reader import DataFrameStringArrayReader
# TODO: move this function to core as it's now used by more than one subpackage
from gaiaxpy.core import array_to_symmetric_matrix

matrix_columns = [('bp_n_parameters', 'bp_coefficient_correlations'),
Expand Down Expand Up @@ -48,6 +48,10 @@ def _read_df(self):
if needs_matrix_conversion(array_columns):
for index, row in data.iterrows():
for size_column, values_column in matrix_columns:
data[values_column][index] = array_to_symmetric_matrix(
data[size_column][index].astype(int), row[values_column])
try:
data[values_column][index] = array_to_symmetric_matrix(
data[size_column][index].astype(int), row[values_column])
except AttributeError as err:
if isnull(data[size_column][index]):
continue
return data, None # No extension for dataframes
10 changes: 8 additions & 2 deletions gaiaxpy/input_reader/dataframe_string_array_reader.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numpy as np
import pandas as pd
from math import isnan

# Avoid warning, false positive
pd.options.mode.chained_assignment = None
Expand All @@ -17,8 +18,13 @@ def _parse_parenthesis_arrays(self):
for column in array_columns:
# String column to NumPy array
for index, row in df.iterrows():
df[column][index] = np.fromstring(
row[column][1:-1], sep=',')
current_element = row[column]
try:
df[column][index] = np.fromstring(
current_element[1:-1], sep=',')
except TypeError:
if isinstance(current_element, float) and isnan(current_element):
continue
return df

def _parse_brackets_arrays(self):
Expand Down
13 changes: 10 additions & 3 deletions gaiaxpy/input_reader/input_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,48 @@
from .list_reader import ListReader
from .query_reader import QueryReader


default_extension = 'csv'


class InputReader(object):

def __init__(self, content, function):
def __init__(self, content, function, user=None, password=None):
self.content = content
self.function = function
self.user = user
self.password = password

def _string_reader(self):
content = self.content
function = self.function
user = self.user
password = self.password
# Check whether content is path
if path.isfile(content) or path.isabs(content):
selector = FileReader(function)
parser = selector._select() # Select type of parser required
parsed_input_data, extension = parser.parse(content)
# Query should start with select
elif content.lower().startswith('select'):
parsed_input_data, extension = QueryReader(content, function)._read()
parsed_input_data, extension = QueryReader(content, function, user, password)._read()
else:
raise ValueError('Input string does not correspond to an existing file and it is not an ADQL query.')
return parsed_input_data, extension

def _read(self):
content = self.content
function = self.function
user = self.user
password = self.password
# DataFrame reader
if isinstance(content, pd.DataFrame):
# Call Dataframe reader
parsed_data, extension = DataFrameReader(content)._read_df()
# List reader for query
elif isinstance(content, list):
# Construct query from list
parsed_data, extension = ListReader(content, function)._read()
parsed_data, extension = ListReader(content, function, user, password)._read()
# String can be either query or file path
elif isinstance(content, str):
parsed_data, extension = self._string_reader()
Expand Down
9 changes: 5 additions & 4 deletions gaiaxpy/input_reader/list_reader.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from astroquery.gaia import GaiaClass
from .dataframe_reader import DataFrameReader
from .archive_reader import ArchiveReader

not_supported_functions = ['apply_colour_equation']

Expand All @@ -13,14 +14,14 @@ def extremes_are_enclosing(first_row, column):
return False


class ListReader(object):
class ListReader(ArchiveReader):

def __init__(self, content, function):
def __init__(self, content, function, user, password):
super(ListReader, self).__init__(function, user, password)
if content != []:
self.content = content
else:
raise ValueError('Input list cannot be empty.')
self.function = function

def _read(self):
sources = self.content
Expand All @@ -29,7 +30,7 @@ def _read(self):
raise ValueError(f'Function {function_name} does not support receiving a list as input.')
# Connect to geapre
gaia = GaiaClass(gaia_tap_server='https://geapre.esac.esa.int/', gaia_data_server='https://geapre.esac.esa.int/')
gaia.login()
self._login(gaia)
# ADQL query
result = gaia.load_data(ids=sources, format='csv', data_release='Gaia DR3_INT6', data_structure='raw',
retrieval_type='XP_CONTINUOUS', avoid_datatype_check=True)
Expand Down
9 changes: 5 additions & 4 deletions gaiaxpy/input_reader/query_reader.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from astroquery.gaia import GaiaClass
from .dataframe_reader import DataFrameReader
from .archive_reader import ArchiveReader

not_supported_functions = ['apply_colour_equation']


class QueryReader(object):
class QueryReader(ArchiveReader):

def __init__(self, content, function):
def __init__(self, content, function, user=None, password=None):
self.content = content
self.function = function
super(QueryReader, self).__init__(function, user, password)

def _read(self, data_release='Gaia DR3_INT6'):
query = self.content
Expand All @@ -17,7 +18,7 @@ def _read(self, data_release='Gaia DR3_INT6'):
raise ValueError(f'Function {function_name} does not support receiving a query as input.')
# Connect to geapre
gaia = GaiaClass(gaia_tap_server='https://geapre.esac.esa.int/', gaia_data_server='https://geapre.esac.esa.int/')
gaia.login()
self._login(gaia)
# ADQL query
job = gaia.launch_job_async(query, dump_to_file=False)
ids = job.get_results()
Expand Down