Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Adding support for query by Solar Distance #137

Merged
merged 17 commits into from
Aug 18, 2024
Merged

Conversation

NucleonGodX
Copy link
Contributor

As the #134 suggested adding support for querying by solar distance. This pull request extends support for another REQUEST method, doQueryFilteredByDistance.

@nabobalis
Copy link
Contributor

Looks like there is a file conflict with main

@NucleonGodX
Copy link
Contributor Author

Looks like there is a file conflict with main

yep, I'll fix it.

@hayesla
Copy link
Member

hayesla commented Jul 31, 2024

thanks for this PR @NucleonGodX !

Some comments to begin with -

  • I think it would be best to pass astropy units to a.soar.Distance rather than just floats. i.e. a.soar.Distance(0.2*u.AU, 0.3*u.AU), and equivalent distance etc (u.km, u.Mm).
  • there seems to be an issue if the passed distances are outside the range e.g. :
>>> res = Fido.search(a.Time("2022-03-30 17:00", "2022-03-30 19:00"), 
                  a.Instrument.eui, a.Provider.soar, a.soar.Distance(0.2, 0.9))
---------------------------------------------------------------------------
HTTPError                                 Traceback (most recent call last)
Cell In[11], line 1
----> 1 res = Fido.search(a.Time("2022-03-30 17:00", "2022-03-30 19:00"), 
      2                   a.Instrument.eui, a.Provider.soar, a.soar.Distance(0.2, 0.9))

File ~/opt/miniconda3/envs/sunpysoar_dev/lib/python3.11/site-packages/sunpy/net/fido_factory.py:314, in UnifiedDownloaderFactory.search(self, *query)
    268 """
    269 Query for data in form of multiple parameters.
    270 
   (...)
    311 parts individually.
    312 """
    313 query = attr.and_(*query)
--> 314 results = query_walker.create(query, self)
    316 # If we have searched the VSO but no results were returned, but another
    317 # client generated results, we drop the empty VSO results for tidiness.
    318 # This is because the VSO _can_handle_query is very broad because we
    319 # don't know the full list of supported values we can search for (yet).
    320 results = [r for r in results if not isinstance(r, vso.VSOQueryResponseTable) or len(r) > 0]

File ~/opt/miniconda3/envs/sunpysoar_dev/lib/python3.11/site-packages/sunpy/net/attr.py:613, in AttrWalker.create(self, *args, **kwargs)
    609 def create(self, *args, **kwargs):
    610     """
    611     Call the create function(s) matching the arguments to this method.
    612     """
--> 613     return self.createmm(self, *args, **kwargs)

File ~/opt/miniconda3/envs/sunpysoar_dev/lib/python3.11/site-packages/sunpy/util/functools.py:18, in seconddispatch.<locals>.wrapper(*args, **kwargs)
     17 def wrapper(*args, **kwargs):
---> 18     return dispatcher.dispatch(args[1].__class__)(*args, **kwargs)

File ~/opt/miniconda3/envs/sunpysoar_dev/lib/python3.11/site-packages/sunpy/net/fido_factory.py:243, in _create_and(walker, query, factory)
    241 @query_walker.add_creator(attr.AttrAnd)
    242 def _create_and(walker, query, factory):
--> 243     return factory._make_query_to_client(*query.attrs)

File ~/opt/miniconda3/envs/sunpysoar_dev/lib/python3.11/site-packages/sunpy/net/fido_factory.py:485, in UnifiedDownloaderFactory._make_query_to_client(self, *query)
    483     if isinstance(tmpclient, vso.VSOClient):
    484         kwargs = dict(response_format="table")
--> 485     results.append(tmpclient.search(*query, **kwargs))
    487 # This method is called by `search` and the results are fed into a
    488 # UnifiedResponse object.
    489 return results

File ~/dev_things/sunpy-soar/sunpy_soar/client.py:33, in SOARClient.search(self, *query, **kwargs)
     31     if "provider='SOAR'" in query_parameters:
     32         query_parameters.remove("provider='SOAR'")
---> 33     results.append(self._do_search(query_parameters))
     34 table = astropy.table.vstack(results)
     35 qrt = QueryResponseTable(table, client=self)

File ~/dev_things/sunpy-soar/sunpy_soar/client.py:189, in SOARClient._do_search(query)
    187 r = requests.get(f"{tap_endpoint}/sync", params=payload)
    188 log.debug(f"Sent query: {r.url}")
--> 189 r.raise_for_status()
    191 try:
    192     response_json = r.json()

File ~/opt/miniconda3/envs/sunpysoar_dev/lib/python3.11/site-packages/requests/models.py:1021, in Response.raise_for_status(self)
   1016     http_error_msg = (
   1017         f"{self.status_code} Server Error: {reason} for url: {self.url}"
   1018     )
   1020 if http_error_msg:
