Module pyaurorax.search
Interact with the AuroraX search engine. This includes finding data sources, searching for conjunctions or ephemeris data, and uploading/managing your own data in the AuroraX platform.
Sub-modules
pyaurorax.search.api
-
Interface for AuroraX API requests. Primarily an under-the-hood module not needed for most use-cases.
pyaurorax.search.availability
-
Retrieve availability information about data in the AuroraX search engine.
pyaurorax.search.conjunctions
-
Use the AuroraX search engine to find conjunctions between groupings of data sources …
pyaurorax.search.data_products
-
Use the AuroraX search engine to search and upload data product records …
pyaurorax.search.ephemeris
-
Use the AuroraX search engine to search and upload ephemeris records …
pyaurorax.search.location
-
Class definition for AuroraX search engine location data
pyaurorax.search.metadata
-
Interacting with the data source metadata schemas …
pyaurorax.search.metadata_filters
-
Class definition for a metadata filter objects
pyaurorax.search.requests
-
Helper methods for retrieving data from an AuroraX search engine API request …
pyaurorax.search.sources
-
Manage AuroraX data sources utilized by the search engine.
pyaurorax.search.util
-
Utility methods. For example, converting arbitrary geographic locations to North/South B-trace geographic locations.
Classes
class AvailabilityResult (data_source: DataSource,
available_data_products: Dict | None = None,
available_ephemeris: Dict | None = None)-
Expand source code
@dataclass class AvailabilityResult: """ Class definition for data availability information Attributes: data_source (pyaurorax.search.DataSource): The data source that the records are associated with available_ephemeris (Dict): The ephemeris availability information available_data_products (Dict): The data product availability information """ data_source: DataSource available_data_products: Optional[Dict] = None available_ephemeris: Optional[Dict] = None
Class definition for data availability information
Attributes
data_source
:DataSource
- The data source that the records are associated with
available_ephemeris
:Dict
- The ephemeris availability information
available_data_products
:Dict
- The data product availability information
Class variables
var available_data_products : Dict | None
var available_ephemeris : Dict | None
var data_source : DataSource
class Conjunction (conjunction_type: str,
start: datetime.datetime,
end: datetime.datetime,
data_sources: List[DataSource],
min_distance: float,
max_distance: float,
events: List[Dict],
closest_epoch: datetime.datetime,
farthest_epoch: datetime.datetime)-
Expand source code
class Conjunction: """ Conjunction object Attributes: conjunction_type (str): The type of location data used when the conjunction was found (either `nbtrace`, `sbtrace`, or `geographic`) start (datetime.datetime): Start timestamp of the conjunction end (datetime.datetime): End timestamp of the conjunction data_sources (List[DataSource]): Data sources in the conjunction min_distance (float): Minimum kilometer distance of the conjunction max_distance (float): Maximum kilometer distance of the conjunction events (List[Dict]): The sub-conjunctions that make up this over-arching conjunction (the conjunctions between each set of two data sources) closest_epoch (datetime.datetime): Timestamp for when data sources were closest farthest_epoch (datetime.datetime): Timestamp for when data sources were farthest """ def __init__( self, conjunction_type: str, start: datetime.datetime, end: datetime.datetime, data_sources: List[DataSource], min_distance: float, max_distance: float, events: List[Dict], closest_epoch: datetime.datetime, farthest_epoch: datetime.datetime, ): self.conjunction_type = conjunction_type self.start = start self.end = end self.data_sources = data_sources self.min_distance = min_distance self.max_distance = max_distance self.events = events self.closest_epoch = closest_epoch self.farthest_epoch = farthest_epoch def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: return f"Conjunction(start={repr(self.start)}, end={repr(self.end)}, min_distance={self.min_distance:.2f}, " \ f"max_distance={self.max_distance:.2f}, data_sources=[...], events=[...])"
Conjunction object
Attributes
conjunction_type
:str
- The type of location data used when the conjunction was found (either
nbtrace
,sbtrace
, orgeographic
) start
:datetime.datetime
- Start timestamp of the conjunction
end
:datetime.datetime
- End timestamp of the conjunction
data_sources
:List[DataSource]
- Data sources in the conjunction
min_distance
:float
- Minimum kilometer distance of the conjunction
max_distance
:float
- Maximum kilometer distance of the conjunction
events
:List[Dict]
- The sub-conjunctions that make up this over-arching conjunction (the conjunctions between each set of two data sources)
closest_epoch
:datetime.datetime
- Timestamp for when data sources were closest
farthest_epoch
:datetime.datetime
- Timestamp for when data sources were farthest
class ConjunctionSearch (aurorax_obj: PyAuroraX,
start: datetime.datetime,
end: datetime.datetime,
distance: Union[int, float, Dict],
ground: Sequence[Union[GroundCriteriaBlock, Dict]] = [],
space: Sequence[Union[SpaceCriteriaBlock, Dict]] = [],
events: Sequence[Union[EventsCriteriaBlock, Dict]] = [],
custom_locations: Sequence[Union[CustomLocationsCriteriaBlock, Dict]] = [],
conjunction_types: "Sequence[Union[str, Literal['nbtrace', 'sbtrace', 'geographic']]]" = ['nbtrace'],
response_format: Optional[Dict] = None)-
Expand source code
class ConjunctionSearch: """ Class representing a conjunction search Attributes: start (datetime.datetime): Start timestamp of the search (inclusive). end (datetime.datetime): End timestamp of the search (inclusive). distance (int or float or Dict): The maximum distance allowed between data sources when searching for conjunctions. This can either be a number (int or float), or a dictionary modified from the output of the "get_advanced_distances_combos()" function. ground (List[GroundCriteriaBlock or Dict]): List of ground instrument criteria blocks, defaults to []. space (List[SpaceCriteriaBlock or Dict]): List of space instrument criteria blocks, defaults to []. events (List[EventsCriteriaBlock or Dict]): List of event criteria blocks, defaults to []. custom_locations (List[CustomLocationsCriteriaBlock or Dict]): List of custom location criteria blocks, defaults to []. conjunction_types (List[str]): List of conjunction types, defaults to [] (meaning all conjunction types). Valid options are 'nbtrace', 'sbtrace', and 'geographic'. Defaults to 'nbtrace'. response_format (Dict): JSON representation of desired data response format request (AuroraXResponse): AuroraXResponse object returned when the search is executed request_id (str): Unique ID assigned to the request by the AuroraX API request_url (str): Unique URL assigned to the request by the AuroraX API executed (bool): Indicates if the search has been executed/started completed (bool): Indicates if the search has finished data_url (str): The URL where data is accessed query (Dict): The query for this request as JSON status (Dict): The status of the query data (List[Conjunction]): The conjunctions found logs (List[Dict]): All log messages outputted by the AuroraX API for this request """ __STANDARD_POLLING_SLEEP_TIME: float = 1.0 def __init__(self, aurorax_obj: PyAuroraX, start: datetime.datetime, end: datetime.datetime, distance: Union[int, float, Dict], ground: Sequence[Union[GroundCriteriaBlock, Dict]] = [], space: Sequence[Union[SpaceCriteriaBlock, Dict]] = [], events: Sequence[Union[EventsCriteriaBlock, Dict]] = [], custom_locations: Sequence[Union[CustomLocationsCriteriaBlock, Dict]] = [], conjunction_types: Sequence[Union[str, Literal["nbtrace", "sbtrace", "geographic"]]] = ["nbtrace"], response_format: Optional[Dict] = None): # set variables using passed in args self.__aurorax_obj = aurorax_obj self.start = start self.end = end self.ground = ground self.space = space self.events = events self.custom_locations = custom_locations self.distance = distance self.conjunction_types = conjunction_types self.response_format = response_format # initialize additional variables self.request = None self.request_id = "" self.request_url = "" self.executed = False self.completed = False self.data_url = "" self.__query = {} self.status = {} self.data = [] self.logs = [] def __str__(self): return self.__repr__() def __repr__(self): return "ConjunctionSearch(executed=%s, completed=%s, request_id='%s')" % ( self.executed, self.completed, self.request_id, ) def pretty_print(self): """ A special print output for this class. """ # set status and query strings max_len = 80 status_str = str(self.status) query_str = str(self.query) if (len(status_str) > max_len): status_str = "%s..." % (status_str[0:max_len]) if (len(query_str) > max_len): query_str = "%s..." % (query_str[0:max_len]) # set results string if (self.executed is True): if (len(self.data) == 0): data_str = "[0 conjunction results]" elif (len(self.data) == 1): data_str = "[1 conjunction result]" else: data_str = "[%d conjunction results]" % (len(self.data)) else: data_str = "" # set logs string if (self.executed is True): if (len(self.logs) == 0): logs_str = "[0 log messages]" elif (len(self.logs) == 1): logs_str = "[1 log message]" else: logs_str = "[%d log messages]" % (len(self.logs)) else: logs_str = "" # print print("ConjunctionSearch:") print(" %-13s: %s" % ("executed", self.executed)) print(" %-13s: %s" % ("completed", self.completed)) print(" %-13s: %s" % ("request_id", self.request_id)) print(" %-13s: %s" % ("request", self.request)) print(" %-13s: %s" % ("request_url", self.request_url)) print(" %-13s: %s" % ("data_url", self.data_url)) print(" %-13s: %s" % ("query", query_str)) print(" %-13s: %s" % ("status", status_str)) print(" %-13s: %s" % ("data", data_str)) print(" %-13s: %s" % ("logs", logs_str)) def __fill_in_missing_distances(self, curr_distances: Dict) -> Dict: # get all distances possible all_distances = self.get_advanced_distances_combos() # go through current distances and fill in the values for curr_key, curr_value in curr_distances.items(): curr_key_split = curr_key.split('-') curr_key1 = curr_key_split[0].strip() curr_key2 = curr_key_split[1].strip() for all_key in all_distances.keys(): if (curr_key1 in all_key and curr_key2 in all_key): # found the matching key, replace the value all_distances[all_key] = curr_value # return return all_distances def check_criteria_block_count_validity(self) -> None: """ Check the number of of criteria blocks to see if there is too many. A max of 10 is allowed by the AuroraX conjunction search engine. An exception is raised if it was determined to have too many. Raises: pyaurorax.exceptions.AuroraXError: Too many criteria blocks are found """ count_ground = 0 count_space = 0 count_events = 0 count_custom_locations = 0 if (self.ground is not None): count_ground = len(self.ground) if (self.space is not None): count_space = len(self.space) if (self.events is not None): count_events = len(self.events) if (self.custom_locations is not None): count_custom_locations = len(self.custom_locations) if ((count_ground + count_space + count_events + count_custom_locations) > 10): raise AuroraXError("Number of criteria blocks exceeds 10, please reduce the count") def get_advanced_distances_combos(self, default_distance: Optional[Union[int, float]] = None) -> Dict: """ Get the advanced distances combinations for this search Args: default_distance (int): The default distance to use, defaults to None Returns: The advanced distances combinations """ # set input arrays options = [] if (self.ground is not None): for i in range(0, len(self.ground)): options.append("ground%d" % (i + 1)) if (self.space is not None): for i in range(0, len(self.space)): options.append("space%d" % (i + 1)) if (self.events is not None): for i in range(0, len(self.events)): options.append("events%d" % (i + 1)) if (self.custom_locations is not None): for i in range(0, len(self.custom_locations)): options.append("adhoc%d" % (i + 1)) # derive all combinations of options of size 2 combinations = {} for element in itertools.combinations(options, r=2): combinations["%s-%s" % (element[0], element[1])] = default_distance # return return combinations @property def distance(self) -> Union[int, float, Dict[str, Union[int, float]]]: """ Property for the distance parameter Returns: The distance dictionary with all combinations """ return self.__distance @distance.setter def distance(self, distance: Union[int, float, Dict[str, Union[int, float]]]) -> None: # set distances to a dict if it's an int or float if (isinstance(distance, int) or isinstance(distance, float)): self.__distance = self.get_advanced_distances_combos(default_distance=distance) # type: ignore else: # is a dict, fill in any gaps self.__distance = self.__fill_in_missing_distances(distance) # type: ignore @property def query(self) -> Dict: """ Property for the query value Returns: The query parameter """ # set ground ground_param = self.ground if (isinstance(self.ground, list) and all(isinstance(item, GroundCriteriaBlock) for item in self.ground)): # ground parameter is a list of GroundCriteriaBlock objects, so we # want to set the query to the dict version of it ground_param = [] for val in self.ground: this_dict = deepcopy(val.__dict__) this_dict["ephemeris_metadata_filters"] = this_dict["metadata_filters"] del this_dict["metadata_filters"] if (this_dict["ephemeris_metadata_filters"] is not None): this_dict["ephemeris_metadata_filters"] = this_dict["ephemeris_metadata_filters"].to_query_dict() ground_param.append(this_dict) # set space space_param = self.space if (isinstance(self.space, list) and all(isinstance(item, SpaceCriteriaBlock) for item in self.space)): # space parameter is a list of SpaceCriteriaBlock objects, so we # want to set the query to the dict version of it space_param = [] for val in self.space: this_dict = deepcopy(val.__dict__) this_dict["ephemeris_metadata_filters"] = this_dict["metadata_filters"] del this_dict["metadata_filters"] if (this_dict["ephemeris_metadata_filters"] is not None): this_dict["ephemeris_metadata_filters"] = this_dict["ephemeris_metadata_filters"].to_query_dict() space_param.append(this_dict) # set events events_param = self.events if (isinstance(self.events, list) and all(isinstance(item, EventsCriteriaBlock) for item in self.events)): # space parameter is a list of EventsCriteriaBlock objects, so we # want to set the query to the dict version of it events_param = [] for val in self.events: this_dict = deepcopy(val.__dict__) this_dict["ephemeris_metadata_filters"] = this_dict["metadata_filters"] this_dict["programs"] = ["events"] del this_dict["metadata_filters"] if (this_dict["ephemeris_metadata_filters"] is not None): this_dict["ephemeris_metadata_filters"] = this_dict["ephemeris_metadata_filters"].to_query_dict() events_param.append(this_dict) # set custom locations custom_param = self.custom_locations if (isinstance(self.custom_locations, list) and all(isinstance(item, CustomLocationsCriteriaBlock) for item in self.custom_locations)): # space parameter is a list of CustomLocationsCriteriaBlock objects, so we # want to set the query to the dict version of it custom_param = [] for val in self.custom_locations: this_dict = val.to_search_query_dict() # type: ignore custom_param.append(this_dict) # set query self.__query = { "start": self.start.strftime("%Y-%m-%dT%H:%M:%S"), "end": self.end.strftime("%Y-%m-%dT%H:%M:%S"), "ground": ground_param, "space": space_param, "events": events_param, "adhoc": custom_param, "conjunction_types": self.conjunction_types, "max_distances": self.distance, "epoch_search_precision": 60, } return self.__query @query.setter def query(self, query: Dict) -> None: self.__query = query def execute(self) -> None: """ Initiate a conjunction search request Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ # check number of criteria blocks self.check_criteria_block_count_validity() # do request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_CONJUNCTION_SEARCH) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query, null_response=True) res = req.execute() # set request ID, request_url, executed self.executed = True if res.status_code == 202: # request successfully dispatched self.executed = True self.request_url = res.request.headers["location"] self.request_id = self.request_url.rsplit("/", 1)[-1] # set request variable self.request = res def update_status(self, status: Optional[Dict] = None) -> None: """ Update the status of this conjunction search request Args: status (Dict): The previously-retrieved status of this request (include to avoid requesting it from the API again), defaults to None Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ # get the status if it isn't passed in if (status is None): status = requests_get_status(self.__aurorax_obj, self.request_url) # check response if (status is None): raise AuroraXAPIError("Could not retrieve status for this request") # update request status by checking if data URI is set if (status["search_result"]["data_uri"] is not None): self.completed = True self.data_url = "%s/data" % (self.request_url) # set class variable "status" and "logs" self.status = status self.logs = status["logs"] def check_for_data(self) -> bool: """ Check to see if data is available for this conjunction search request Returns: True if data is available, else False Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ self.update_status() return self.completed def get_data(self) -> None: """ Retrieve the data available for this conjunction search request Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ # check if completed yet if (self.completed is False): print("No data available, update status or check for data first") return # get data raw_data = requests_get_data(self.__aurorax_obj, self.data_url, self.response_format, False) # set data variable if (self.response_format is not None): self.data = raw_data else: # cast data source objects for i in range(0, len(raw_data)): for j in range(0, len(raw_data[i]["data_sources"])): ds = DataSource(**raw_data[i]["data_sources"][j], format=FORMAT_BASIC_INFO) raw_data[i]["data_sources"][j] = ds # cast conjunctions self.data = [Conjunction(**c) for c in raw_data] def wait(self, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> None: """ Block and wait until the request is complete and data is available for retrieval Args: poll_interval (float): Time in seconds to wait between polling attempts, defaults to 1 second verbose (bool): Output poll times and other progress messages, defaults to False Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_CONJUNCTION_REQUEST.format(self.request_id)) self.update_status(requests_wait_for_data(self.__aurorax_obj, url, poll_interval, verbose)) def cancel(self, wait: bool = False, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> int: """ Cancel the conjunction search request This method returns immediately by default since the API processes this request asynchronously. If you would prefer to wait for it to be completed, set the 'wait' parameter to True. You can adjust the polling time using the 'poll_interval' parameter. Args: wait (bool): Wait until the cancellation request has been completed (may wait for several minutes) poll_interval (float): Seconds to wait between polling calls, defaults to STANDARD_POLLING_SLEEP_TIME. verbose (bool): Output poll times and other progress messages, defaults to False Returns: 1 on success Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_CONJUNCTION_REQUEST.format(self.request_id)) return requests_cancel(self.__aurorax_obj, url, wait, poll_interval, verbose) def describe(self): """ Describe the conjunction search as an "SQL-like" string. Returns: The "SQL-like" string describing the conjunction search object """ # make request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DESCRIBE_CONJUNCTION_QUERY) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query) res = req.execute() # return return res.data
Class representing a conjunction search
Attributes
start
:datetime.datetime
- Start timestamp of the search (inclusive).
end
:datetime.datetime
- End timestamp of the search (inclusive).
distance
:int
orfloat
orDict
- The maximum distance allowed between data sources when searching for conjunctions. This can either be a number (int or float), or a dictionary modified from the output of the "get_advanced_distances_combos()" function.
ground
:List[GroundCriteriaBlock
orDict]
- List of ground instrument criteria blocks, defaults to [].
space
:List[SpaceCriteriaBlock
orDict]
- List of space instrument criteria blocks, defaults to [].
events
:List[EventsCriteriaBlock
orDict]
- List of event criteria blocks, defaults to [].
custom_locations
:List[CustomLocationsCriteriaBlock
orDict]
- List of custom location criteria blocks, defaults to [].
conjunction_types
:List[str]
- List of conjunction types, defaults to [] (meaning all conjunction types). Valid options are 'nbtrace', 'sbtrace', and 'geographic'. Defaults to 'nbtrace'.
response_format
:Dict
- JSON representation of desired data response format
request
:AuroraXResponse
- AuroraXResponse object returned when the search is executed
request_id
:str
- Unique ID assigned to the request by the AuroraX API
request_url
:str
- Unique URL assigned to the request by the AuroraX API
executed
:bool
- Indicates if the search has been executed/started
completed
:bool
- Indicates if the search has finished
data_url
:str
- The URL where data is accessed
query
:Dict
- The query for this request as JSON
status
:Dict
- The status of the query
data
:List[Conjunction]
- The conjunctions found
logs
:List[Dict]
- All log messages outputted by the AuroraX API for this request
Instance variables
prop distance : Union[int, float, Dict[str, Union[int, float]]]
-
Expand source code
@property def distance(self) -> Union[int, float, Dict[str, Union[int, float]]]: """ Property for the distance parameter Returns: The distance dictionary with all combinations """ return self.__distance
Property for the distance parameter
Returns
The distance dictionary with all combinations
prop query : Dict
-
Expand source code
@property def query(self) -> Dict: """ Property for the query value Returns: The query parameter """ # set ground ground_param = self.ground if (isinstance(self.ground, list) and all(isinstance(item, GroundCriteriaBlock) for item in self.ground)): # ground parameter is a list of GroundCriteriaBlock objects, so we # want to set the query to the dict version of it ground_param = [] for val in self.ground: this_dict = deepcopy(val.__dict__) this_dict["ephemeris_metadata_filters"] = this_dict["metadata_filters"] del this_dict["metadata_filters"] if (this_dict["ephemeris_metadata_filters"] is not None): this_dict["ephemeris_metadata_filters"] = this_dict["ephemeris_metadata_filters"].to_query_dict() ground_param.append(this_dict) # set space space_param = self.space if (isinstance(self.space, list) and all(isinstance(item, SpaceCriteriaBlock) for item in self.space)): # space parameter is a list of SpaceCriteriaBlock objects, so we # want to set the query to the dict version of it space_param = [] for val in self.space: this_dict = deepcopy(val.__dict__) this_dict["ephemeris_metadata_filters"] = this_dict["metadata_filters"] del this_dict["metadata_filters"] if (this_dict["ephemeris_metadata_filters"] is not None): this_dict["ephemeris_metadata_filters"] = this_dict["ephemeris_metadata_filters"].to_query_dict() space_param.append(this_dict) # set events events_param = self.events if (isinstance(self.events, list) and all(isinstance(item, EventsCriteriaBlock) for item in self.events)): # space parameter is a list of EventsCriteriaBlock objects, so we # want to set the query to the dict version of it events_param = [] for val in self.events: this_dict = deepcopy(val.__dict__) this_dict["ephemeris_metadata_filters"] = this_dict["metadata_filters"] this_dict["programs"] = ["events"] del this_dict["metadata_filters"] if (this_dict["ephemeris_metadata_filters"] is not None): this_dict["ephemeris_metadata_filters"] = this_dict["ephemeris_metadata_filters"].to_query_dict() events_param.append(this_dict) # set custom locations custom_param = self.custom_locations if (isinstance(self.custom_locations, list) and all(isinstance(item, CustomLocationsCriteriaBlock) for item in self.custom_locations)): # space parameter is a list of CustomLocationsCriteriaBlock objects, so we # want to set the query to the dict version of it custom_param = [] for val in self.custom_locations: this_dict = val.to_search_query_dict() # type: ignore custom_param.append(this_dict) # set query self.__query = { "start": self.start.strftime("%Y-%m-%dT%H:%M:%S"), "end": self.end.strftime("%Y-%m-%dT%H:%M:%S"), "ground": ground_param, "space": space_param, "events": events_param, "adhoc": custom_param, "conjunction_types": self.conjunction_types, "max_distances": self.distance, "epoch_search_precision": 60, } return self.__query
Property for the query value
Returns
The query parameter
Methods
def cancel(self, wait: bool = False, poll_interval: float = 1.0, verbose: bool = False) ‑> int
-
Expand source code
def cancel(self, wait: bool = False, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> int: """ Cancel the conjunction search request This method returns immediately by default since the API processes this request asynchronously. If you would prefer to wait for it to be completed, set the 'wait' parameter to True. You can adjust the polling time using the 'poll_interval' parameter. Args: wait (bool): Wait until the cancellation request has been completed (may wait for several minutes) poll_interval (float): Seconds to wait between polling calls, defaults to STANDARD_POLLING_SLEEP_TIME. verbose (bool): Output poll times and other progress messages, defaults to False Returns: 1 on success Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_CONJUNCTION_REQUEST.format(self.request_id)) return requests_cancel(self.__aurorax_obj, url, wait, poll_interval, verbose)
Cancel the conjunction search request
This method returns immediately by default since the API processes this request asynchronously. If you would prefer to wait for it to be completed, set the 'wait' parameter to True. You can adjust the polling time using the 'poll_interval' parameter.
Args
wait
:bool
- Wait until the cancellation request has been completed (may wait for several minutes)
poll_interval
:float
- Seconds to wait between polling calls, defaults to STANDARD_POLLING_SLEEP_TIME.
verbose
:bool
- Output poll times and other progress messages, defaults to False
Returns
1 on success
Raises
AuroraXAPIError
- An API error was encountered
def check_criteria_block_count_validity(self) ‑> None
-
Expand source code
def check_criteria_block_count_validity(self) -> None: """ Check the number of of criteria blocks to see if there is too many. A max of 10 is allowed by the AuroraX conjunction search engine. An exception is raised if it was determined to have too many. Raises: pyaurorax.exceptions.AuroraXError: Too many criteria blocks are found """ count_ground = 0 count_space = 0 count_events = 0 count_custom_locations = 0 if (self.ground is not None): count_ground = len(self.ground) if (self.space is not None): count_space = len(self.space) if (self.events is not None): count_events = len(self.events) if (self.custom_locations is not None): count_custom_locations = len(self.custom_locations) if ((count_ground + count_space + count_events + count_custom_locations) > 10): raise AuroraXError("Number of criteria blocks exceeds 10, please reduce the count")
Check the number of of criteria blocks to see if there is too many. A max of 10 is allowed by the AuroraX conjunction search engine. An exception is raised if it was determined to have too many.
Raises
AuroraXError
- Too many criteria blocks are found
def check_for_data(self) ‑> bool
-
Expand source code
def check_for_data(self) -> bool: """ Check to see if data is available for this conjunction search request Returns: True if data is available, else False Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ self.update_status() return self.completed
Check to see if data is available for this conjunction search request
Returns
True if data is available, else False
Raises
AuroraXAPIError
- An API error was encountered
def describe(self)
-
Expand source code
def describe(self): """ Describe the conjunction search as an "SQL-like" string. Returns: The "SQL-like" string describing the conjunction search object """ # make request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DESCRIBE_CONJUNCTION_QUERY) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query) res = req.execute() # return return res.data
Describe the conjunction search as an "SQL-like" string.
Returns
The "SQL-like" string describing the conjunction search object
def execute(self) ‑> None
-
Expand source code
def execute(self) -> None: """ Initiate a conjunction search request Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ # check number of criteria blocks self.check_criteria_block_count_validity() # do request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_CONJUNCTION_SEARCH) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query, null_response=True) res = req.execute() # set request ID, request_url, executed self.executed = True if res.status_code == 202: # request successfully dispatched self.executed = True self.request_url = res.request.headers["location"] self.request_id = self.request_url.rsplit("/", 1)[-1] # set request variable self.request = res
def get_advanced_distances_combos(self, default_distance: Optional[Union[int, float]] = None) ‑> Dict
-
Expand source code
def get_advanced_distances_combos(self, default_distance: Optional[Union[int, float]] = None) -> Dict: """ Get the advanced distances combinations for this search Args: default_distance (int): The default distance to use, defaults to None Returns: The advanced distances combinations """ # set input arrays options = [] if (self.ground is not None): for i in range(0, len(self.ground)): options.append("ground%d" % (i + 1)) if (self.space is not None): for i in range(0, len(self.space)): options.append("space%d" % (i + 1)) if (self.events is not None): for i in range(0, len(self.events)): options.append("events%d" % (i + 1)) if (self.custom_locations is not None): for i in range(0, len(self.custom_locations)): options.append("adhoc%d" % (i + 1)) # derive all combinations of options of size 2 combinations = {} for element in itertools.combinations(options, r=2): combinations["%s-%s" % (element[0], element[1])] = default_distance # return return combinations
Get the advanced distances combinations for this search
Args
default_distance
:int
- The default distance to use, defaults to None
Returns
The advanced distances combinations
def get_data(self) ‑> None
-
Expand source code
def get_data(self) -> None: """ Retrieve the data available for this conjunction search request Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ # check if completed yet if (self.completed is False): print("No data available, update status or check for data first") return # get data raw_data = requests_get_data(self.__aurorax_obj, self.data_url, self.response_format, False) # set data variable if (self.response_format is not None): self.data = raw_data else: # cast data source objects for i in range(0, len(raw_data)): for j in range(0, len(raw_data[i]["data_sources"])): ds = DataSource(**raw_data[i]["data_sources"][j], format=FORMAT_BASIC_INFO) raw_data[i]["data_sources"][j] = ds # cast conjunctions self.data = [Conjunction(**c) for c in raw_data]
Retrieve the data available for this conjunction search request
Raises
AuroraXAPIError
- An API error was encountered
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # set status and query strings max_len = 80 status_str = str(self.status) query_str = str(self.query) if (len(status_str) > max_len): status_str = "%s..." % (status_str[0:max_len]) if (len(query_str) > max_len): query_str = "%s..." % (query_str[0:max_len]) # set results string if (self.executed is True): if (len(self.data) == 0): data_str = "[0 conjunction results]" elif (len(self.data) == 1): data_str = "[1 conjunction result]" else: data_str = "[%d conjunction results]" % (len(self.data)) else: data_str = "" # set logs string if (self.executed is True): if (len(self.logs) == 0): logs_str = "[0 log messages]" elif (len(self.logs) == 1): logs_str = "[1 log message]" else: logs_str = "[%d log messages]" % (len(self.logs)) else: logs_str = "" # print print("ConjunctionSearch:") print(" %-13s: %s" % ("executed", self.executed)) print(" %-13s: %s" % ("completed", self.completed)) print(" %-13s: %s" % ("request_id", self.request_id)) print(" %-13s: %s" % ("request", self.request)) print(" %-13s: %s" % ("request_url", self.request_url)) print(" %-13s: %s" % ("data_url", self.data_url)) print(" %-13s: %s" % ("query", query_str)) print(" %-13s: %s" % ("status", status_str)) print(" %-13s: %s" % ("data", data_str)) print(" %-13s: %s" % ("logs", logs_str))
A special print output for this class.
def update_status(self, status: Optional[Dict] = None) ‑> None
-
Expand source code
def update_status(self, status: Optional[Dict] = None) -> None: """ Update the status of this conjunction search request Args: status (Dict): The previously-retrieved status of this request (include to avoid requesting it from the API again), defaults to None Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ # get the status if it isn't passed in if (status is None): status = requests_get_status(self.__aurorax_obj, self.request_url) # check response if (status is None): raise AuroraXAPIError("Could not retrieve status for this request") # update request status by checking if data URI is set if (status["search_result"]["data_uri"] is not None): self.completed = True self.data_url = "%s/data" % (self.request_url) # set class variable "status" and "logs" self.status = status self.logs = status["logs"]
Update the status of this conjunction search request
Args
status
:Dict
- The previously-retrieved status of this request (include to avoid requesting it from the API again), defaults to None
Raises
AuroraXAPIError
- An API error was encountered
def wait(self, poll_interval: float = 1.0, verbose: bool = False) ‑> None
-
Expand source code
def wait(self, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> None: """ Block and wait until the request is complete and data is available for retrieval Args: poll_interval (float): Time in seconds to wait between polling attempts, defaults to 1 second verbose (bool): Output poll times and other progress messages, defaults to False Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_CONJUNCTION_REQUEST.format(self.request_id)) self.update_status(requests_wait_for_data(self.__aurorax_obj, url, poll_interval, verbose))
Block and wait until the request is complete and data is available for retrieval
Args
poll_interval
:float
- Time in seconds to wait between polling attempts, defaults to 1 second
verbose
:bool
- Output poll times and other progress messages, defaults to False
Raises
AuroraXAPIError
- An API error was encountered
class CustomLocationsCriteriaBlock (locations: List[Tuple[float, float]] = [])
-
Expand source code
class CustomLocationsCriteriaBlock: """ Representation of a custom location criteria block used for conjunction searches. Attributes: locations (List[Tuple[float, float]]): List of locations to use in this criteria block. Location are 2-element tuples of (latitude, longitude). Latitude values must be between -90 and 90, and longitude values must be between -180 and 180. Optional, default is `[]`. """ def __init__(self, locations: List[Tuple[float, float]] = []): self.locations = locations def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: return "CustomLocationsCriteriaBlock(locations=%s)" % (self.locations) def pretty_print(self): """ A special print output for this class. """ print("CustomLocationsCriteriaBlock:") print(" %-11s: %s" % ("locations", self.locations)) def to_search_query_dict(self): query_dict = {} if (len(self.locations) > 0): query_dict["locations"] = [] for location in self.locations: query_dict["locations"].append({ "lat": location[0], "lon": location[1], }) return query_dict
Representation of a custom location criteria block used for conjunction searches.
Attributes
locations
:List[Tuple[float, float]]
- List of locations to use in this criteria block. Location are 2-element tuples
of (latitude, longitude). Latitude values must be between -90 and 90, and longitude
values must be between -180 and 180. Optional, default is
[]
.
Methods
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ print("CustomLocationsCriteriaBlock:") print(" %-11s: %s" % ("locations", self.locations))
A special print output for this class.
def to_search_query_dict(self)
-
Expand source code
def to_search_query_dict(self): query_dict = {} if (len(self.locations) > 0): query_dict["locations"] = [] for location in self.locations: query_dict["locations"].append({ "lat": location[0], "lon": location[1], }) return query_dict
class DataProductData (data_source: DataSource,
data_product_type: str,
start: datetime.datetime,
end: datetime.datetime,
url: str,
metadata: Dict | None = None)-
Expand source code
class DataProductData: """ Data product object Attributes: data_source (DataSource): Data source that the ephemeris record is associated with data_product_type (str): Data product type ("keogram", "movie", "summary_plot", etc.) start (datetime.datetime): Starting timestamp for the record (assumed it is in UTC), inclusive end (datetime.datetime): Ending timestamp for the record (assumed it is in UTC), inclusive url (str): The URL of data product metadata (Dict): Metadata for this record (arbitrary keys and values) """ def __init__(self, data_source: DataSource, data_product_type: str, start: datetime.datetime, end: datetime.datetime, url: str, metadata: Optional[Dict] = None): self.data_source = data_source self.data_product_type = data_product_type self.start = start self.end = end self.url = url self.metadata = metadata def to_json_serializable(self) -> Dict: """ Convert object to a JSON-serializable object (ie. translate datetime objects to strings) Returns: A dictionary object that is JSON-serializable """ # init d = self.__dict__ # format epoch as str if (type(d["start"]) is datetime.datetime): d["start"] = d["start"].strftime("%Y-%m-%dT%H:%M:00.000") if (type(d["end"]) is datetime.datetime): d["end"] = d["end"].strftime("%Y-%m-%dT%H:%M:00.000") # format metadata if (self.metadata is not None): for key, value in self.metadata.items(): if (isinstance(value, datetime.datetime) is True or isinstance(value, datetime.date) is True): self.metadata[key] = self.metadata[key].strftime("%Y-%m-%dT%H:%M:%S.%f") # if (isinstance(self.metadata, list) is True): # self.metadata = {} # format data source fields for query d["program"] = self.data_source.program d["platform"] = self.data_source.platform d["instrument_type"] = self.data_source.instrument_type del d["data_source"] # return return d def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: # shorten the metadata and url max_len = 20 attr_metadata = f"{self.metadata}" if (len(attr_metadata) > max_len): attr_metadata = attr_metadata[0:max_len] + "...}" attr_url = f"{self.url}" if (len(attr_url) > max_len): attr_url = attr_url[0:max_len] + "..." # return formatted representation return f"DataProductData(start={repr(self.start)}, end={repr(self.end)}, data_product_type='{self.data_product_type}', " \ f"url='{attr_url}', metadata={attr_metadata}, data_source=DataSource(...))"
Data product object
Attributes
data_source
:DataSource
- Data source that the ephemeris record is associated with
data_product_type
:str
- Data product type ("keogram", "movie", "summary_plot", etc.)
start
:datetime.datetime
- Starting timestamp for the record (assumed it is in UTC), inclusive
end
:datetime.datetime
- Ending timestamp for the record (assumed it is in UTC), inclusive
url
:str
- The URL of data product
metadata
:Dict
- Metadata for this record (arbitrary keys and values)
Methods
def to_json_serializable(self) ‑> Dict
-
Expand source code
def to_json_serializable(self) -> Dict: """ Convert object to a JSON-serializable object (ie. translate datetime objects to strings) Returns: A dictionary object that is JSON-serializable """ # init d = self.__dict__ # format epoch as str if (type(d["start"]) is datetime.datetime): d["start"] = d["start"].strftime("%Y-%m-%dT%H:%M:00.000") if (type(d["end"]) is datetime.datetime): d["end"] = d["end"].strftime("%Y-%m-%dT%H:%M:00.000") # format metadata if (self.metadata is not None): for key, value in self.metadata.items(): if (isinstance(value, datetime.datetime) is True or isinstance(value, datetime.date) is True): self.metadata[key] = self.metadata[key].strftime("%Y-%m-%dT%H:%M:%S.%f") # if (isinstance(self.metadata, list) is True): # self.metadata = {} # format data source fields for query d["program"] = self.data_source.program d["platform"] = self.data_source.platform d["instrument_type"] = self.data_source.instrument_type del d["data_source"] # return return d
Convert object to a JSON-serializable object (ie. translate datetime objects to strings)
Returns
A dictionary object that is JSON-serializable
class DataProductSearch (aurorax_obj: PyAuroraX,
start: datetime.datetime,
end: datetime.datetime,
programs: Optional[List[str]] = None,
platforms: Optional[List[str]] = None,
instrument_types: Optional[List[str]] = None,
data_product_types: "Optional[Literal['keogram', 'montage', 'movie', 'summary_plot', 'data_availability']]" = None,
metadata_filters: Optional[Union[MetadataFilter, List[Dict]]] = None,
metadata_filters_logical_operator: "Optional[Literal['and', 'or', 'AND', 'OR']]" = None,
response_format: Optional[Dict] = None)-
Expand source code
class DataProductSearch: """ Class representing a data product search Attributes: start (datetime.datetime): Start timestamp of the search (inclusive) end (datetime.datetime): End timestamp of the search (inclusive) programs (List[str]): List of program names to search platforms (List[str]): List of platform names to search instrument_types (List[str]): List of instrument types to search data_product_types (List[str]): List of strings describing data product types to filter on e.g. "keogram", defaults to None. Valid options are: `keogram`, `montage`, `movie`, `summary_plot`, and `data_availability`. metadata_filters (MetadataFilter or List[Dict]): The metadata filters to use when searching, defaults to None metadata_filters_logical_operator (str): The logical operator to use when evaluating metadata filters (either `and` or `or`), defaults to `and`. This parameter is deprecated in exchange for passing a MetadataFilter object into the metadata_filters parameter. response_format (Dict): JSON representation of desired data response format request (AuroraXResponse): AuroraXResponse object returned when the search is executed request_id (str): Unique ID assigned to the request by the AuroraX API request_url (str): Unique URL assigned to the request by the AuroraX API executed (bool): Indicates if the search has been executed/started completed (bool): Indicates if the search has finished data_url (str): The URL where data is accessed query (Dict): The query for this request as JSON status (Dict): The status of the query data (List[DataProductData]): The data product records found logs (List[Dict]): All log messages outputted by the AuroraX API for this request """ __STANDARD_POLLING_SLEEP_TIME: float = 1.0 def __init__(self, aurorax_obj: PyAuroraX, start: datetime.datetime, end: datetime.datetime, programs: Optional[List[str]] = None, platforms: Optional[List[str]] = None, instrument_types: Optional[List[str]] = None, data_product_types: Optional[Literal["keogram", "montage", "movie", "summary_plot", "data_availability"]] = None, metadata_filters: Optional[Union[MetadataFilter, List[Dict]]] = None, metadata_filters_logical_operator: Optional[Literal["and", "or", "AND", "OR"]] = None, response_format: Optional[Dict] = None) -> None: # set variables using passed in args self.__aurorax_obj = aurorax_obj self.start = start self.end = end self.programs = programs self.platforms = platforms self.instrument_types = instrument_types self.data_product_types = data_product_types self.metadata_filters = metadata_filters self.metadata_filters_logical_operator = "AND" if metadata_filters_logical_operator is None else metadata_filters_logical_operator self.response_format = response_format # initialize additional variables self.request = None self.request_id = "" self.request_url = "" self.executed = False self.completed = False self.data_url = "" self.__query = {} self.status = {} self.data = [] self.logs = [] def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: return "DataProductSearch(executed=%s, completed=%s, request_id='%s')" % ( self.executed, self.completed, self.request_id, ) def pretty_print(self): """ A special print output for this class. """ # set status and query strings max_len = 80 status_str = str(self.status) query_str = str(self.query) if (len(status_str) > max_len): status_str = "%s..." % (status_str[0:max_len]) if (len(query_str) > max_len): query_str = "%s..." % (query_str[0:max_len]) # set results string if (self.executed is True): if (len(self.data) == 0): data_str = "[0 data product results]" elif (len(self.data) == 1): data_str = "[1 data product result]" else: data_str = "[%d data product results]" % (len(self.data)) else: data_str = "" # set logs string if (self.executed is True): if (len(self.logs) == 0): logs_str = "[0 log messages]" elif (len(self.logs) == 1): logs_str = "[1 log message]" else: logs_str = "[%d log messages]" % (len(self.logs)) else: logs_str = "" # print print("DataProductSearch:") print(" %-13s: %s" % ("executed", self.executed)) print(" %-13s: %s" % ("completed", self.completed)) print(" %-13s: %s" % ("request_id", self.request_id)) print(" %-13s: %s" % ("request", self.request)) print(" %-13s: %s" % ("request_url", self.request_url)) print(" %-13s: %s" % ("data_url", self.data_url)) print(" %-13s: %s" % ("query", query_str)) print(" %-13s: %s" % ("status", status_str)) print(" %-13s: %s" % ("data", data_str)) print(" %-13s: %s" % ("logs", logs_str)) @property def query(self): """ Property for the query value """ # set metadata filter value if (self.metadata_filters is None): metadata_filters_dict = {} elif (isinstance(self.metadata_filters, MetadataFilter) is True): # metadata filter is a class metadata_filters_dict = self.metadata_filters.to_query_dict() # type: ignore else: # metadata filter is a dictionary metadata_filters_dict = { "expressions": self.metadata_filters, "logical_operator": self.metadata_filters_logical_operator, } # set query self.__query = { "data_sources": { "programs": [] if not self.programs else self.programs, "platforms": [] if not self.platforms else self.platforms, "instrument_types": [] if not self.instrument_types else self.instrument_types, "data_product_metadata_filters": metadata_filters_dict, }, "start": self.start.strftime("%Y-%m-%dT%H:%M:%S"), "end": self.end.strftime("%Y-%m-%dT%H:%M:%S"), "data_product_type_filters": [] if not self.data_product_types else self.data_product_types, } # return return self.__query @query.setter def query(self, query): self.__query = query def execute(self) -> None: """ Initiate a data product search request """ # do request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DATA_PRODUCTS_SEARCH) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query, null_response=True) res = req.execute() # set request ID, request_url, executed self.executed = True if (res.status_code == 202): # request successfully dispatched self.executed = True self.request_url = res.request.headers["location"] self.request_id = self.request_url.rsplit("/", 1)[-1] # set request variable self.request = res def update_status(self, status: Optional[Dict] = None) -> None: """ Update the status of this data product search request Args: status (Dict): The previously-retrieved status of this request (include to avoid requesting it from the API again), defaults to None """ # get the status if it isn't passed in if (status is None): status = requests_get_status(self.__aurorax_obj, self.request_url) # check response if (status is None): raise AuroraXAPIError("Could not retrieve status for this request") # update request status by checking if data URI is set if (status["search_result"]["data_uri"] is not None): self.completed = True self.data_url = "%s/data" % (self.request_url) # set class variable "status" and "logs" self.status = status self.logs = status["logs"] def check_for_data(self) -> bool: """ Check to see if data is available for this data product search request Returns: True if data is available, else False """ self.update_status() return self.completed def get_data(self) -> None: """ Retrieve the data available for this data product search request """ # check if completed yet if (self.completed is False): print("No data available, update status or check for data first") return # get data raw_data = requests_get_data(self.__aurorax_obj, self.data_url, self.response_format, False) # set data variable if (self.response_format is not None): self.data = raw_data else: # cast data source objects for i in range(0, len(raw_data)): ds = DataSource(**raw_data[i]["data_source"], format=FORMAT_BASIC_INFO) raw_data[i]["data_source"] = ds # cast data product objects self.data = [DataProductData(**dp) for dp in raw_data] def wait(self, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> None: """ Block and wait for the request to complete and data is available for retrieval Args: poll_interval (float): Time in seconds to wait between polling attempts, defaults to 1 second verbose (bool): Output poll times and other progress messages, defaults to False """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DATA_PRODUCTS_REQUEST.format(self.request_id)) self.update_status(requests_wait_for_data(self.__aurorax_obj, url, poll_interval, verbose)) def cancel(self, wait: bool = False, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> int: """ Cancel the data product search request This method returns immediately by default since the API processes this request asynchronously. If you would prefer to wait for it to be completed, set the 'wait' parameter to True. You can adjust the polling time using the 'poll_interval' parameter. Args: wait (bool): Wait until the cancellation request has been completed (may wait for several minutes) poll_interval (float): Seconds to wait between polling calls, defaults to 1 second. verbose (bool): Output poll times and other progress messages, defaults to False Returns: 1 on success Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered pyaurorax.exceptions.AuroraXUnauthorizedError: Invalid API key for this operation """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DATA_PRODUCTS_REQUEST.format(self.request_id)) return requests_cancel(self.__aurorax_obj, url, wait, poll_interval, verbose) def describe(self): """ Describe the data products search as an "SQL-like" string. Returns: The "SQL-like" string describing the data products search object """ # make request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DESCRIBE_DATA_PRODUCTS_QUERY) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query) res = req.execute() # return return res.data
Class representing a data product search
Attributes
start
:datetime.datetime
- Start timestamp of the search (inclusive)
end
:datetime.datetime
- End timestamp of the search (inclusive)
programs
:List[str]
- List of program names to search
platforms
:List[str]
- List of platform names to search
instrument_types
:List[str]
- List of instrument types to search
data_product_types
:List[str]
- List of strings describing data product types to filter on e.g. "keogram", defaults
to None. Valid options are:
keogram
,montage
,movie
,summary_plot
, anddata_availability
. metadata_filters
:MetadataFilter
orList[Dict]
- The metadata filters to use when searching, defaults to None
metadata_filters_logical_operator
:str
- The logical operator to use when evaluating metadata filters (either
and
oror
), defaults toand
. This parameter is deprecated in exchange for passing a MetadataFilter object into the metadata_filters parameter. response_format
:Dict
- JSON representation of desired data response format
request
:AuroraXResponse
- AuroraXResponse object returned when the search is executed
request_id
:str
- Unique ID assigned to the request by the AuroraX API
request_url
:str
- Unique URL assigned to the request by the AuroraX API
executed
:bool
- Indicates if the search has been executed/started
completed
:bool
- Indicates if the search has finished
data_url
:str
- The URL where data is accessed
query
:Dict
- The query for this request as JSON
status
:Dict
- The status of the query
data
:List[DataProductData]
- The data product records found
logs
:List[Dict]
- All log messages outputted by the AuroraX API for this request
Instance variables
prop query
-
Expand source code
@property def query(self): """ Property for the query value """ # set metadata filter value if (self.metadata_filters is None): metadata_filters_dict = {} elif (isinstance(self.metadata_filters, MetadataFilter) is True): # metadata filter is a class metadata_filters_dict = self.metadata_filters.to_query_dict() # type: ignore else: # metadata filter is a dictionary metadata_filters_dict = { "expressions": self.metadata_filters, "logical_operator": self.metadata_filters_logical_operator, } # set query self.__query = { "data_sources": { "programs": [] if not self.programs else self.programs, "platforms": [] if not self.platforms else self.platforms, "instrument_types": [] if not self.instrument_types else self.instrument_types, "data_product_metadata_filters": metadata_filters_dict, }, "start": self.start.strftime("%Y-%m-%dT%H:%M:%S"), "end": self.end.strftime("%Y-%m-%dT%H:%M:%S"), "data_product_type_filters": [] if not self.data_product_types else self.data_product_types, } # return return self.__query
Property for the query value
Methods
def cancel(self, wait: bool = False, poll_interval: float = 1.0, verbose: bool = False) ‑> int
-
Expand source code
def cancel(self, wait: bool = False, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> int: """ Cancel the data product search request This method returns immediately by default since the API processes this request asynchronously. If you would prefer to wait for it to be completed, set the 'wait' parameter to True. You can adjust the polling time using the 'poll_interval' parameter. Args: wait (bool): Wait until the cancellation request has been completed (may wait for several minutes) poll_interval (float): Seconds to wait between polling calls, defaults to 1 second. verbose (bool): Output poll times and other progress messages, defaults to False Returns: 1 on success Raises: pyaurorax.exceptions.AuroraXAPIError: An API error was encountered pyaurorax.exceptions.AuroraXUnauthorizedError: Invalid API key for this operation """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DATA_PRODUCTS_REQUEST.format(self.request_id)) return requests_cancel(self.__aurorax_obj, url, wait, poll_interval, verbose)
Cancel the data product search request
This method returns immediately by default since the API processes this request asynchronously. If you would prefer to wait for it to be completed, set the 'wait' parameter to True. You can adjust the polling time using the 'poll_interval' parameter.
Args
wait
:bool
- Wait until the cancellation request has been completed (may wait for several minutes)
poll_interval
:float
- Seconds to wait between polling calls, defaults to 1 second.
verbose
:bool
- Output poll times and other progress messages, defaults to False
Returns
1 on success
Raises
AuroraXAPIError
- An API error was encountered
AuroraXUnauthorizedError
- Invalid API key for this operation
def check_for_data(self) ‑> bool
-
Expand source code
def check_for_data(self) -> bool: """ Check to see if data is available for this data product search request Returns: True if data is available, else False """ self.update_status() return self.completed
Check to see if data is available for this data product search request
Returns
True if data is available, else False
def describe(self)
-
Expand source code
def describe(self): """ Describe the data products search as an "SQL-like" string. Returns: The "SQL-like" string describing the data products search object """ # make request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DESCRIBE_DATA_PRODUCTS_QUERY) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query) res = req.execute() # return return res.data
Describe the data products search as an "SQL-like" string.
Returns
The "SQL-like" string describing the data products search object
def execute(self) ‑> None
-
Expand source code
def execute(self) -> None: """ Initiate a data product search request """ # do request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DATA_PRODUCTS_SEARCH) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query, null_response=True) res = req.execute() # set request ID, request_url, executed self.executed = True if (res.status_code == 202): # request successfully dispatched self.executed = True self.request_url = res.request.headers["location"] self.request_id = self.request_url.rsplit("/", 1)[-1] # set request variable self.request = res
Initiate a data product search request
def get_data(self) ‑> None
-
Expand source code
def get_data(self) -> None: """ Retrieve the data available for this data product search request """ # check if completed yet if (self.completed is False): print("No data available, update status or check for data first") return # get data raw_data = requests_get_data(self.__aurorax_obj, self.data_url, self.response_format, False) # set data variable if (self.response_format is not None): self.data = raw_data else: # cast data source objects for i in range(0, len(raw_data)): ds = DataSource(**raw_data[i]["data_source"], format=FORMAT_BASIC_INFO) raw_data[i]["data_source"] = ds # cast data product objects self.data = [DataProductData(**dp) for dp in raw_data]
Retrieve the data available for this data product search request
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # set status and query strings max_len = 80 status_str = str(self.status) query_str = str(self.query) if (len(status_str) > max_len): status_str = "%s..." % (status_str[0:max_len]) if (len(query_str) > max_len): query_str = "%s..." % (query_str[0:max_len]) # set results string if (self.executed is True): if (len(self.data) == 0): data_str = "[0 data product results]" elif (len(self.data) == 1): data_str = "[1 data product result]" else: data_str = "[%d data product results]" % (len(self.data)) else: data_str = "" # set logs string if (self.executed is True): if (len(self.logs) == 0): logs_str = "[0 log messages]" elif (len(self.logs) == 1): logs_str = "[1 log message]" else: logs_str = "[%d log messages]" % (len(self.logs)) else: logs_str = "" # print print("DataProductSearch:") print(" %-13s: %s" % ("executed", self.executed)) print(" %-13s: %s" % ("completed", self.completed)) print(" %-13s: %s" % ("request_id", self.request_id)) print(" %-13s: %s" % ("request", self.request)) print(" %-13s: %s" % ("request_url", self.request_url)) print(" %-13s: %s" % ("data_url", self.data_url)) print(" %-13s: %s" % ("query", query_str)) print(" %-13s: %s" % ("status", status_str)) print(" %-13s: %s" % ("data", data_str)) print(" %-13s: %s" % ("logs", logs_str))
A special print output for this class.
def update_status(self, status: Optional[Dict] = None) ‑> None
-
Expand source code
def update_status(self, status: Optional[Dict] = None) -> None: """ Update the status of this data product search request Args: status (Dict): The previously-retrieved status of this request (include to avoid requesting it from the API again), defaults to None """ # get the status if it isn't passed in if (status is None): status = requests_get_status(self.__aurorax_obj, self.request_url) # check response if (status is None): raise AuroraXAPIError("Could not retrieve status for this request") # update request status by checking if data URI is set if (status["search_result"]["data_uri"] is not None): self.completed = True self.data_url = "%s/data" % (self.request_url) # set class variable "status" and "logs" self.status = status self.logs = status["logs"]
Update the status of this data product search request
Args
status
:Dict
- The previously-retrieved status of this request (include to avoid requesting it from the API again), defaults to None
def wait(self, poll_interval: float = 1.0, verbose: bool = False) ‑> None
-
Expand source code
def wait(self, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> None: """ Block and wait for the request to complete and data is available for retrieval Args: poll_interval (float): Time in seconds to wait between polling attempts, defaults to 1 second verbose (bool): Output poll times and other progress messages, defaults to False """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DATA_PRODUCTS_REQUEST.format(self.request_id)) self.update_status(requests_wait_for_data(self.__aurorax_obj, url, poll_interval, verbose))
Block and wait for the request to complete and data is available for retrieval
Args
poll_interval
:float
- Time in seconds to wait between polling attempts, defaults to 1 second
verbose
:bool
- Output poll times and other progress messages, defaults to False
class DataSource (identifier: int | None = None,
program: str | None = None,
platform: str | None = None,
instrument_type: str | None = None,
source_type: str | None = None,
display_name: str | None = None,
metadata: Dict | None = None,
owner: str | None = None,
maintainers: List[str] | None = None,
ephemeris_metadata_schema: List[Dict] | None = None,
data_product_metadata_schema: List[Dict] | None = None,
stats: DataSourceStatistics | None = None,
format: str = 'full_record')-
Expand source code
class DataSource: """ AuroraX data source record Attributes: identifier (int): The unique AuroraX data source identifier program (str): The program for this data source platform (str): The platform for this data source instrument_type (str): The instrument type for this data source source_type (str): The data source type for this data source. Options are in the pyaurorax.search.sources module, or at the top level using the pyaurorax.search.SOURCE_TYPE_* variables. display_name (str): The display name for this data source metadata (Dict): Metadata for this data source (arbitrary keys and values) owner (str): The owner's email address of this data source maintainers (List[str]): The email addresses of AuroraX accounts that can alter this data source and its associated records ephemeris_metadata_schema (Dict): A list of dictionaries capturing the metadata keys and values that can appear in ephemeris records associated with this data source data_product_metadata_schema (Dict): A list of dictionaries capturing the metadata keys and values that can appear in data product records associated with this data source stats (DataSourceStatistics): Data source statistics information format (str): The format used when printing the data source, defaults to `full_record`. Other options are in the pyaurorax.search.sources module, or at the top level using the pyaurorax.search.FORMAT_* variables. """ def __init__(self, identifier: Optional[int] = None, program: Optional[str] = None, platform: Optional[str] = None, instrument_type: Optional[str] = None, source_type: Optional[str] = None, display_name: Optional[str] = None, metadata: Optional[Dict] = None, owner: Optional[str] = None, maintainers: Optional[List[str]] = None, ephemeris_metadata_schema: Optional[List[Dict]] = None, data_product_metadata_schema: Optional[List[Dict]] = None, stats: Optional[DataSourceStatistics] = None, format: str = FORMAT_FULL_RECORD): self.identifier = identifier self.program = program self.platform = platform self.instrument_type = instrument_type self.source_type = source_type self.display_name = display_name self.metadata = metadata self.owner = owner self.maintainers = maintainers self.ephemeris_metadata_schema = ephemeris_metadata_schema self.data_product_metadata_schema = data_product_metadata_schema self.stats = stats self.format = format def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: return "DataSource(identifier=%s, program='%s', platform='%s', instrument_type='%s', source_type='%s', display_name='%s', ...)" % ( self.identifier, self.program, self.platform, self.instrument_type, self.source_type, self.display_name, ) def pretty_print(self): """ A special print output for this class. """ max_len = 80 print("DataSource:") print(" %-30s: %d" % ("identifier", self.identifier)) print(" %-30s: %s" % ("program", self.program)) print(" %-30s: %s" % ("platform", self.platform)) print(" %-30s: %s" % ("instrument_type", self.instrument_type)) print(" %-30s: %s" % ("source_type", self.source_type)) print(" %-30s: %s" % ("display_name", self.display_name)) print(" %-30s: %s" % ("metadata", self.metadata)) print(" %-30s: %s" % ("owner", self.owner)) print(" %-30s: %s" % ("maintainers", self.maintainers)) if (self.ephemeris_metadata_schema is not None and len(str(self.ephemeris_metadata_schema)) > max_len): ephemeris_metadata_schema_str = "%s..." % (str(self.ephemeris_metadata_schema)[0:max_len]) else: ephemeris_metadata_schema_str = self.ephemeris_metadata_schema print(" %-30s: %s" % ("ephemeris_metadata_schema", ephemeris_metadata_schema_str)) if (self.data_product_metadata_schema is not None and len(str(self.data_product_metadata_schema)) > max_len): data_product_metadata_schema_str = "%s..." % (str(self.data_product_metadata_schema)[0:max_len]) else: data_product_metadata_schema_str = self.data_product_metadata_schema print(" %-30s: %s" % ("data_product_metadata_schema", data_product_metadata_schema_str)) if (self.stats is not None and len(str(self.stats)) > max_len): stats_str = "%s..." % (str(self.stats)[0:max_len]) else: stats_str = self.data_product_metadata_schema print(" %-30s: %s" % ("stats", stats_str)) print(" %-30s: %s" % ("format", self.format))
AuroraX data source record
Attributes
identifier
:int
- The unique AuroraX data source identifier
program
:str
- The program for this data source
platform
:str
- The platform for this data source
instrument_type
:str
- The instrument type for this data source
source_type
:str
- The data source type for this data source. Options are in the pyaurorax.search.sources module, or at the top level using the pyaurorax.search.SOURCE_TYPE_* variables.
display_name
:str
- The display name for this data source
metadata
:Dict
- Metadata for this data source (arbitrary keys and values)
owner
:str
- The owner's email address of this data source
maintainers
:List[str]
- The email addresses of AuroraX accounts that can alter this data source and its associated records
ephemeris_metadata_schema
:Dict
- A list of dictionaries capturing the metadata keys and values that can appear in ephemeris records associated with this data source
data_product_metadata_schema
:Dict
- A list of dictionaries capturing the metadata keys and values that can appear in data product records associated with this data source
stats
:DataSourceStatistics
- Data source statistics information
format
:str
- The format used when printing the data source, defaults to
full_record
. Other options are in the pyaurorax.search.sources module, or at the top level using the pyaurorax.search.FORMAT_* variables.
Methods
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ max_len = 80 print("DataSource:") print(" %-30s: %d" % ("identifier", self.identifier)) print(" %-30s: %s" % ("program", self.program)) print(" %-30s: %s" % ("platform", self.platform)) print(" %-30s: %s" % ("instrument_type", self.instrument_type)) print(" %-30s: %s" % ("source_type", self.source_type)) print(" %-30s: %s" % ("display_name", self.display_name)) print(" %-30s: %s" % ("metadata", self.metadata)) print(" %-30s: %s" % ("owner", self.owner)) print(" %-30s: %s" % ("maintainers", self.maintainers)) if (self.ephemeris_metadata_schema is not None and len(str(self.ephemeris_metadata_schema)) > max_len): ephemeris_metadata_schema_str = "%s..." % (str(self.ephemeris_metadata_schema)[0:max_len]) else: ephemeris_metadata_schema_str = self.ephemeris_metadata_schema print(" %-30s: %s" % ("ephemeris_metadata_schema", ephemeris_metadata_schema_str)) if (self.data_product_metadata_schema is not None and len(str(self.data_product_metadata_schema)) > max_len): data_product_metadata_schema_str = "%s..." % (str(self.data_product_metadata_schema)[0:max_len]) else: data_product_metadata_schema_str = self.data_product_metadata_schema print(" %-30s: %s" % ("data_product_metadata_schema", data_product_metadata_schema_str)) if (self.stats is not None and len(str(self.stats)) > max_len): stats_str = "%s..." % (str(self.stats)[0:max_len]) else: stats_str = self.data_product_metadata_schema print(" %-30s: %s" % ("stats", stats_str)) print(" %-30s: %s" % ("format", self.format))
A special print output for this class.
class EphemerisData (data_source: DataSource,
epoch: datetime.datetime,
location_geo: Location | None = None,
nbtrace: Location | None = None,
sbtrace: Location | None = None,
location_gsm: Location | None = None,
metadata: Dict | None = None)-
Expand source code
class EphemerisData: """ Ephemeris object Attributes: data_source (DataSource): Data source that the ephemeris record is associated with epoch (datetime.datetime): Timestamp for the record (assumed it is in UTC) location_geo (Location): Location object containing geographic latitude and longitude location_gsm (Location): Location object containing GSM latitude and longitude (leave empty for data sources with a type of 'ground') nbtrace (Location): Location object with north B-trace geographic latitude and longitude sbtrace (Location): Location object with south B-trace geographic latitude and longitude metadata (Dict): Metadata for this record (arbitrary keys and values) """ def __init__(self, data_source: DataSource, epoch: datetime.datetime, location_geo: Optional[Location] = None, nbtrace: Optional[Location] = None, sbtrace: Optional[Location] = None, location_gsm: Optional[Location] = None, metadata: Optional[Dict] = None): self.data_source = data_source self.epoch = epoch self.location_geo = Location(lat=None, lon=None) if location_geo is None else location_geo self.nbtrace = Location(lat=None, lon=None) if nbtrace is None else nbtrace self.sbtrace = Location(lat=None, lon=None) if sbtrace is None else sbtrace self.location_gsm = Location(lat=None, lon=None) if location_gsm is None else location_gsm self.metadata = metadata def to_json_serializable(self) -> Dict: """ Convert object to a JSON-serializable object (ie. translate datetime objects to strings) Returns: A dictionary object that is JSON-serializable """ # init d = self.__dict__ # format epoch as str if (isinstance(d["epoch"], datetime.datetime) is True): d["epoch"] = d["epoch"].strftime("%Y-%m-%dT%H:%M:00.000Z") # format location if (isinstance(d["location_geo"], Location) is True): d["location_geo"] = d["location_geo"].to_json_serializable() if (isinstance(d["location_gsm"], Location) is True): d["location_gsm"] = d["location_gsm"].to_json_serializable() if (isinstance(d["nbtrace"], Location) is True): d["nbtrace"] = d["nbtrace"].to_json_serializable() if (isinstance(d["sbtrace"], Location) is True): d["sbtrace"] = d["sbtrace"].to_json_serializable() # format metadata if (self.metadata is not None): for key, value in self.metadata.items(): if (isinstance(value, datetime.datetime) is True or isinstance(value, datetime.date) is True): self.metadata[key] = self.metadata[key].strftime("%Y-%m-%dT%H:%M:%S.%f") # if (isinstance(self.metadata, list) is True): # self.metadata = {} # format data source fields for query d["program"] = self.data_source.program d["platform"] = self.data_source.platform d["instrument_type"] = self.data_source.instrument_type del d["data_source"] # return return d def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: # shorten the metadata max_len = 20 attr_metadata = f"{self.metadata}" if (len(attr_metadata) > max_len): attr_metadata = attr_metadata[0:max_len] + "...}" # return formatted representation return f"EphemerisData(epoch={repr(self.epoch)}, location_geo={repr(self.location_geo)}, " \ f"location_gsm={repr(self.location_gsm)}, nbtrace={repr(self.nbtrace)}, sbtrace={repr(self.sbtrace)}, " \ f"metadata={attr_metadata}, data_source=DataSource(...))"
Ephemeris object
Attributes
data_source
:DataSource
- Data source that the ephemeris record is associated with
epoch
:datetime.datetime
- Timestamp for the record (assumed it is in UTC)
location_geo
:Location
- Location object containing geographic latitude and longitude
location_gsm
:Location
- Location object containing GSM latitude and longitude (leave empty for data sources with a type of 'ground')
nbtrace
:Location
- Location object with north B-trace geographic latitude and longitude
sbtrace
:Location
- Location object with south B-trace geographic latitude and longitude
metadata
:Dict
- Metadata for this record (arbitrary keys and values)
Methods
def to_json_serializable(self) ‑> Dict
-
Expand source code
def to_json_serializable(self) -> Dict: """ Convert object to a JSON-serializable object (ie. translate datetime objects to strings) Returns: A dictionary object that is JSON-serializable """ # init d = self.__dict__ # format epoch as str if (isinstance(d["epoch"], datetime.datetime) is True): d["epoch"] = d["epoch"].strftime("%Y-%m-%dT%H:%M:00.000Z") # format location if (isinstance(d["location_geo"], Location) is True): d["location_geo"] = d["location_geo"].to_json_serializable() if (isinstance(d["location_gsm"], Location) is True): d["location_gsm"] = d["location_gsm"].to_json_serializable() if (isinstance(d["nbtrace"], Location) is True): d["nbtrace"] = d["nbtrace"].to_json_serializable() if (isinstance(d["sbtrace"], Location) is True): d["sbtrace"] = d["sbtrace"].to_json_serializable() # format metadata if (self.metadata is not None): for key, value in self.metadata.items(): if (isinstance(value, datetime.datetime) is True or isinstance(value, datetime.date) is True): self.metadata[key] = self.metadata[key].strftime("%Y-%m-%dT%H:%M:%S.%f") # if (isinstance(self.metadata, list) is True): # self.metadata = {} # format data source fields for query d["program"] = self.data_source.program d["platform"] = self.data_source.platform d["instrument_type"] = self.data_source.instrument_type del d["data_source"] # return return d
Convert object to a JSON-serializable object (ie. translate datetime objects to strings)
Returns
A dictionary object that is JSON-serializable
class EphemerisSearch (aurorax_obj: PyAuroraX,
start: datetime.datetime,
end: datetime.datetime,
programs: Optional[List[str]] = None,
platforms: Optional[List[str]] = None,
instrument_types: Optional[List[str]] = None,
metadata_filters: Optional[Union[MetadataFilter, List[Dict]]] = None,
metadata_filters_logical_operator: "Optional[Literal['and', 'or', 'AND', 'OR']]" = None,
response_format: Optional[Dict] = None)-
Expand source code
class EphemerisSearch: """ Class representing an ephemeris search Note: At least one search criteria from programs, platforms, or instrument_types must be specified. Attributes: start (datetime.datetime): Start timestamp of the search (inclusive) end (datetime.datetime): End timestamp of the search (inclusive) programs (List[str]): List of programs to search through, defaults to None platforms (List[str]): List of platforms to search through, defaults to None instrument_types (List[str]): List of instrument types to search through, defaults to None metadata_filters (MetadataFilter or List[Dict]): List of dictionaries describing metadata keys and values to filter on, defaults to None metadata_filters_logical_operator (str): The logical operator to use when evaluating metadata filters (either `AND` or `OR`), defaults to `AND` response_format (Dict): JSON representation of desired data response format request (AuroraXResponse): AuroraXResponse object returned when the search is executed request_id (str): Unique ID assigned to the request by the AuroraX API request_url (str): Unique URL assigned to the request by the AuroraX API executed (bool): Indicates if the search has been executed/started completed (bool): Indicates if the search has finished data_url (str): The URL where data is accessed query (Dict): The query for this request as JSON status (Dict): The status of the query data (List[EphemerisData]): The ephemeris records found logs (List[Dict]): All log messages outputted by the AuroraX API for this request """ __STANDARD_POLLING_SLEEP_TIME: float = 1.0 def __init__(self, aurorax_obj: PyAuroraX, start: datetime.datetime, end: datetime.datetime, programs: Optional[List[str]] = None, platforms: Optional[List[str]] = None, instrument_types: Optional[List[str]] = None, metadata_filters: Optional[Union[MetadataFilter, List[Dict]]] = None, metadata_filters_logical_operator: Optional[Literal["and", "or", "AND", "OR"]] = None, response_format: Optional[Dict] = None) -> None: # set variables using passed in args self.__aurorax_obj = aurorax_obj self.start = start self.end = end self.programs = programs self.platforms = platforms self.instrument_types = instrument_types self.metadata_filters = metadata_filters self.metadata_filters_logical_operator = "AND" if metadata_filters_logical_operator is None else metadata_filters_logical_operator.upper() self.response_format = response_format # initialize additional variables self.request = None self.request_id = "" self.request_url = "" self.executed = False self.completed = False self.data_url = "" self.__query = {} self.status = {} self.data = [] self.logs = [] def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: return "EphemerisSearch(executed=%s, completed=%s, request_id='%s')" % ( self.executed, self.completed, self.request_id, ) def pretty_print(self): """ A special print output for this class. """ # set status and query strings max_len = 80 status_str = str(self.status) query_str = str(self.query) if (len(status_str) > max_len): status_str = "%s..." % (status_str[0:max_len]) if (len(query_str) > max_len): query_str = "%s..." % (query_str[0:max_len]) # set results string if (self.executed is True): if (len(self.data) == 0): data_str = "[0 ephemeris results]" elif (len(self.data) == 1): data_str = "[1 ephemeris result]" else: data_str = "[%d ephemeris results]" % (len(self.data)) else: data_str = "" # set logs string if (self.executed is True): if (len(self.logs) == 0): logs_str = "[0 log messages]" elif (len(self.logs) == 1): logs_str = "[1 log message]" else: logs_str = "[%d log messages]" % (len(self.logs)) else: logs_str = "" # print print("EphemerisSearch:") print(" %-13s: %s" % ("executed", self.executed)) print(" %-13s: %s" % ("completed", self.completed)) print(" %-13s: %s" % ("request_id", self.request_id)) print(" %-13s: %s" % ("request", self.request)) print(" %-13s: %s" % ("request_url", self.request_url)) print(" %-13s: %s" % ("data_url", self.data_url)) print(" %-13s: %s" % ("query", query_str)) print(" %-13s: %s" % ("status", status_str)) print(" %-13s: %s" % ("data", data_str)) print(" %-13s: %s" % ("logs", logs_str)) @property def query(self): """ Property for the query value """ # set metadata filter value if (self.metadata_filters is None): metadata_filters_dict = {} elif (isinstance(self.metadata_filters, MetadataFilter) is True): # metadata filter is a class metadata_filters_dict = self.metadata_filters.to_query_dict() # type: ignore else: # metadata filter is a dictionary metadata_filters_dict = { "expressions": self.metadata_filters, "logical_operator": self.metadata_filters_logical_operator, } # set query self.__query = { "data_sources": { "programs": [] if not self.programs else self.programs, "platforms": [] if not self.platforms else self.platforms, "instrument_types": [] if not self.instrument_types else self.instrument_types, "ephemeris_metadata_filters": metadata_filters_dict, }, "start": self.start.strftime("%Y-%m-%dT%H:%M:%S"), "end": self.end.strftime("%Y-%m-%dT%H:%M:%S"), } # return return self.__query @query.setter def query(self, query): self.__query = query def execute(self) -> None: """ Initiate ephemeris search request Raises: pyaurorax.exceptions.AuroraXError: Invalid request parameters are set """ # check for at least one filter criteria if not (self.programs or self.platforms or self.instrument_types or self.metadata_filters): raise AuroraXError("At least one filter criteria parameter besides 'start' and 'end' must be specified") # do request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_EPHEMERIS_SEARCH) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query, null_response=True) res = req.execute() # set request ID, request_url, executed self.executed = True if (res.status_code == 202): # request successfully dispatched self.executed = True self.request_url = res.request.headers["location"] self.request_id = self.request_url.rsplit("/", 1)[-1] # set the request variable self.request = res def update_status(self, status: Optional[Dict] = None) -> None: """ Update the status of this ephemeris search request Args: status (Dict): The previously-retrieved status of this request (include to avoid requesting it from the API again), defaults to None """ # get the status if it isn't passed in if (status is None): status = requests_get_status(self.__aurorax_obj, self.request_url) # check response if (status is None): raise AuroraXAPIError("Could not retrieve status for this request") # update request status by checking if data URI is set if (status["search_result"]["data_uri"] is not None): self.completed = True self.data_url = "%s/data" % (self.request_url) # set class variable "status" and "logs" self.status = status self.logs = status["logs"] def check_for_data(self) -> bool: """ Check to see if data is available for this ephemeris search request Returns: True if data is available, else False """ self.update_status() return self.completed def get_data(self) -> None: """ Retrieve the data available for this ephemeris search request """ # check if completed yet if (self.completed is False): print("No data available, update status or check for data first") return # get data raw_data = requests_get_data(self.__aurorax_obj, self.data_url, self.response_format, False) # set data variable if (self.response_format is not None): self.data = raw_data else: # cast data source objects for i in range(0, len(raw_data)): ds = DataSource(**raw_data[i]["data_source"], format=FORMAT_BASIC_INFO) raw_data[i]["data_source"] = ds # cast ephemeris objects self.data = [EphemerisData(**e) for e in raw_data] def wait(self, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> None: """ Block and wait for the request to complete and data is available for retrieval Args: poll_interval (float): Time in seconds to wait between polling attempts, defaults to 1 second verbose (bool): Output poll times and other progress messages, defaults to False """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_EPHEMERIS_REQUEST.format(self.request_id)) self.update_status(requests_wait_for_data(self.__aurorax_obj, url, poll_interval, verbose)) def cancel(self, wait: bool = False, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> int: """ Cancel the ephemeris search request This method returns immediately by default since the API processes this request asynchronously. If you would prefer to wait for it to be completed, set the 'wait' parameter to True. You can adjust the polling time using the 'poll_interval' parameter. Args: wait (bool): Wait until the cancellation request has been completed (may wait for several minutes) poll_interval (float): Seconds to wait between polling calls, defaults to 1 second verbose (bool): Output poll times and other progress messages, defaults to False Returns: 1 on success Raises: pyaurorax.exceptions.AuroraXUnauthorizedError: Invalid API key for this operation pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_EPHEMERIS_REQUEST.format(self.request_id)) return requests_cancel(self.__aurorax_obj, url, wait, poll_interval, verbose) def describe(self): """ Describe the ephemeris search as an "SQL-like" string. Returns: The "SQL-like" string describing the ephemeris search object """ # make request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DESCRIBE_EPHEMERIS_QUERY) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query) res = req.execute() # return return res.data
Class representing an ephemeris search
Note: At least one search criteria from programs, platforms, or instrument_types must be specified.
Attributes
start
:datetime.datetime
- Start timestamp of the search (inclusive)
end
:datetime.datetime
- End timestamp of the search (inclusive)
programs
:List[str]
- List of programs to search through, defaults to None
platforms
:List[str]
- List of platforms to search through, defaults to None
instrument_types
:List[str]
- List of instrument types to search through, defaults to None
metadata_filters
:MetadataFilter
orList[Dict]
- List of dictionaries describing metadata keys and values to filter on, defaults to None
metadata_filters_logical_operator
:str
- The logical operator to use when evaluating metadata filters (either
AND
orOR
), defaults toAND
response_format
:Dict
- JSON representation of desired data response format
request
:AuroraXResponse
- AuroraXResponse object returned when the search is executed
request_id
:str
- Unique ID assigned to the request by the AuroraX API
request_url
:str
-
Unique URL assigned to the request by the AuroraX API
executed (bool): Indicates if the search has been executed/started
completed (bool): Indicates if the search has finished
data_url (str): The URL where data is accessed
query (Dict): The query for this request as JSON
status (Dict): The status of the query
data (List[EphemerisData]): The ephemeris records found
logs (List[Dict]): All log messages outputted by the AuroraX API for this request
Instance variables
prop query
-
Expand source code
@property def query(self): """ Property for the query value """ # set metadata filter value if (self.metadata_filters is None): metadata_filters_dict = {} elif (isinstance(self.metadata_filters, MetadataFilter) is True): # metadata filter is a class metadata_filters_dict = self.metadata_filters.to_query_dict() # type: ignore else: # metadata filter is a dictionary metadata_filters_dict = { "expressions": self.metadata_filters, "logical_operator": self.metadata_filters_logical_operator, } # set query self.__query = { "data_sources": { "programs": [] if not self.programs else self.programs, "platforms": [] if not self.platforms else self.platforms, "instrument_types": [] if not self.instrument_types else self.instrument_types, "ephemeris_metadata_filters": metadata_filters_dict, }, "start": self.start.strftime("%Y-%m-%dT%H:%M:%S"), "end": self.end.strftime("%Y-%m-%dT%H:%M:%S"), } # return return self.__query
Property for the query value
Methods
def cancel(self, wait: bool = False, poll_interval: float = 1.0, verbose: bool = False) ‑> int
-
Expand source code
def cancel(self, wait: bool = False, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> int: """ Cancel the ephemeris search request This method returns immediately by default since the API processes this request asynchronously. If you would prefer to wait for it to be completed, set the 'wait' parameter to True. You can adjust the polling time using the 'poll_interval' parameter. Args: wait (bool): Wait until the cancellation request has been completed (may wait for several minutes) poll_interval (float): Seconds to wait between polling calls, defaults to 1 second verbose (bool): Output poll times and other progress messages, defaults to False Returns: 1 on success Raises: pyaurorax.exceptions.AuroraXUnauthorizedError: Invalid API key for this operation pyaurorax.exceptions.AuroraXAPIError: An API error was encountered """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_EPHEMERIS_REQUEST.format(self.request_id)) return requests_cancel(self.__aurorax_obj, url, wait, poll_interval, verbose)
Cancel the ephemeris search request
This method returns immediately by default since the API processes this request asynchronously. If you would prefer to wait for it to be completed, set the 'wait' parameter to True. You can adjust the polling time using the 'poll_interval' parameter.
Args
wait
:bool
- Wait until the cancellation request has been completed (may wait for several minutes)
poll_interval
:float
- Seconds to wait between polling calls, defaults to 1 second
verbose
:bool
- Output poll times and other progress messages, defaults to False
Returns
1 on success
Raises
AuroraXUnauthorizedError
- Invalid API key for this operation
AuroraXAPIError
- An API error was encountered
def check_for_data(self) ‑> bool
-
Expand source code
def check_for_data(self) -> bool: """ Check to see if data is available for this ephemeris search request Returns: True if data is available, else False """ self.update_status() return self.completed
Check to see if data is available for this ephemeris search request
Returns
True if data is available, else False
def describe(self)
-
Expand source code
def describe(self): """ Describe the ephemeris search as an "SQL-like" string. Returns: The "SQL-like" string describing the ephemeris search object """ # make request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_DESCRIBE_EPHEMERIS_QUERY) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query) res = req.execute() # return return res.data
Describe the ephemeris search as an "SQL-like" string.
Returns
The "SQL-like" string describing the ephemeris search object
def execute(self) ‑> None
-
Expand source code
def execute(self) -> None: """ Initiate ephemeris search request Raises: pyaurorax.exceptions.AuroraXError: Invalid request parameters are set """ # check for at least one filter criteria if not (self.programs or self.platforms or self.instrument_types or self.metadata_filters): raise AuroraXError("At least one filter criteria parameter besides 'start' and 'end' must be specified") # do request url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_EPHEMERIS_SEARCH) req = AuroraXAPIRequest(self.__aurorax_obj, method="post", url=url, body=self.query, null_response=True) res = req.execute() # set request ID, request_url, executed self.executed = True if (res.status_code == 202): # request successfully dispatched self.executed = True self.request_url = res.request.headers["location"] self.request_id = self.request_url.rsplit("/", 1)[-1] # set the request variable self.request = res
def get_data(self) ‑> None
-
Expand source code
def get_data(self) -> None: """ Retrieve the data available for this ephemeris search request """ # check if completed yet if (self.completed is False): print("No data available, update status or check for data first") return # get data raw_data = requests_get_data(self.__aurorax_obj, self.data_url, self.response_format, False) # set data variable if (self.response_format is not None): self.data = raw_data else: # cast data source objects for i in range(0, len(raw_data)): ds = DataSource(**raw_data[i]["data_source"], format=FORMAT_BASIC_INFO) raw_data[i]["data_source"] = ds # cast ephemeris objects self.data = [EphemerisData(**e) for e in raw_data]
Retrieve the data available for this ephemeris search request
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # set status and query strings max_len = 80 status_str = str(self.status) query_str = str(self.query) if (len(status_str) > max_len): status_str = "%s..." % (status_str[0:max_len]) if (len(query_str) > max_len): query_str = "%s..." % (query_str[0:max_len]) # set results string if (self.executed is True): if (len(self.data) == 0): data_str = "[0 ephemeris results]" elif (len(self.data) == 1): data_str = "[1 ephemeris result]" else: data_str = "[%d ephemeris results]" % (len(self.data)) else: data_str = "" # set logs string if (self.executed is True): if (len(self.logs) == 0): logs_str = "[0 log messages]" elif (len(self.logs) == 1): logs_str = "[1 log message]" else: logs_str = "[%d log messages]" % (len(self.logs)) else: logs_str = "" # print print("EphemerisSearch:") print(" %-13s: %s" % ("executed", self.executed)) print(" %-13s: %s" % ("completed", self.completed)) print(" %-13s: %s" % ("request_id", self.request_id)) print(" %-13s: %s" % ("request", self.request)) print(" %-13s: %s" % ("request_url", self.request_url)) print(" %-13s: %s" % ("data_url", self.data_url)) print(" %-13s: %s" % ("query", query_str)) print(" %-13s: %s" % ("status", status_str)) print(" %-13s: %s" % ("data", data_str)) print(" %-13s: %s" % ("logs", logs_str))
A special print output for this class.
def update_status(self, status: Optional[Dict] = None) ‑> None
-
Expand source code
def update_status(self, status: Optional[Dict] = None) -> None: """ Update the status of this ephemeris search request Args: status (Dict): The previously-retrieved status of this request (include to avoid requesting it from the API again), defaults to None """ # get the status if it isn't passed in if (status is None): status = requests_get_status(self.__aurorax_obj, self.request_url) # check response if (status is None): raise AuroraXAPIError("Could not retrieve status for this request") # update request status by checking if data URI is set if (status["search_result"]["data_uri"] is not None): self.completed = True self.data_url = "%s/data" % (self.request_url) # set class variable "status" and "logs" self.status = status self.logs = status["logs"]
Update the status of this ephemeris search request
Args
status
:Dict
- The previously-retrieved status of this request (include to avoid requesting it from the API again), defaults to None
def wait(self, poll_interval: float = 1.0, verbose: bool = False) ‑> None
-
Expand source code
def wait(self, poll_interval: float = __STANDARD_POLLING_SLEEP_TIME, verbose: bool = False) -> None: """ Block and wait for the request to complete and data is available for retrieval Args: poll_interval (float): Time in seconds to wait between polling attempts, defaults to 1 second verbose (bool): Output poll times and other progress messages, defaults to False """ url = "%s/%s" % (self.__aurorax_obj.api_base_url, self.__aurorax_obj.search.api.URL_SUFFIX_EPHEMERIS_REQUEST.format(self.request_id)) self.update_status(requests_wait_for_data(self.__aurorax_obj, url, poll_interval, verbose))
Block and wait for the request to complete and data is available for retrieval
Args
poll_interval
:float
- Time in seconds to wait between polling attempts, defaults to 1 second
verbose
:bool
- Output poll times and other progress messages, defaults to False
class EventsCriteriaBlock (platforms: List[str] = [],
instrument_types: List[str] = [],
metadata_filters: MetadataFilter | None = None)-
Expand source code
class EventsCriteriaBlock: """ Representation of a event criteria block used for conjunction searches. Attributes: platforms (List[str]): List of platform strings to use in this criteria block. Optional, default is `[]`. instrument_types (List[str]): List of instrument type strings to use in this criteria block. Optional, default is `[]`. metadata_filters (MetadataFilter): The metadata filters to use in this criteria block. Optional, default is None. """ def __init__(self, platforms: List[str] = [], instrument_types: List[str] = [], metadata_filters: Optional[MetadataFilter] = None): self.platforms = platforms self.instrument_types = instrument_types self.metadata_filters = metadata_filters def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: return "EventsCriteriaBlock(platforms=%s, instrument_types=%s, metadata_filters=%s)" % ( self.platforms, self.instrument_types, self.metadata_filters, ) def pretty_print(self): """ A special print output for this class. """ # set special strings max_len = 80 metadata_filters_str = str(self.metadata_filters) if (len(metadata_filters_str) > max_len): metadata_filters_str = "%s...)" % (metadata_filters_str[0:max_len]) # print print("EventsCriteriaBlock:") print(" %-18s: %s" % ("platforms", self.platforms)) print(" %-18s: %s" % ("instrument_types", self.instrument_types)) print(" %-18s: %s" % ("metadata_filters", metadata_filters_str))
Representation of a event criteria block used for conjunction searches.
Attributes
platforms
:List[str]
- List of platform strings to use in this criteria block. Optional, default is
[]
. instrument_types
:List[str]
- List of instrument type strings to use in this criteria block. Optional, default is
[]
. metadata_filters
:MetadataFilter
- The metadata filters to use in this criteria block. Optional, default is None.
Methods
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # set special strings max_len = 80 metadata_filters_str = str(self.metadata_filters) if (len(metadata_filters_str) > max_len): metadata_filters_str = "%s...)" % (metadata_filters_str[0:max_len]) # print print("EventsCriteriaBlock:") print(" %-18s: %s" % ("platforms", self.platforms)) print(" %-18s: %s" % ("instrument_types", self.instrument_types)) print(" %-18s: %s" % ("metadata_filters", metadata_filters_str))
A special print output for this class.
class GroundCriteriaBlock (programs: List[str] = [],
platforms: List[str] = [],
instrument_types: List[str] = [],
metadata_filters: MetadataFilter | None = None)-
Expand source code
class GroundCriteriaBlock: """ Representation of a ground criteria block used for conjunction searches. Attributes: programs (List[str]): List of program strings to use in this criteria block. Optional, default is `[]`. platforms (List[str]): List of platform strings to use in this criteria block. Optional, default is `[]`. instrument_types (List[str]): List of instrument type strings to use in this criteria block. Optional, default is `[]`. metadata_filters (MetadataFilter): The metadata filters to use in this criteria block. Optional, default is None. """ def __init__(self, programs: List[str] = [], platforms: List[str] = [], instrument_types: List[str] = [], metadata_filters: Optional[MetadataFilter] = None): self.programs = programs self.platforms = platforms self.instrument_types = instrument_types self.metadata_filters = metadata_filters def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: return "GroundCriteriaBlock(programs=%s, platforms=%s, instrument_types=%s, metadata_filters=%s)" % ( self.programs, self.platforms, self.instrument_types, self.metadata_filters, ) def pretty_print(self): """ A special print output for this class. """ # set special strings max_len = 80 metadata_filters_str = str(self.metadata_filters) if (len(metadata_filters_str) > max_len): metadata_filters_str = "%s...)" % (metadata_filters_str[0:max_len]) # print print("GroundCriteriaBlock:") print(" %-18s: %s" % ("programs", self.programs)) print(" %-18s: %s" % ("platforms", self.platforms)) print(" %-18s: %s" % ("instrument_types", self.instrument_types)) print(" %-18s: %s" % ("metadata_filters", metadata_filters_str))
Representation of a ground criteria block used for conjunction searches.
Attributes
programs
:List[str]
- List of program strings to use in this criteria block. Optional, default is
[]
. platforms
:List[str]
- List of platform strings to use in this criteria block. Optional, default is
[]
. instrument_types
:List[str]
- List of instrument type strings to use in this criteria block. Optional, default is
[]
. metadata_filters
:MetadataFilter
- The metadata filters to use in this criteria block. Optional, default is None.
Methods
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # set special strings max_len = 80 metadata_filters_str = str(self.metadata_filters) if (len(metadata_filters_str) > max_len): metadata_filters_str = "%s...)" % (metadata_filters_str[0:max_len]) # print print("GroundCriteriaBlock:") print(" %-18s: %s" % ("programs", self.programs)) print(" %-18s: %s" % ("platforms", self.platforms)) print(" %-18s: %s" % ("instrument_types", self.instrument_types)) print(" %-18s: %s" % ("metadata_filters", metadata_filters_str))
A special print output for this class.
class Location (lat: float | None = None, lon: float | None = None)
-
Expand source code
class Location: """ Representation for an AuroraX search engine location. This data can be in geodetic coordinates, GSM coordinates, or geodetic northern/southern B-trace magnetic footprints. Latitude and longitude values are in decimal degrees format, ranging from -90 to 90 for latitude and -180 to 180 for longitude. Note that latitude and longitude must both be numbers, or both be None. Attributes: lat (float): latitude value lon (float): longitude value Raises: ValueError: if both latitude and longitude are not real numbers, or not both None. """ def __init__(self, lat: Optional[float] = None, lon: Optional[float] = None): if (lat is None and lon is not None) or (lat is not None and lon is None): # one of them is None, not allowed raise ValueError("Latitude and longitude must both be numbers, or both be None") self.__lat = lat self.__lon = lon @property def lat(self): return self.__lat @lat.setter def lat(self, value: float): if (self.__lon is None and value is not None) or (self.__lon is not None and value is None): # one of them is None, not allowed raise ValueError("Latitude and longitude must both be numbers, or both be None") self.__lat = value @property def lon(self): return self.__lon @lon.setter def lon(self, value: float): if (self.__lat is None and value is not None) or (self.__lat is not None and value is None): # one of them is None, not allowed raise ValueError("Latitude and longitude must both be numbers, or both be None") self.__lon = value def to_json_serializable(self) -> Dict: """ Convert object to a JSON-serializable object (ie. translate datetime objects to strings) Returns: a dictionary object that is JSON-serializable """ return {"lat": self.lat, "lon": self.lon} def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: return "%s(lat=%s, lon=%s)" % (self.__class__.__name__, str(self.lat), str(self.lon))
Representation for an AuroraX search engine location. This data can be in geodetic coordinates, GSM coordinates, or geodetic northern/southern B-trace magnetic footprints.
Latitude and longitude values are in decimal degrees format, ranging from -90 to 90 for latitude and -180 to 180 for longitude.
Note that latitude and longitude must both be numbers, or both be None.
Attributes
lat
:float
- latitude value
lon
:float
- longitude value
Raises
ValueError
- if both latitude and longitude are not real numbers, or not both None.
Instance variables
prop lat
-
Expand source code
@property def lat(self): return self.__lat
prop lon
-
Expand source code
@property def lon(self): return self.__lon
Methods
def to_json_serializable(self) ‑> Dict
-
Expand source code
def to_json_serializable(self) -> Dict: """ Convert object to a JSON-serializable object (ie. translate datetime objects to strings) Returns: a dictionary object that is JSON-serializable """ return {"lat": self.lat, "lon": self.lon}
Convert object to a JSON-serializable object (ie. translate datetime objects to strings)
Returns
a dictionary object that is JSON-serializable
class MetadataFilter (expressions: List[MetadataFilterExpression],
operator: Literal['and', 'or', 'AND', 'OR'] = 'and')-
Expand source code
class MetadataFilter: """ Representation for an AuroraX search engine metadata filter. These are used as part of conjunction, ephemeris, and data product searching. Attributes: expressions (List[MetadataFilterExpression]): The list of metadata filter expressions for use with conjunction, ephemeris, and data product searches. operator (str): The logical operator to use when the search engine will evaluate multiple expressions. If not supplied, the search engine will perform a logical 'AND' between each expression. Possible choices are 'and' or 'or'. Raises: pyaurorax.exceptions.AuroraXError: if invalid operator was specified. """ def __init__( self, expressions: List[MetadataFilterExpression], operator: Literal["and", "or", "AND", "OR"] = "and", ): self.expressions = expressions self.__operator = operator @property def operator(self): return self.__operator @operator.setter def operator(self, val: Literal["and", "or", "AND", "OR"] = "and"): if (val.lower() not in ["and", "or"]): AuroraXError("Operator '%s' not allowed. You must use one of the following: ['and', 'or']" % (val)) self.__operator = val.lower() def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: # set special strings if (len(self.expressions) == 0): expressions_str = "[0 expressions]" elif (len(self.expressions) == 1): expressions_str = "[1 expression]" else: expressions_str = "[%d expressions]" % (len(self.expressions)) # return return "MetadataFilter(expressions=%s, operator='%s')" % (expressions_str, self.operator) def pretty_print(self): """ A special print output for this class. """ # set special strings if (len(self.expressions) == 0): expressions_str = "[0 expressions]" elif (len(self.expressions) == 1): expressions_str = "[1 expression]" else: expressions_str = "[%d expressions]" % (len(self.expressions)) # print print("MetadataFilter:") print(" %-13s: %s" % ("expressions", expressions_str)) print(" %-13s: %s" % ("operator", self.operator)) def to_query_dict(self): """ Convert the expression object to a dictionary that will be used when executing a search. """ return { "expressions": [x.to_query_dict() for x in self.expressions], "logical_operator": self.operator.upper(), }
Representation for an AuroraX search engine metadata filter. These are used as part of conjunction, ephemeris, and data product searching.
Attributes
expressions
:List[MetadataFilterExpression]
- The list of metadata filter expressions for use with conjunction, ephemeris, and data product searches.
operator
:str
- The logical operator to use when the search engine will evaluate multiple expressions. If not supplied, the search engine will perform a logical 'AND' between each expression. Possible choices are 'and' or 'or'.
Raises
AuroraXError
- if invalid operator was specified.
Instance variables
prop operator
-
Expand source code
@property def operator(self): return self.__operator
Methods
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # set special strings if (len(self.expressions) == 0): expressions_str = "[0 expressions]" elif (len(self.expressions) == 1): expressions_str = "[1 expression]" else: expressions_str = "[%d expressions]" % (len(self.expressions)) # print print("MetadataFilter:") print(" %-13s: %s" % ("expressions", expressions_str)) print(" %-13s: %s" % ("operator", self.operator))
A special print output for this class.
def to_query_dict(self)
-
Expand source code
def to_query_dict(self): """ Convert the expression object to a dictionary that will be used when executing a search. """ return { "expressions": [x.to_query_dict() for x in self.expressions], "logical_operator": self.operator.upper(), }
Convert the expression object to a dictionary that will be used when executing a search.
class MetadataFilterExpression (key: str,
values: Any | List[Any],
operator: Literal['=', '!=', '>', '<', '>=', '<=', 'between', 'in', 'not in'] = 'in')-
Expand source code
class MetadataFilterExpression: """ Representation for an AuroraX search engine metadata filter expression. These are used as part of conjunction, ephemeris, and data product searching. Attributes: key (str): The special key for the metadata filter. For example, 'nbtrace_region'. values (Any or List[Any]): The value(s) that the search will use when filtering. This can either be a single value, or a list of values. operator (str): The operator to use when the search engine evaluates the expression. Valid choices are: "=", "!=", ">", "<", ">=", "<=", "between", "in", "not in". The "in" and "not in" operators are meant exclusively for expressions where there are multiple values (ie. the values parameter is a list of strings). Raises: pyaurorax.exceptions.AuroraXError: if invalid operator was specified. """ def __init__( self, key: str, values: Union[Any, List[Any]], operator: Literal["=", "!=", ">", "<", ">=", "<=", "between", "in", "not in"] = "in", ): # set required parameters self.key = key self.values = values self.__operator = operator @property def operator(self) -> str: return self.__operator @operator.setter def operator(self, val: Literal["=", "!=", ">", "<", ">=", "<=", "between", "in", "not in"]): if (val not in ["=", "!=", ">", "<", ">=", "<=", "between", "in", "not in"]): AuroraXError("Operator '%s' not allowed. You must use one of the following: ['=', '!=', '>', '<', " + "'>=', '<=', 'between', 'in', 'not in']" % (val)) self.__operator = val def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: # set special strings values_str = "'%s'" % (self.values) if (type(self.values) is list): values_str = str(self.values) # return return "MetadataFilterExpression(key='%s', values=%s, operator='%s')" % (self.key, values_str, self.operator) def pretty_print(self): """ A special print output for this class. """ # print print("MetadataFilterExpression:") print(" %-10s: %s" % ("key", self.key)) print(" %-10s: %s" % ("values", self.values)) print(" %-10s: %s" % ("operator", self.operator)) def to_query_dict(self): """ Convert the expression object to a dictionary that will be used when executing a search. """ return { "key": str(self.key), "values": [str(self.values)] if type(self.values) is not list else self.values, "operator": str(self.operator), }
Representation for an AuroraX search engine metadata filter expression. These are used as part of conjunction, ephemeris, and data product searching.
Attributes
key
:str
- The special key for the metadata filter. For example, 'nbtrace_region'.
values
:Any
orList[Any]
- The value(s) that the search will use when filtering. This can either be a single value, or a list of values.
operator
:str
-
The operator to use when the search engine evaluates the expression. Valid choices are: "=", "!=", ">", "<", ">=", "<=", "between", "in", "not in".
The "in" and "not in" operators are meant exclusively for expressions where there are multiple values (ie. the values parameter is a list of strings).
Raises
AuroraXError
- if invalid operator was specified.
Instance variables
prop operator : str
-
Expand source code
@property def operator(self) -> str: return self.__operator
Methods
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # print print("MetadataFilterExpression:") print(" %-10s: %s" % ("key", self.key)) print(" %-10s: %s" % ("values", self.values)) print(" %-10s: %s" % ("operator", self.operator))
A special print output for this class.
def to_query_dict(self)
-
Expand source code
def to_query_dict(self): """ Convert the expression object to a dictionary that will be used when executing a search. """ return { "key": str(self.key), "values": [str(self.values)] if type(self.values) is not list else self.values, "operator": str(self.operator), }
Convert the expression object to a dictionary that will be used when executing a search.
class SearchManager (aurorax_obj)
-
Expand source code
class SearchManager: """ The SearchManager object is initialized within every PyAuroraX object. It acts as a way to access the submodules and carry over configuration information in the super class. """ def __init__(self, aurorax_obj): self.__aurorax_obj = aurorax_obj # initialize sub-modules self.__util = UtilManager() self.__api = module_api self.__sources = SourcesManager(self.__aurorax_obj) self.__availability = AvailabilityManager(self.__aurorax_obj) self.__metadata = MetadataManager(self.__aurorax_obj) self.__requests = RequestsManager(self.__aurorax_obj) self.__ephemeris = EphemerisManager(self.__aurorax_obj) self.__data_products = DataProductsManager(self.__aurorax_obj) self.__conjunctions = ConjunctionsManager(self.__aurorax_obj) # initialize class vars self.DataSource = DataSource self.Location = Location self.MetadataFilter = MetadataFilter self.MetadataFilterExpression = MetadataFilterExpression self.GroundCriteriaBlock = GroundCriteriaBlock self.SpaceCriteriaBlock = SpaceCriteriaBlock self.EventsCriteriaBlock = EventsCriteriaBlock self.CustomLocationsCriteriaBlock = CustomLocationsCriteriaBlock self.ConjunctionSearch = ConjunctionSearch self.EphemerisSearch = EphemerisSearch self.DataProductSearch = DataProductSearch self.EphemerisData = EphemerisData self.DataProductData = DataProductData # initialize static vars self.FORMAT_BASIC_INFO = FORMAT_BASIC_INFO self.FORMAT_BASIC_INFO_WITH_METADATA = FORMAT_BASIC_INFO_WITH_METADATA self.FORMAT_FULL_RECORD = FORMAT_FULL_RECORD self.FORMAT_IDENTIFIER_ONLY = FORMAT_IDENTIFIER_ONLY self.FORMAT_DEFAULT = FORMAT_DEFAULT self.SOURCE_TYPE_EVENT_LIST = SOURCE_TYPE_EVENT_LIST self.SOURCE_TYPE_GROUND = SOURCE_TYPE_GROUND self.SOURCE_TYPE_HEO = SOURCE_TYPE_HEO self.SOURCE_TYPE_LEO = SOURCE_TYPE_LEO self.SOURCE_TYPE_LUNAR = SOURCE_TYPE_LUNAR self.DATA_PRODUCT_TYPE_KEOGRAM = DATA_PRODUCT_TYPE_KEOGRAM self.DATA_PRODUCT_TYPE_MONTAGE = DATA_PRODUCT_TYPE_MONTAGE self.DATA_PRODUCT_TYPE_MOVIE = DATA_PRODUCT_TYPE_MOVIE self.DATA_PRODUCT_TYPE_SUMMARY_PLOT = DATA_PRODUCT_TYPE_SUMMARY_PLOT self.DATA_PRODUCT_TYPE_DATA_AVAILABILITY = DATA_PRODUCT_TYPE_DATA_AVAILABILITY self.CONJUNCTION_TYPE_NBTRACE = CONJUNCTION_TYPE_NBTRACE self.CONJUNCTION_TYPE_SBTRACE = CONJUNCTION_TYPE_SBTRACE # ------------------------------------------ # properties for submodule managers # ------------------------------------------ @property def util(self): """ Access to the `util` submodule from within a PyAuroraX object. """ return self.__util @property def api(self): """ Access to the `api` submodule from within a PyAuroraX object. """ return self.__api @property def sources(self): """ Access to the `sources` submodule from within a PyAuroraX object. """ return self.__sources @property def availability(self): """ Access to the `availability` submodule from within a PyAuroraX object. """ return self.__availability @property def metadata(self): """ Access to the `metadata` submodule from within a PyAuroraX object. """ return self.__metadata @property def requests(self): """ Access to the `requests` submodule from within a PyAuroraX object. """ return self.__requests @property def ephemeris(self): """ Access to the `ephemeris` submodule from within a PyAuroraX object. """ return self.__ephemeris @property def data_products(self): """ Access to the `data_products` submodule from within a PyAuroraX object. """ return self.__data_products @property def conjunctions(self): """ Access to the `conjunctions` submodule from within a PyAuroraX object. """ return self.__conjunctions
The SearchManager object is initialized within every PyAuroraX object. It acts as a way to access the submodules and carry over configuration information in the super class.
Instance variables
prop api
-
Expand source code
@property def api(self): """ Access to the `api` submodule from within a PyAuroraX object. """ return self.__api
Access to the
pyaurorax.search.api
submodule from within a PyAuroraX object. prop availability
-
Expand source code
@property def availability(self): """ Access to the `availability` submodule from within a PyAuroraX object. """ return self.__availability
Access to the
pyaurorax.search.availability
submodule from within a PyAuroraX object. prop conjunctions
-
Expand source code
@property def conjunctions(self): """ Access to the `conjunctions` submodule from within a PyAuroraX object. """ return self.__conjunctions
Access to the
pyaurorax.search.conjunctions
submodule from within a PyAuroraX object. prop data_products
-
Expand source code
@property def data_products(self): """ Access to the `data_products` submodule from within a PyAuroraX object. """ return self.__data_products
Access to the
pyaurorax.search.data_products
submodule from within a PyAuroraX object. prop ephemeris
-
Expand source code
@property def ephemeris(self): """ Access to the `ephemeris` submodule from within a PyAuroraX object. """ return self.__ephemeris
Access to the
pyaurorax.search.ephemeris
submodule from within a PyAuroraX object. prop metadata
-
Expand source code
@property def metadata(self): """ Access to the `metadata` submodule from within a PyAuroraX object. """ return self.__metadata
Access to the
pyaurorax.search.metadata
submodule from within a PyAuroraX object. prop requests
-
Expand source code
@property def requests(self): """ Access to the `requests` submodule from within a PyAuroraX object. """ return self.__requests
Access to the
pyaurorax.search.requests
submodule from within a PyAuroraX object. prop sources
-
Expand source code
@property def sources(self): """ Access to the `sources` submodule from within a PyAuroraX object. """ return self.__sources
Access to the
pyaurorax.search.sources
submodule from within a PyAuroraX object. prop util
-
Expand source code
@property def util(self): """ Access to the `util` submodule from within a PyAuroraX object. """ return self.__util
Access to the
pyaurorax.search.util
submodule from within a PyAuroraX object.
class SpaceCriteriaBlock (programs: List[str] = [],
platforms: List[str] = [],
instrument_types: List[str] = [],
hemisphere: List[Literal['northern', 'southern']] = [],
metadata_filters: MetadataFilter | None = None)-
Expand source code
class SpaceCriteriaBlock: """ Representation of a space criteria block used for conjunction searches. Attributes: programs (List[str]): List of program strings to use in this criteria block. Optional, default is `[]`. platforms (List[str]): List of platform strings to use in this criteria block. Optional, default is `[]`. instrument_types (List[str]): List of instrument type strings to use in this criteria block. Optional, default is `[]`. hemisphere (List[str]): List of hemisphere strings to use in this criteria block. Valid values are 'northern' or 'southern'. Optional, default is `[]`. metadata_filters (MetadataFilter): The metadata filters to use in this criteria block. Optional, default is None. """ def __init__(self, programs: List[str] = [], platforms: List[str] = [], instrument_types: List[str] = [], hemisphere: List[Literal["northern", "southern"]] = [], metadata_filters: Optional[MetadataFilter] = None): self.programs = programs self.platforms = platforms self.instrument_types = instrument_types self.hemisphere = hemisphere self.metadata_filters = metadata_filters def __str__(self) -> str: return self.__repr__() def __repr__(self) -> str: return "SpaceCriteriaBlock(programs=%s, platforms=%s, instrument_types=%s, hemisphere=%s, metadata_filters=%s)" % ( self.programs, self.platforms, self.instrument_types, self.hemisphere, self.metadata_filters, ) def pretty_print(self): """ A special print output for this class. """ # set special strings max_len = 80 metadata_filters_str = str(self.metadata_filters) if (len(metadata_filters_str) > max_len): metadata_filters_str = "%s...)" % (metadata_filters_str[0:max_len]) # print print("SpaceCriteriaBlock:") print(" %-18s: %s" % ("programs", self.programs)) print(" %-18s: %s" % ("platforms", self.platforms)) print(" %-18s: %s" % ("instrument_types", self.instrument_types)) print(" %-18s: %s" % ("hemisphere", self.hemisphere)) print(" %-18s: %s" % ("metadata_filters", metadata_filters_str)) def to_search_query_dict(self): query_dict = self.__dict__ query_dict["ephemeris_metadata_filters"] = None if self.metadata_filters is None else self.metadata_filters.__dict__ del query_dict["metadata_filters"] return query_dict
Representation of a space criteria block used for conjunction searches.
Attributes
programs
:List[str]
- List of program strings to use in this criteria block. Optional, default is
[]
. platforms
:List[str]
- List of platform strings to use in this criteria block. Optional, default is
[]
. instrument_types
:List[str]
- List of instrument type strings to use in this criteria block. Optional, default is
[]
. hemisphere
:List[str]
- List of hemisphere strings to use in this criteria block. Valid values are 'northern'
or 'southern'. Optional, default is
[]
. metadata_filters
:MetadataFilter
- The metadata filters to use in this criteria block. Optional, default is None.
Methods
def pretty_print(self)
-
Expand source code
def pretty_print(self): """ A special print output for this class. """ # set special strings max_len = 80 metadata_filters_str = str(self.metadata_filters) if (len(metadata_filters_str) > max_len): metadata_filters_str = "%s...)" % (metadata_filters_str[0:max_len]) # print print("SpaceCriteriaBlock:") print(" %-18s: %s" % ("programs", self.programs)) print(" %-18s: %s" % ("platforms", self.platforms)) print(" %-18s: %s" % ("instrument_types", self.instrument_types)) print(" %-18s: %s" % ("hemisphere", self.hemisphere)) print(" %-18s: %s" % ("metadata_filters", metadata_filters_str))
A special print output for this class.
def to_search_query_dict(self)
-
Expand source code
def to_search_query_dict(self): query_dict = self.__dict__ query_dict["ephemeris_metadata_filters"] = None if self.metadata_filters is None else self.metadata_filters.__dict__ del query_dict["metadata_filters"] return query_dict