-
-
Notifications
You must be signed in to change notification settings - Fork 574
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7463 from GillySpace27/main
ADAPT Client
- Loading branch information
Showing
12 changed files
with
309 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
A new client (`sunpy.net.dataretriever.ADAPTClient`) has been added to search and download `ADAPT <https://gong.nso.edu/adapt/maps/gong/>`__ files. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
from . import goes | ||
from . import adapt, goes | ||
|
||
__all__ = ['goes'] | ||
__all__ = ['adapt', 'goes'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
from sunpy.net.attr import SimpleAttr | ||
|
||
__all__ = ['ADAPTFileType', 'ADAPTLonType', 'ADAPTInputSource', | ||
'ADAPTDataAssimilation', 'ADAPTResolution', 'ADAPTVersionYear', 'ADAPTVersionMonth', | ||
'ADAPTEvolutionMode', 'ADAPTHelioData', 'ADAPTRealizations', 'ADAPTMagData'] | ||
|
||
# Define a custom __dir__ to restrict tab-completion to __all__ | ||
def __dir__(): | ||
return __all__ | ||
|
||
|
||
class ADAPTFileType(SimpleAttr): | ||
""" | ||
ADAPT file type: Public. | ||
""" | ||
pass | ||
|
||
class ADAPTLonType(SimpleAttr): | ||
""" | ||
ADAPT longitude type: Carrington Fixed, Central Meridian, East Limb. | ||
""" | ||
pass | ||
|
||
class ADAPTInputSource(SimpleAttr): | ||
""" | ||
ADAPT input source: All, KPVT, VSM, GONG, HMI, MDI, MWO. | ||
""" | ||
pass | ||
|
||
class ADAPTDataAssimilation(SimpleAttr): | ||
""" | ||
ADAPT data assimilation: WH, enLS, enkf, enLAKF. | ||
""" | ||
pass | ||
|
||
class ADAPTResolution(SimpleAttr): | ||
""" | ||
ADAPT model spatial resolution: 1.0 deg, 0.2 deg. | ||
""" | ||
pass | ||
|
||
class ADAPTVersionYear(SimpleAttr): | ||
""" | ||
ADAPT code version year. | ||
""" | ||
pass | ||
|
||
class ADAPTVersionMonth(SimpleAttr): | ||
""" | ||
ADAPT code version month. | ||
""" | ||
pass | ||
|
||
class ADAPTEvolutionMode(SimpleAttr): | ||
""" | ||
ADAPT evolution mode: Data assimilation step, Intermediate step, Forecast step. | ||
""" | ||
pass | ||
|
||
class ADAPTHelioData(SimpleAttr): | ||
""" | ||
ADAPT helioseismic data: Not added or no data, Far-side, Emergence, Both emergence & far-side. | ||
""" | ||
pass | ||
|
||
class ADAPTRealizations(SimpleAttr): | ||
""" | ||
ADAPT realizations: number of model/file realizations, e.g., 16 -> "016" | ||
""" | ||
pass | ||
|
||
|
||
class ADAPTMagData(SimpleAttr): | ||
""" | ||
ADAPT magnetic data: Not added or no data, Mag-los, Mag-vector, Mag- both los & vector, Mag- polar avg obs, Mag- los & polar, Mag- vector & polar, Mag- both los and vector & polar. | ||
""" | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
from sunpy.net import attrs as a | ||
from sunpy.net.dataretriever import GenericClient | ||
from sunpy.net.dataretriever.attrs.adapt import ( | ||
ADAPTDataAssimilation, | ||
ADAPTEvolutionMode, | ||
ADAPTFileType, | ||
ADAPTHelioData, | ||
ADAPTInputSource, | ||
ADAPTLonType, | ||
ADAPTMagData, | ||
ADAPTRealizations, | ||
ADAPTResolution, | ||
ADAPTVersionMonth, | ||
ADAPTVersionYear, | ||
) | ||
|
||
__all__ = ['ADAPTClient'] | ||
|
||
|
||
class ADAPTClient(GenericClient): | ||
""" | ||
Provides access to the ADvanced Adaptive Prediction Technique (ADAPT) products | ||
of the National Solar Observatory (NSO). | ||
`Searches data hosted by the NSO <https://gong.nso.edu/adapt/maps/gong/>`__ | ||
Examples | ||
-------- | ||
>>> import astropy.units as u | ||
>>> from sunpy.net import Fido, attrs as a | ||
>>> from sunpy.coordinates.sun import carrington_rotation_time | ||
>>> # Define the Carrington Rotation Number and the number of frames | ||
>>> CR = 2193 | ||
>>> frames = 10 | ||
>>> date_start = carrington_rotation_time(CR) | ||
>>> date_end = date_start + frames*(3*1.9999999 * u.hour) | ||
>>> longitude_type = '0' | ||
>>> Fido.search(a.Time(date_start, date_end), a.Instrument('adapt'), a.adapt.ADAPTLonType(longitude_type)) # doctest: +REMOTE_DATA | ||
<sunpy.net.fido_factory.UnifiedResponse object at ...> | ||
Results from 1 Provider: | ||
<BLANKLINE> | ||
10 Results from the ADAPTClient: | ||
<BLANKLINE> | ||
Start Time End Time Instrument Provider Source ... ADAPTMagData days_since_last_obs hours_since_last_obs minutes_since_last_obs seconds_since_last_obs | ||
----------------------- ----------------------- ---------- -------- ------ ... ------------ ------------------- -------------------- ---------------------- ---------------------- | ||
2017-07-20 08:00:00.000 2017-07-20 08:00:59.999 ADAPT NSO GONG ... 1 0 1 56 0 | ||
2017-07-20 14:00:00.000 2017-07-20 14:00:59.999 ADAPT NSO GONG ... 1 0 1 56 0 | ||
2017-07-20 20:00:00.000 2017-07-20 20:00:59.999 ADAPT NSO GONG ... 1 0 1 56 0 | ||
2017-07-21 02:00:00.000 2017-07-21 02:00:59.999 ADAPT NSO GONG ... 1 0 1 56 0 | ||
2017-07-21 08:00:00.000 2017-07-21 08:00:59.999 ADAPT NSO GONG ... 1 0 1 56 0 | ||
2017-07-21 14:00:00.000 2017-07-21 14:00:59.999 ADAPT NSO GONG ... 1 0 1 56 0 | ||
2017-07-21 20:00:00.000 2017-07-21 20:00:59.999 ADAPT NSO GONG ... 1 0 1 56 0 | ||
2017-07-22 02:00:00.000 2017-07-22 02:00:59.999 ADAPT NSO GONG ... 1 0 1 56 0 | ||
2017-07-22 08:00:00.000 2017-07-22 08:00:59.999 ADAPT NSO GONG ... 1 0 4 36 0 | ||
2017-07-22 14:00:00.000 2017-07-22 14:00:59.999 ADAPT NSO GONG ... 1 0 1 56 0 | ||
<BLANKLINE> | ||
<BLANKLINE> | ||
References | ||
---------- | ||
`Names and possible attrs values are available <https://gong.nso.edu/adapt/maps/adapt_filename_notes.txt>`__. | ||
""" | ||
baseurl = r'https://gong.nso.edu/adapt/maps/gong/%Y/adapt(\d){5}_(\d){2}(\w){1}(\d){3}_(\d){12}_(\w){1}(\d){8}(\w){1}(\d){1}\.fts\.gz' | ||
pattern = '{}adapt{ADAPTFileType:1d}{ADAPTLonType:1d}{ADAPTInputSource:1d}{ADAPTDataAssimilation:1d}{ADAPTResolution:1d}' + \ | ||
'_{ADAPTVersionYear:2d}{ADAPTVersionMonth:1l}{ADAPTRealizations:3d}_{year:4d}{month:2d}{day:2d}{hour:2d}{minute:2d}' + \ | ||
'_{ADAPTEvolutionMode:1l}{days_since_last_obs:2d}{hours_since_last_obs:2d}{minutes_since_last_obs:2d}{seconds_since_last_obs:2d}{ADAPTHelioData:1l}{ADAPTMagData:1d}.fts.gz' | ||
|
||
@classmethod | ||
def _attrs_module(cls): | ||
return 'adapt', 'sunpy.net.dataretriever.attrs.adapt' | ||
|
||
@classmethod | ||
def register_values(cls): | ||
adict = { | ||
a.Instrument: [('ADAPT', 'ADvanced Adaptive Prediction Technique.')], | ||
a.Provider: [('NSO', 'National Solar Observatory.')], | ||
a.Source: [('GONG', 'Global Oscillation Network Group.')], | ||
ADAPTFileType: [('4', 'Public')], | ||
ADAPTLonType: [('0', 'Carrington Fixed'), ('1', 'Central Meridian'), ('2', 'East Limb')], | ||
ADAPTInputSource: [('0', 'All'), ('1', 'KPVT'), ('2', 'VSM'), ('3', 'GONG'), ('4', 'HMI'), ('5', 'MDI'), ('6', 'MWO')], | ||
ADAPTDataAssimilation: [('0', 'WH'), ('1', 'enLS'), ('2', 'enkf'), ('3', 'enLAKF')], | ||
ADAPTResolution: [('1', '1.0 deg'), ('2', '0.2 deg')], | ||
ADAPTVersionYear: [(str(i), f"Code version year -> {2000 + i}") for i in range(1, 20)], | ||
ADAPTRealizations: [(str(i), f"Number of Realizations -> {i}") for i in range(1, 20)], | ||
ADAPTVersionMonth: [(chr(i+96), f"Code version month -> {i}") for i in range(1, 13)], | ||
ADAPTEvolutionMode: [('a', 'Data assimilation step'), ('i', 'Intermediate step'), ('f', 'Forecast step')], | ||
ADAPTHelioData: [('n', 'Not added or no data'), ('f', 'Far-side'), ('e', 'Emergence'), ('b', 'Both emergence & far-side')], | ||
ADAPTMagData: [('0', 'Not added or no data'), ('1', 'Mag-los'), ('2', 'Mag-vector'), ('3', 'Mag- both los & vector'), | ||
('4', 'Mag- polar avg obs'), ('5', 'Mag- los & polar'), ('6', 'Mag- vector & polar'), ('7', 'Mag- both los and vector & polar')] | ||
} | ||
return adict |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
|
||
import tempfile | ||
|
||
import pytest | ||
from hypothesis import given | ||
|
||
import sunpy.net.dataretriever.sources.adapt as adapt | ||
from sunpy.net import attrs as a | ||
from sunpy.net.dataretriever.client import QueryResponse | ||
from sunpy.net.tests.strategies import time_attr | ||
from sunpy.time import parse_time | ||
|
||
|
||
@pytest.fixture | ||
def adapt_client(): | ||
return adapt.ADAPTClient() | ||
|
||
|
||
@given(time_attr()) | ||
def test_can_handle_query(time): | ||
# Hypothesis complains if we use the fixture | ||
adapt_client = adapt.ADAPTClient() | ||
ans1 = adapt_client._can_handle_query(time, a.Instrument.adapt) | ||
assert ans1 is True | ||
ans2 = adapt_client._can_handle_query(time, a.Instrument.adapt, | ||
a.adapt.ADAPTResolution('1')) | ||
assert ans2 is True | ||
ans3 = adapt_client._can_handle_query(time, a.Instrument.adapt, | ||
a.adapt.ADAPTResolution('1'), | ||
a.adapt.ADAPTHelioData('f')) | ||
assert ans3 is True | ||
ans4 = adapt_client._can_handle_query(time) | ||
assert ans4 is False | ||
ans5 = adapt_client._can_handle_query(time, a.Instrument.adapt, a.Provider.nso) | ||
assert ans5 is True | ||
ans6 = adapt_client._can_handle_query(time, a.Instrument.adapt, | ||
a.adapt.ADAPTLonType('0')) | ||
assert ans6 is True | ||
|
||
|
||
def mock_query_object(adapt_client): | ||
""" | ||
Creating a Query Response object and prefilling it with some information | ||
""" | ||
start = '2019-05-25T02:00:00.00' | ||
end = '2019-05-25T02:00:59.999' | ||
obj = { | ||
'Start Time': parse_time(start), | ||
'End Time': parse_time(end), | ||
'Instrument': 'ADAPT', | ||
'Physobs': 'flux', | ||
'Source': 'GONG', | ||
'Provider': 'NSO', | ||
'url': ("https://gong.nso.edu/adapt/maps/gong/2019/adapt40311_03i012_201905250200_i00005600n0.fts.gz") | ||
} | ||
results = QueryResponse([obj], client=adapt_client) | ||
return results | ||
|
||
|
||
@pytest.mark.remote_data | ||
def test_fetch_working(adapt_client): | ||
""" | ||
Tests if the online server is working. | ||
This also checks if the mock is working well. | ||
""" | ||
start = '2019/05/25 02:00:00' | ||
end = '2019/05/26 02:00:59.999' | ||
tr = a.Time(start, end) | ||
qr = adapt_client.search(tr, a.Instrument.adapt)[0] | ||
mock_qr = mock_query_object(adapt_client)[0] | ||
|
||
assert mock_qr['Source'] == qr['Source'] | ||
assert mock_qr['Provider'] == qr['Provider'] | ||
assert mock_qr['Instrument'] == qr['Instrument'] | ||
assert mock_qr['url'] == qr['url'] | ||
assert qr['Start Time'].isot == mock_qr['Start Time'].isot | ||
assert qr['End Time'].isot == mock_qr['End Time'].isot | ||
|
||
with tempfile.TemporaryDirectory() as tmpdirname: | ||
download_list = adapt_client.fetch(qr, path=tmpdirname) | ||
assert len(download_list) == 1 | ||
|
||
|
||
|
||
def test_show(adapt_client): | ||
mock_qr = mock_query_object(adapt_client) | ||
qrshow0 = mock_qr.show() | ||
qrshow1 = mock_qr.show('Start Time', 'Instrument') | ||
allcols = {'Start Time', 'End Time', 'Instrument', 'Source', 'Provider', 'url'} | ||
assert not allcols.difference(qrshow0.colnames) | ||
assert qrshow1.colnames == ['Start Time', 'Instrument'] | ||
assert qrshow0['Instrument'][0] == 'ADAPT' | ||
|
||
|
||
def test_attr_reg(): | ||
assert a.Instrument.adapt == a.Instrument('ADAPT') | ||
|
||
|
||
def test_client_repr(adapt_client): | ||
""" | ||
Repr check | ||
""" | ||
output = str(adapt_client) | ||
assert output[:50] == 'sunpy.net.dataretriever.sources.adapt.ADAPTClient\n' |