-> 1021     raise HTTPError(http_error_msg, response=self)

HTTPError: 400 Client Error:  for url: [http://soar.esac.esa.int/soar-sl-tap/tap/sync?REQUEST=doQueryFilteredByDistance&LANG=ADQL&FORMAT=json&QUERY=SELECT+h1.instrument,%20h1.descriptor,%20h1.level,%20h1.begin_time,%20h1.end_time,%20h1.data_item_id,%20h1.filesize,%20h1.filename,%20h1.soop_name,%20h2.detector,%20h2.wavelength,%20h2.dimension_index+FROM+v_sc_data_item%20AS%20h1%20JOIN%20v_eui_sc_fits%20AS%20h2%20USING%20(data_item_oid)+WHERE+h1.begin_time%3E='2022-03-30+17:00:00'+AND+h1.begin_time%3C='2022-03-30+19:00:00'+AND+h2.dimension_index='1'+AND+h1.instrument='EUI'&DISTANCE(0.2,0.9](http://soar.esac.esa.int/soar-sl-tap/tap/sync?REQUEST=doQueryFilteredByDistance&LANG=ADQL&FORMAT=json&QUERY=SELECT+h1.instrument,%20h1.descriptor,%20h1.level,%20h1.begin_time,%20h1.end_time,%20h1.data_item_id,%20h1.filesize,%20h1.filename,%20h1.soop_name,%20h2.detector,%20h2.wavelength,%20h2.dimension_index+FROM+v_sc_data_item%20AS%20h1%20JOIN%20v_eui_sc_fits%20AS%20h2%20USING%20(data_item_oid)+WHERE+h1.begin_time%3E=%272022-03-30+17:00:00%27+AND+h1.begin_time%3C=%272022-03-30+19:00:00%27+AND+h2.dimension_index=%271%27+AND+h1.instrument=%27EUI%27&DISTANCE(0.2,0.9))

@hayesla
Copy link
Member

hayesla commented Jul 31, 2024

so it seems like if you pass anything outside of (0.28, 1), it doesnt like that - so we'd need to raise a warning etc.

Some tests testing this are also needed.

@NucleonGodX
Copy link
Contributor Author

I'll push all the needful changes.

Copy link
Member

@hayesla hayesla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good @NucleonGodX !

I think it also needs some tests for which the wrong units are passed to test for the warning raised. Similarly a test for when you build a search outside of (0.28, 1)

by solar distance without relying on a specific distance column.
"""
if dist_max is None:
dist_max = dist_min
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this actually work though - like if you have a range with the same values in both it wont work in the query, right? So we should force people to give a range.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this actually work though - like if you have a range with the same values in both it wont work in the query, right? So we should force people to give a range.

Yeah, makes sense.

sunpy_soar/attrs.py Show resolved Hide resolved
sunpy_soar/attrs.py Outdated Show resolved Hide resolved
sunpy_soar/attrs.py Outdated Show resolved Hide resolved
sunpy_soar/attrs.py Outdated Show resolved Hide resolved
###############################################################################
# We shall start with constructing a search query with instrument, level, detector, and distance.

instrument = a.Instrument("METIS")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you make this EUI instead. And maybe EUI with the product being eui_hrieuv174_image rather than using METIS. Users would be more interested in building this search for with the EUI instrument, and specifically the HRI telescope.

examples/solar_distance_query.py Show resolved Hide resolved
@NucleonGodX
Copy link
Contributor Author

I'll fix the failing test and change the instrument to EUI once I reach home.

Copy link
Member

@hayesla hayesla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great @NucleonGodX!

I dont know what the test fails are exactly, but once they pass good to go

sunpy_soar/attrs.py Outdated Show resolved Hide resolved
sunpy_soar/attrs.py Outdated Show resolved Hide resolved
assert res.file_num == 48


def test_distance_out_of_bounds_warning(recwarn):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the recwarn here for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, its a pytest fixture provided by the pytest library that allows you to capture warnings emitted during the execution of a test.

@NucleonGodX
Copy link
Contributor Author

@nabobalis I'll push some changes to fix pre-commit, let me know if they are okay.

@@ -122,7 +122,7 @@ def add_join_to_query(query: list[str], data_table: str, instrument_table: str):
return where_part, from_part, select_part

@staticmethod
def _construct_payload(query):
def _construct_payload(query): # NOQA: C901
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is C901?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its about the function being too complex.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh that should be added to the global ignore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright!

@hayesla hayesla merged commit 37d1227 into sunpy:main Aug 18, 2024
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants