-
Notifications
You must be signed in to change notification settings - Fork 1
updated catalogue with landing page and polytope integration #72
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
Open
mathleur
wants to merge
11
commits into
main
Choose a base branch
from
feat/landing_page
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 10 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
ec18e43
new catalogue UI test
mathleur 187dabd
add datepicker
mathleur d62dcd2
add leaflet map
mathleur 50f3559
integrate polytope request button
mathleur 02d98b1
fix auth
mathleur 6ac351e
add search bar
mathleur 286b3a4
add landing page with catalogue templates
mathleur 541ff04
add landing page and fix search bar bug
mathleur 0182613
try to add logo
mathleur 83a78dd
add data download button
mathleur 3760909
Update Polytope API key instructions
mathleur File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,47 @@ | ||
| # Polytope Authentication | ||
|
|
||
| The STAC server's Polytope integration collects authentication credentials directly from users through the web interface and queries the **Destination Earth** Polytope service. | ||
|
|
||
| ## User Flow | ||
|
|
||
| 1. Navigate through the STAC catalogue and select your data | ||
| 2. At the end of the catalogue, you'll see the "Query Data with Polytope" section | ||
| 3. Enter your Destination Earth Polytope credentials: | ||
| - **Email Address**: Your email address registered with Destination Earth | ||
| - **API Key**: Your Polytope API key | ||
| 4. Click "Query Polytope Service" to submit your data extraction requests | ||
|
|
||
| ## Getting Your Polytope API Key | ||
|
|
||
| 1. Visit [https://polytope.lumi.apps.dte.destination-earth.eu](https://polytope.lumi.apps.dte.destination-earth.eu) | ||
| 2. Log in with your Destination Earth credentials | ||
| 3. Navigate to your profile or settings | ||
| 4. Generate or copy your API key | ||
|
|
||
| ## Technical Details | ||
|
|
||
| The service connects to the Destination Earth Polytope instance: | ||
| - **Address**: `polytope.lumi.apps.dte.destination-earth.eu` | ||
| - **Collection**: `destination-earth` | ||
|
|
||
| ## Security Notes | ||
|
|
||
| - Credentials are sent securely with each request | ||
| - Credentials are not stored on the server | ||
| - Each user provides their own authentication | ||
| - Credentials are only logged in a masked format for debugging | ||
|
|
||
| ## For Developers | ||
|
|
||
| The credentials are sent in the request body as: | ||
| ```json | ||
| { | ||
| "requests": [...], | ||
| "credentials": { | ||
| "user_email": "user@ecmwf.int", | ||
| "user_key": "your_api_key" | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| The backend passes these credentials directly to `earthkit.data.from_source()` when querying Polytope. | ||
This file contains hidden or 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 |
|---|---|---|
|
|
@@ -120,6 +120,15 @@ async def deprecated(): | |
|
|
||
| @app.get("/", response_class=HTMLResponse) | ||
| async def read_root(request: Request): | ||
| index_config = { | ||
| "title": os.environ.get("TITLE", "Qubed Catalogue Browser"), | ||
| } | ||
|
|
||
| return templates.TemplateResponse(request, "landing.html", index_config) | ||
|
|
||
|
|
||
| @app.get("/browse", response_class=HTMLResponse) | ||
| async def browse_catalogue(request: Request): | ||
| index_config = { | ||
| "api_url": os.environ.get("API_URL", "/api/v2/"), | ||
| "title": os.environ.get("TITLE", "Qubed Catalogue Browser"), | ||
|
|
@@ -147,6 +156,120 @@ async def union( | |
| return qube.to_json() | ||
|
|
||
|
|
||
| @app.post("/api/v2/polytope/query") | ||
| async def query_polytope( | ||
| body_json=Depends(get_body_json), | ||
| ): | ||
| """ | ||
| Query the Destination Earth Polytope data extraction service with MARS requests. | ||
| Expects a JSON body with: | ||
| - 'requests': array of MARS request objects | ||
| - 'credentials': object with 'user_email' and 'user_key' fields | ||
|
|
||
| Connects to: polytope.lumi.apps.dte.destination-earth.eu | ||
| Collection: destination-earth | ||
| """ | ||
| try: | ||
| import earthkit.data | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would use the polytope-client rather than earthkit.data unless we're using some speficic functionality of it |
||
| except ImportError: | ||
| raise HTTPException( | ||
| status_code=500, | ||
| detail="earthkit.data is not installed. Please install it with 'pip install earthkit-data'", | ||
| ) | ||
|
|
||
| requests = body_json.get("requests", []) | ||
| if not requests: | ||
| raise HTTPException(status_code=400, detail="No requests provided") | ||
|
|
||
| # Get credentials from request body | ||
| credentials = body_json.get("credentials", {}) | ||
| user_email = credentials.get("user_email") | ||
| user_key = credentials.get("user_key") | ||
|
|
||
| if not user_email or not user_key: | ||
| raise HTTPException( | ||
| status_code=400, | ||
| detail="Credentials required: provide user_email and user_key", | ||
| ) | ||
|
|
||
| # Prepare kwargs for polytope connection | ||
| polytope_kwargs = { | ||
| "stream": False, | ||
| "address": "polytope.lumi.apps.dte.destination-earth.eu", | ||
| "user_email": user_email, | ||
| "user_key": user_key, | ||
| } | ||
|
|
||
| logger.info(f"Querying Polytope with user email: {user_email}") | ||
|
|
||
| results = [] | ||
| successful = 0 | ||
| failed = 0 | ||
|
|
||
| for idx, mars_request in enumerate(requests): | ||
| try: | ||
| logger.info(f"Querying Polytope for request {idx + 1}/{len(requests)}") | ||
| logger.debug(f"Request: {mars_request}") | ||
|
|
||
| # Query Polytope service | ||
| ds = earthkit.data.from_source( | ||
| "polytope", "destination-earth", mars_request, **polytope_kwargs | ||
| ) | ||
|
|
||
| # Get JSON representation of the data | ||
| try: | ||
| ds_json = ds._json() | ||
| logger.info(f"Successfully extracted JSON from request {idx + 1}") | ||
| except Exception as json_error: | ||
| logger.warning( | ||
| f"Could not extract JSON from request {idx + 1}: {json_error}" | ||
| ) | ||
| ds_json = None | ||
|
|
||
| # Get some basic info about the result | ||
| data_info = ( | ||
| f"Retrieved {len(ds)} fields" | ||
| if hasattr(ds, "__len__") | ||
| else "Data retrieved" | ||
| ) | ||
|
|
||
| result_entry = { | ||
| "success": True, | ||
| "request_index": idx, | ||
| "message": data_info, | ||
| "data_size": str(len(ds)) if hasattr(ds, "__len__") else None, | ||
| "mars_request": mars_request, | ||
| } | ||
|
|
||
| # Add JSON data if available | ||
| if ds_json is not None: | ||
| result_entry["json_data"] = ds_json | ||
|
|
||
| results.append(result_entry) | ||
| successful += 1 | ||
| logger.info(f"Request {idx + 1} successful: {data_info}") | ||
|
|
||
| except Exception as e: | ||
| error_msg = str(e) | ||
| logger.error(f"Request {idx + 1} failed: {error_msg}") | ||
| results.append( | ||
| { | ||
| "success": False, | ||
| "request_index": idx, | ||
| "error": error_msg, | ||
| "mars_request": mars_request, | ||
| } | ||
| ) | ||
| failed += 1 | ||
|
|
||
| return { | ||
| "total": len(requests), | ||
| "successful": successful, | ||
| "failed": failed, | ||
| "results": results, | ||
| } | ||
|
|
||
|
|
||
| def follow_query(request: dict[str, str | list[str]], qube: Qube): | ||
| rel_qube = qube.select(request, consume=False) | ||
|
|
||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Misleading instructions, at least currently