From ee68f33ddf631b9a5f2b55ce40cf25127525a341 Mon Sep 17 00:00:00 2001 From: akash5100 Date: Thu, 14 Jul 2022 12:07:12 +0530 Subject: [PATCH 1/5] adds getClosestImage endpoint --- hvpy/api_groups/official_clients/__init__.py | 0 .../official_clients/get_closest_image.py | 41 +++++++++++++++++++ .../official_clients/tests/__init__.py | 0 .../tests/test_get_closest_image.py | 29 +++++++++++++ hvpy/facade.py | 30 +++++++++++++- hvpy/parameters.py | 2 + 6 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 hvpy/api_groups/official_clients/__init__.py create mode 100644 hvpy/api_groups/official_clients/get_closest_image.py create mode 100644 hvpy/api_groups/official_clients/tests/__init__.py create mode 100644 hvpy/api_groups/official_clients/tests/test_get_closest_image.py diff --git a/hvpy/api_groups/official_clients/__init__.py b/hvpy/api_groups/official_clients/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hvpy/api_groups/official_clients/get_closest_image.py b/hvpy/api_groups/official_clients/get_closest_image.py new file mode 100644 index 0000000..7887eb9 --- /dev/null +++ b/hvpy/api_groups/official_clients/get_closest_image.py @@ -0,0 +1,41 @@ +from typing import Optional +from datetime import datetime + +from pydantic import validator + +from hvpy.io import HvpyParameters, OutputType +from hvpy.utils import convert_date_to_isoformat + + +class getClosestImageInputParameters(HvpyParameters): + """ + Handles the input parameters of the getClosestImage API. + + Attributes + ---------- + {Shared} + date : datetime.datetime + Date and time of the image. + sourceId : int + Unique image datasource identifier. + callback : str, optional + Wrap the response object in a function call of your choosing. + + References + ---------- + * ``__ + {Shared} + """ + + date: datetime + sourceId: int + callback: Optional[str] = None + _date_validator = validator("date", allow_reuse=True)(convert_date_to_isoformat) + + def get_output_type(self) -> OutputType: + """ + Returns the output type of the API call. + """ + if self.callback is None: + return OutputType.JSON + return OutputType.STRING diff --git a/hvpy/api_groups/official_clients/tests/__init__.py b/hvpy/api_groups/official_clients/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hvpy/api_groups/official_clients/tests/test_get_closest_image.py b/hvpy/api_groups/official_clients/tests/test_get_closest_image.py new file mode 100644 index 0000000..9772666 --- /dev/null +++ b/hvpy/api_groups/official_clients/tests/test_get_closest_image.py @@ -0,0 +1,29 @@ +from datetime import datetime + +import pytest + +from hvpy import getClosestImage +from hvpy.api_groups.official_clients.get_closest_image import getClosestImageInputParameters + + +def test_json_res(): + response = getClosestImage(date=datetime(2014, 1, 1, 23, 59, 59), sourceId=14) + assert isinstance(response, dict) + + +def test_str_res(): + response = getClosestImage(date=datetime(2014, 1, 1, 23, 59, 59), sourceId=14, callback="callback") + assert isinstance(response, str) + assert response.startswith("callback") + + +def test_error_handling(): + with pytest.raises(TypeError, match="missing 1 required positional argument: 'date'"): + getClosestImage(sourceId=14) + with pytest.raises(TypeError, match="missing 1 required positional argument: 'sourceId'"): + getClosestImage(date=datetime(2014, 1, 1, 23, 59, 59)) + + +def test_url_property(): + params = getClosestImageInputParameters(date=datetime(2014, 1, 1, 23, 59, 59), sourceId=14) + assert params.url == "https://api.helioviewer.org/v2/getClosestImage/" diff --git a/hvpy/facade.py b/hvpy/facade.py index d1bb74c..d5a6835 100644 --- a/hvpy/facade.py +++ b/hvpy/facade.py @@ -5,7 +5,7 @@ from hvpy.parameters import * from hvpy.utils import add_shared_docstring -__all__ = ["getJP2Image", "getJP2Header", "getJPXClosestToMidPoint", "getJPX", "getStatus"] +__all__ = ["getJP2Image", "getJP2Header", "getJPXClosestToMidPoint", "getJPX", "getStatus", "getClosestImage"] @add_shared_docstring(getJP2ImageInputParameters) @@ -146,3 +146,31 @@ def getStatus() -> Union[bytes, str, Dict[str, Any]]: """ params = getStatusInputParameters() return execute_api_call(input_parameters=params) + + +@add_shared_docstring(getClosestImageInputParameters) +def getClosestImage( + date: datetime, + sourceId: int, + callback: Optional[str] = None, +) -> Union[bytes, str, Dict[str, Any]]: + """ + Find the image data that is closest to the requested date/time. Return the + associated metadata from the helioviewer database and the XML header of the + JPEG2000 image file. + + Parameters + ---------- + {Insert} + Examples + -------- + >>> from datetime import datetime + >>> from hvpy import getClosestImage + >>> getClosestImage( + ... date=datetime(2014,1,1,23,59,59), + ... sourceId=14, + ... ) + {'id': '32271665', 'date': '2014-01-02 00:00:03', 'name': 'AIA 335', 'scale': 0.5899606831770233, 'width': 4096, 'height': 4096, 'refPixelX': 2048.5, 'refPixelY': 2048.5, 'sunCenterOffsetParams': [], 'layeringOrder': 1} + """ + params = getClosestImageInputParameters(date=date, sourceId=sourceId, callback=callback) + return execute_api_call(input_parameters=params) diff --git a/hvpy/parameters.py b/hvpy/parameters.py index a192a3e..2a6cee2 100644 --- a/hvpy/parameters.py +++ b/hvpy/parameters.py @@ -3,6 +3,7 @@ from hvpy.api_groups.jpeg2000.get_jpx import getJPXInputParameters from hvpy.api_groups.jpeg2000.get_jpx_closest_to_mid_point import getJPXClosestToMidPointInputParameters from hvpy.api_groups.jpeg2000.get_status import getStatusInputParameters +from hvpy.api_groups.official_clients.get_closest_image import getClosestImageInputParameters __all__ = [ "getJP2ImageInputParameters", @@ -10,4 +11,5 @@ "getJPXClosestToMidPointInputParameters", "getJPXInputParameters", "getStatusInputParameters", + "getClosestImageInputParameters", ] From dd0c0f6272a28031fe7ed842961231eb9d164902 Mon Sep 17 00:00:00 2001 From: akash5100 Date: Thu, 14 Jul 2022 13:19:52 +0530 Subject: [PATCH 2/5] adds getDataSources endpoint --- hvpy/api_groups/official_clients/__init__.py | 0 .../official_clients/get_data_sources.py | 37 +++++++++++++++++++ .../official_clients/tests/__init__.py | 0 .../tests/test_get_data_sources.py | 17 +++++++++ hvpy/facade.py | 28 +++++++++++++- hvpy/parameters.py | 2 + 6 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 hvpy/api_groups/official_clients/__init__.py create mode 100644 hvpy/api_groups/official_clients/get_data_sources.py create mode 100644 hvpy/api_groups/official_clients/tests/__init__.py create mode 100644 hvpy/api_groups/official_clients/tests/test_get_data_sources.py diff --git a/hvpy/api_groups/official_clients/__init__.py b/hvpy/api_groups/official_clients/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hvpy/api_groups/official_clients/get_data_sources.py b/hvpy/api_groups/official_clients/get_data_sources.py new file mode 100644 index 0000000..920e8da --- /dev/null +++ b/hvpy/api_groups/official_clients/get_data_sources.py @@ -0,0 +1,37 @@ +from typing import Optional + +from hvpy.io import HvpyParameters, OutputType + + +class getDataSourcesInputParameters(HvpyParameters): + """ + Handles the input parameters of the getDataSources API. + + Attributes + ---------- + {Shared} + verbose : bool, optional + Output the hierarchical list of available datasources in a format that is compatible with the JHelioviewer desktop client + enable : str, optional + Comma-separated list of observatories to enable. + callback : str, optional + Wrap the response object in a function call of your choosing. + + References + ---------- + * ``__ + {Shared} + """ + + verbose: Optional[bool] = False + enable: Optional[str] = None + callback: Optional[str] = None + + def get_output_type(self) -> OutputType: + """ + Returns the output type of the API call. + """ + if self.callback: + return OutputType.STRING + else: + return OutputType.JSON diff --git a/hvpy/api_groups/official_clients/tests/__init__.py b/hvpy/api_groups/official_clients/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hvpy/api_groups/official_clients/tests/test_get_data_sources.py b/hvpy/api_groups/official_clients/tests/test_get_data_sources.py new file mode 100644 index 0000000..8754476 --- /dev/null +++ b/hvpy/api_groups/official_clients/tests/test_get_data_sources.py @@ -0,0 +1,17 @@ +from hvpy import getDataSources + + +def test_json_response(): + response = getDataSources() + assert isinstance(response, dict) + + +def test_str_response(): + response = getDataSources(callback="callback") + assert isinstance(response, str) + assert response.startswith("callback(") + + +def test_enable_parameter(): + response = getDataSources(verbose=False, enable="[Yohkoh,STEREO_A,STEREO_B]") + assert isinstance(response, dict) diff --git a/hvpy/facade.py b/hvpy/facade.py index d1bb74c..571cce0 100644 --- a/hvpy/facade.py +++ b/hvpy/facade.py @@ -5,7 +5,7 @@ from hvpy.parameters import * from hvpy.utils import add_shared_docstring -__all__ = ["getJP2Image", "getJP2Header", "getJPXClosestToMidPoint", "getJPX", "getStatus"] +__all__ = ["getJP2Image", "getJP2Header", "getJPXClosestToMidPoint", "getJPX", "getStatus", "getDataSources"] @add_shared_docstring(getJP2ImageInputParameters) @@ -146,3 +146,29 @@ def getStatus() -> Union[bytes, str, Dict[str, Any]]: """ params = getStatusInputParameters() return execute_api_call(input_parameters=params) + + +@add_shared_docstring(getDataSourcesInputParameters) +def getDataSources( + verbose: Optional[bool] = False, + enable: Optional[str] = None, + callback: Optional[str] = None, +) -> Union[bytes, str, Dict[str, Any]]: + """ + Return a hierarchial list of the available datasources. + + Parameters + ---------- + {Insert} + Examples + -------- + >>> from hvpy import getDataSources + >>> getDataSources() + {'SDO': {'HMI': {'continuum': {'sourceId': 18, 'nickname': 'HMI Int', 'layeringOrder': 1, 'start': '2010-12-06 06:53:41', 'end': '2022-07-11 23:59:54', 'uiLabels': [{'label': 'Observatory', 'name': 'SDO'}, {'label': 'Instrument', 'name': 'HMI'}, {'label': 'Measurement', 'name': 'continuum'}]}, ...} + """ + params = getDataSourcesInputParameters( + verbose=verbose, + enable=enable, + callback=callback, + ) + return execute_api_call(input_parameters=params) diff --git a/hvpy/parameters.py b/hvpy/parameters.py index a192a3e..648b5b2 100644 --- a/hvpy/parameters.py +++ b/hvpy/parameters.py @@ -3,6 +3,7 @@ from hvpy.api_groups.jpeg2000.get_jpx import getJPXInputParameters from hvpy.api_groups.jpeg2000.get_jpx_closest_to_mid_point import getJPXClosestToMidPointInputParameters from hvpy.api_groups.jpeg2000.get_status import getStatusInputParameters +from hvpy.api_groups.official_clients.get_data_sources import getDataSourcesInputParameters __all__ = [ "getJP2ImageInputParameters", @@ -10,4 +11,5 @@ "getJPXClosestToMidPointInputParameters", "getJPXInputParameters", "getStatusInputParameters", + "getDataSourcesInputParameters", ] From 22e7a2421c89e4938e0e0c6390903c033a9d6bb0 Mon Sep 17 00:00:00 2001 From: akash5100 Date: Thu, 14 Jul 2022 19:39:16 +0530 Subject: [PATCH 3/5] Merge with get_closest_image --- .../official_clients/get_data_sources.py | 37 +++++++++++++++++++ .../tests/test_get_data_sources.py | 17 +++++++++ hvpy/facade.py | 36 +++++++++++++++++- hvpy/parameters.py | 2 + 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 hvpy/api_groups/official_clients/get_data_sources.py create mode 100644 hvpy/api_groups/official_clients/tests/test_get_data_sources.py diff --git a/hvpy/api_groups/official_clients/get_data_sources.py b/hvpy/api_groups/official_clients/get_data_sources.py new file mode 100644 index 0000000..920e8da --- /dev/null +++ b/hvpy/api_groups/official_clients/get_data_sources.py @@ -0,0 +1,37 @@ +from typing import Optional + +from hvpy.io import HvpyParameters, OutputType + + +class getDataSourcesInputParameters(HvpyParameters): + """ + Handles the input parameters of the getDataSources API. + + Attributes + ---------- + {Shared} + verbose : bool, optional + Output the hierarchical list of available datasources in a format that is compatible with the JHelioviewer desktop client + enable : str, optional + Comma-separated list of observatories to enable. + callback : str, optional + Wrap the response object in a function call of your choosing. + + References + ---------- + * ``__ + {Shared} + """ + + verbose: Optional[bool] = False + enable: Optional[str] = None + callback: Optional[str] = None + + def get_output_type(self) -> OutputType: + """ + Returns the output type of the API call. + """ + if self.callback: + return OutputType.STRING + else: + return OutputType.JSON diff --git a/hvpy/api_groups/official_clients/tests/test_get_data_sources.py b/hvpy/api_groups/official_clients/tests/test_get_data_sources.py new file mode 100644 index 0000000..8754476 --- /dev/null +++ b/hvpy/api_groups/official_clients/tests/test_get_data_sources.py @@ -0,0 +1,17 @@ +from hvpy import getDataSources + + +def test_json_response(): + response = getDataSources() + assert isinstance(response, dict) + + +def test_str_response(): + response = getDataSources(callback="callback") + assert isinstance(response, str) + assert response.startswith("callback(") + + +def test_enable_parameter(): + response = getDataSources(verbose=False, enable="[Yohkoh,STEREO_A,STEREO_B]") + assert isinstance(response, dict) diff --git a/hvpy/facade.py b/hvpy/facade.py index d5a6835..75573f0 100644 --- a/hvpy/facade.py +++ b/hvpy/facade.py @@ -5,7 +5,15 @@ from hvpy.parameters import * from hvpy.utils import add_shared_docstring -__all__ = ["getJP2Image", "getJP2Header", "getJPXClosestToMidPoint", "getJPX", "getStatus", "getClosestImage"] +__all__ = [ + "getJP2Image", + "getJP2Header", + "getJPXClosestToMidPoint", + "getJPX", + "getStatus", + "getClosestImage", + "getDataSources", +] @add_shared_docstring(getJP2ImageInputParameters) @@ -174,3 +182,29 @@ def getClosestImage( """ params = getClosestImageInputParameters(date=date, sourceId=sourceId, callback=callback) return execute_api_call(input_parameters=params) + + +@add_shared_docstring(getDataSourcesInputParameters) +def getDataSources( + verbose: Optional[bool] = False, + enable: Optional[str] = None, + callback: Optional[str] = None, +) -> Union[bytes, str, Dict[str, Any]]: + """ + Return a hierarchial list of the available datasources. + + Parameters + ---------- + {Insert} + Examples + -------- + >>> from hvpy import getDataSources + >>> getDataSources() + {'SDO': {'HMI': {'continuum': {'sourceId': 18, 'nickname': 'HMI Int', 'layeringOrder': 1, 'start': '2010-12-06 06:53:41', 'end': '2022-07-11 23:59:54', 'uiLabels': [{'label': 'Observatory', 'name': 'SDO'}, {'label': 'Instrument', 'name': 'HMI'}, {'label': 'Measurement', 'name': 'continuum'}]}, ...} + """ + params = getDataSourcesInputParameters( + verbose=verbose, + enable=enable, + callback=callback, + ) + return execute_api_call(input_parameters=params) diff --git a/hvpy/parameters.py b/hvpy/parameters.py index 2a6cee2..e10de4f 100644 --- a/hvpy/parameters.py +++ b/hvpy/parameters.py @@ -4,6 +4,7 @@ from hvpy.api_groups.jpeg2000.get_jpx_closest_to_mid_point import getJPXClosestToMidPointInputParameters from hvpy.api_groups.jpeg2000.get_status import getStatusInputParameters from hvpy.api_groups.official_clients.get_closest_image import getClosestImageInputParameters +from hvpy.api_groups.official_clients.get_data_sources import getDataSourcesInputParameters __all__ = [ "getJP2ImageInputParameters", @@ -12,4 +13,5 @@ "getJPXInputParameters", "getStatusInputParameters", "getClosestImageInputParameters", + "getDataSourcesInputParameters", ] From 0e840aff82f94f21697b6a1c0dae2ce65ad929f0 Mon Sep 17 00:00:00 2001 From: akash5100 Date: Thu, 14 Jul 2022 21:30:49 +0530 Subject: [PATCH 4/5] Fix for the failing tests --- hvpy/api_groups/official_clients/get_data_sources.py | 2 +- hvpy/facade.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/hvpy/api_groups/official_clients/get_data_sources.py b/hvpy/api_groups/official_clients/get_data_sources.py index 920e8da..61d8842 100644 --- a/hvpy/api_groups/official_clients/get_data_sources.py +++ b/hvpy/api_groups/official_clients/get_data_sources.py @@ -11,7 +11,7 @@ class getDataSourcesInputParameters(HvpyParameters): ---------- {Shared} verbose : bool, optional - Output the hierarchical list of available datasources in a format that is compatible with the JHelioviewer desktop client + Output the hierarchical list of available datasources in a format that is compatible with the JHelioviewer desktop client, default is False. enable : str, optional Comma-separated list of observatories to enable. callback : str, optional diff --git a/hvpy/facade.py b/hvpy/facade.py index 1056cc1..1225a5e 100644 --- a/hvpy/facade.py +++ b/hvpy/facade.py @@ -5,7 +5,6 @@ from hvpy.parameters import * from hvpy.utils import add_shared_docstring - __all__ = [ "getJP2Image", "getJP2Header", @@ -17,7 +16,6 @@ ] - @add_shared_docstring(getJP2ImageInputParameters) def getJP2Image( date: datetime, @@ -186,7 +184,6 @@ def getClosestImage( return execute_api_call(input_parameters=params) - @add_shared_docstring(getDataSourcesInputParameters) def getDataSources( verbose: Optional[bool] = False, @@ -203,7 +200,8 @@ def getDataSources( -------- >>> from hvpy import getDataSources >>> getDataSources() - {'SDO': {'HMI': {'continuum': {'sourceId': 18, 'nickname': 'HMI Int', 'layeringOrder': 1, 'start': '2010-12-06 06:53:41', 'end': '2022-07-11 23:59:54', 'uiLabels': [{'label': 'Observatory', 'name': 'SDO'}, {'label': 'Instrument', 'name': 'HMI'}, {'label': 'Measurement', 'name': 'continuum'}]}, ...} + {'SDO': {'HMI': {'continuum': {'sourceId': 18, 'nickname': 'HMI Int', 'layeringOrder': 1, 'start': '2010-12-06 06:53:41', 'end': '2022-07-11 23:59:54', + 'uiLabels': [{'label': 'Observatory', 'name': 'SDO'}, {'label': 'Instrument', 'name': 'HMI'}, {'label': 'Measurement', 'name': 'continuum'}]}, ...} """ params = getDataSourcesInputParameters( verbose=verbose, From 96462fcf06bdbebb53279c4f6084df3042e03e83 Mon Sep 17 00:00:00 2001 From: akash5100 Date: Thu, 14 Jul 2022 21:35:43 +0530 Subject: [PATCH 5/5] Fix isort --- hvpy/parameters.py | 1 - 1 file changed, 1 deletion(-) diff --git a/hvpy/parameters.py b/hvpy/parameters.py index 711c54d..e10de4f 100644 --- a/hvpy/parameters.py +++ b/hvpy/parameters.py @@ -6,7 +6,6 @@ from hvpy.api_groups.official_clients.get_closest_image import getClosestImageInputParameters from hvpy.api_groups.official_clients.get_data_sources import getDataSourcesInputParameters - __all__ = [ "getJP2ImageInputParameters", "getJP2HeaderInputParameters",