Skip to content
This repository was archived by the owner on Sep 6, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
830fe17
openapi info and tests for observer position
dgarciabriseno Nov 14, 2023
f294b4a
Refactor ephemeris apis into its own file
dgarciabriseno Nov 15, 2023
be20d3a
Move get earth into ephemeris
dgarciabriseno Nov 15, 2023
4a1aba4
Remove openapi.yaml
dgarciabriseno Nov 15, 2023
6baeee7
remove psp position route in favor of ephemeris
dgarciabriseno Nov 15, 2023
f346c08
Update python dependencies
dgarciabriseno Nov 15, 2023
f9cc82c
Update outdated dependencies
dgarciabriseno Nov 15, 2023
fb8a5d3
Update events routes
dgarciabriseno Nov 16, 2023
6869ed9
Update database routes
dgarciabriseno Nov 16, 2023
e27a43b
Fix tests
dgarciabriseno Nov 16, 2023
04544d0
Add response info for get latest scenes
dgarciabriseno Nov 17, 2023
b3804ec
Add operation ids to the apis
dgarciabriseno Nov 17, 2023
fe4af8b
Organize into "monorepo"
dgarciabriseno Nov 17, 2023
d42c1e5
fix get_earth and add test
dgarciabriseno Nov 17, 2023
76b4270
Updates to work with new api
dgarciabriseno Nov 27, 2023
ed9a0a9
don't send thumbnail
dgarciabriseno Nov 27, 2023
5cf34e5
Remove openapi html page
dgarciabriseno Nov 27, 2023
f375b00
disable doc ui
dgarciabriseno Nov 27, 2023
175d4ee
CI Update
dgarciabriseno Nov 27, 2023
22e55ce
update cd paths
dgarciabriseno Nov 27, 2023
d4ecad7
fix all ci paths
dgarciabriseno Nov 27, 2023
27acdcf
Move hidden config files
dgarciabriseno Nov 27, 2023
b015157
Restore API url
dgarciabriseno Nov 27, 2023
861d711
Debug prints for ci environment
dgarciabriseno Nov 27, 2023
de5cfc8
Print config file being used
dgarciabriseno Nov 27, 2023
6a6970c
Rename config environment variable
dgarciabriseno Nov 27, 2023
dde4a73
Remove thumbnail from test
dgarciabriseno Nov 27, 2023
2cb7789
Revert "Rename config environment variable"
dgarciabriseno Nov 27, 2023
9473268
Fix CI database config path
dgarciabriseno Nov 27, 2023
343de10
Add empty __init__.py for api folder
dgarciabriseno Nov 27, 2023
f66d6c7
debugging why ci won't work
dgarciabriseno Nov 27, 2023
7d3ae38
print flask version
dgarciabriseno Nov 27, 2023
dd54eaa
show directory
dgarciabriseno Nov 27, 2023
516864a
import works, add flask
dgarciabriseno Nov 27, 2023
83a78cd
Rename api to server
dgarciabriseno Nov 27, 2023
0e973b7
update folder name in ci
dgarciabriseno Nov 27, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:

env:
DB_PASSWORD: gh-actions
CONFIG_FILE_PATH: ../.github/workflows/ci.config.ini
CONFIG_FILE_PATH: ../../.github/workflows/ci.config.ini

jobs:
build:
Expand Down Expand Up @@ -41,22 +41,27 @@ jobs:

- name: Start API server
run: |
cd server
cd monorepo/server
python -m pip install -r requirements.txt
python -m flask --app main run --debug &
cd ..
python -m flask --app main run &

- name: Make sure package can be built
run: |
cd monorepo/app
npm ci
sh build.sh

- name: Run javascript unit tests
run: npm run test
run: |
cd monorepo/app
npm run test

- name: Run python unit tests
run: cd server && python -m pytest && cd ..
run: |
cd monorepo/api
python -m pytest

- name: Make sure code conforms to prettier standards
run: |
cd monorepo/app
npm run prettier-test
33 changes: 20 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
Welcome to the Helios's Internal API documentation.
This information covers the classes that make up
the Helios application.

You can find the overall design for Helios [here](https://bit.ly/3PtWmLp)
It includes the dependencies between each class.
# Helios
Welcome! Helios is a next-gen web client supported by The Helioviewer Project.
It is a 3D web client for viewing data provided by [Helioviewer](https://helioviewer.org)
You can access Helios [here](https://gl.helioviewer.org)

## Overview
Helios uses threejs to render full disk images on a hemisphere (because observatories) only see one side...
If you've used [JHelioviewer](https://www.jhelioviewer.org/) then you're already familiar with how this works.

The advantage of Helios is that it runs in a browser, meaning it will run on
all of your devices to make sharing easy and accessible.

Helios is interoperable with Helioviewer.org and JHelioviewer.
Any videos made in Helioviewer can be opened in either Helios or JHelioviewer.
Similarly, any data loaded in Helios can also be opened in JHelioviewer with
the click of a button.

Helios is an adaptation of [Helioviewer](https://helioviewer.org) which uses 3js to render solar images in 3D.
It works by getting image and positional data from the Helioviewer API, and rendering them in a 3D scene.
You can interact with a demo [here](https://gl.helioviewer.org).
If you're interested in contributing to this project, see the details below.

## Development Quickstart
The application has been containerized with docker compose.
The fastest way to get this application running on your pc is to get [get docker](https://docs.docker.com/get-docker/).
The development environment for Helios has been containerized with docker compose.
The fastest way to get this application running on your system is to get [get docker](https://docs.docker.com/get-docker/).
Then once it's installed and running, execute:

```
Expand All @@ -24,7 +30,8 @@ If you plan to work on the flask API locally, you must also change `src/Configur

## Development Without Docker (not recommended)
If you want to do development without docker, you need nodejs/npm and python installed.
It's doable, but it's a hassle since you have to manage at least 3 different processes.
It's doable, but it's a hassle since you have to manage at least 3 different processes:
The back end API server, the front end client server, and the javascript bundler.

1. clone the repository
```
Expand Down Expand Up @@ -64,4 +71,4 @@ If running without docker, use `npx webpack watch` to automatically rebuild js c
Running flask in debug mode will automatically update API changes as you make them.

## Development Guide
Information on the program architecture and guides for certain tasks are available on the [wiki](https://github.com/Helioviewer-Project/helios/wiki)
Information on the application's architecture and guides for certain tasks are available on the [wiki](https://github.com/Helioviewer-Project/helios/wiki)
8 changes: 3 additions & 5 deletions compose.devel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ services:
- config_file
volumes:
- type: bind
source: server
source: ./monorepo/api
target: /app
build:
context: .
Expand All @@ -45,7 +45,7 @@ services:
image: httpd:2.4
volumes:
- type: bind
source: .
source: ./monorepo/app
target: /usr/local/apache2/htdocs
# Runs npm webpack on local environment
webpack:
Expand All @@ -59,16 +59,14 @@ services:
ENTRYPOINT ["sh", "/cmd.sh"]
volumes:
- type: bind
source: .
source: ./monorepo/app
target: /app

secrets:
db_password:
file: ./compose_config/database/db_password.example
config_file:
file: ./compose_config/api/config.example.ini
pfss_host:
file: ./compose_config/pfss_manager/pfss_host.example

volumes:
database-storage:
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
13 changes: 13 additions & 0 deletions monorepo/app/resources/lib/css/flatpickr.min.css

Large diffs are not rendered by default.

File renamed without changes.
2 changes: 1 addition & 1 deletion src/API/favorites.ts → monorepo/app/src/API/favorites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class Favorites {
start: dateRange[0],
end: dateRange[1],
shared: false,
thumbnail: thumbnail,
thumbnail: "",
};
let storedFavorites = this.GetFavorites();
storedFavorites.push(newFavorite);
Expand Down
4 changes: 2 additions & 2 deletions src/API/helios.ts → monorepo/app/src/API/helios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Helios {
* @returns Coordinates
*/
static async GetJp2Observer(id) {
let api_url = Config.helios_api_url + "observer/position?id=" + id;
let api_url = Config.helios_api_url + "observer/position/" + id;
let result = await fetch(api_url);
let data = await result.json();
if (data.hasOwnProperty("error")) {
Expand Down Expand Up @@ -52,7 +52,7 @@ class Helios {
static async GetRecentlyShared(): Promise<Favorite[]> {
let response = await fetch(Config.helios_api_url + "scene/latest/10");
let data = await response.json();
return Favorites.RestoreDates(data);
return Favorites.RestoreDates(data.scenes);
}

static async get_field_lines_gong(
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ test("Add Favorite", () => {
favorites.AddFavorite("data:thumbnail blob");
let storedFavorites = favorites.GetFavorites();
expect(storedFavorites.length).toBe(1);
expect(storedFavorites[0].thumbnail).toBe("data:thumbnail blob");
// thumbnail is ignored for now.
expect(storedFavorites[0].thumbnail).toBe("");
expect(storedFavorites[0].layers).toStrictEqual(scene.GetLayers());
});
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from datetime import datetime
from typing import Iterable

from astropy.coordinates import SkyCoord

from .horizons import Horizons
from helios_exceptions import HeliosException

Expand All @@ -11,7 +9,7 @@
'horizons': Horizons
}

def Get(provider: str, body: str, dates: Iterable[datetime]) -> SkyCoord:
def Get(provider: str, body: str, dates: Iterable[datetime]) -> list[dict]:
try:
# Use lower case so any variation of PrOvIdEr will execute the
# selected provider.
Expand Down
31 changes: 28 additions & 3 deletions server/api/events.py → monorepo/server/api/events.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
from datetime import datetime

from pydantic import BaseModel

from get_heeq import Coordinate
from event_coord import get_event_coordinates, CoordinateSystem
from hek import query_hek
def lookup_hek_events(start_time: str, end_time: str):

class EventPosition(BaseModel):
lat: float
lon: float

class EventCoordinateDetails(BaseModel):
event: EventPosition
notes: str
observer: Coordinate

class Event(BaseModel):
vo_event: dict
coordinates: EventCoordinateDetails

def lookup_hek_events(start_time: datetime, end_time: datetime) -> list[Event]:
"""
Looks up HEK events that occur within the given time range

TODO: This should use the Helioviewer Event Interface since it will be faster.

:param start_time: Beginning of time range to query
:type start_time: str
:param end_time: End of time range to query
Expand All @@ -18,9 +39,13 @@ def lookup_hek_events(start_time: str, end_time: str):
for event in events:
system = CoordinateSystem.from_str(event["event_coordsys"])
coordinates = get_event_coordinates(system, event["event_coord1"], event["event_coord2"], event["event_coord3"], event["event_starttime"].to_datetime(), event["obs_instrument"], event["event_coordunit"])
# Convert Coordinate object to json to prepare it to be sent back to the client
# Convert the event data into a serializable dictionary
event_dict = {k:str(v) for (k,v) in zip(event.keys(), event.values())}
event_dict["coordinates"] = coordinates
results["results"].append(event_dict)
# Python needs a way for us to make a class serializable.
# How is this not a language feature?
coordinates['observer'] = coordinates['observer'].model_dump()
vo_event = Event(vo_event=event_dict, coordinates=coordinates)
results["results"].append(vo_event)
return results

File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions monorepo/server/database/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .base import Model
from .layer import Layer, LayerData
from .scene import Scene, SceneData
from .gong_pfss import GongPFSS
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@ def serialize(item) -> any:
class Model(DeclarativeBase):
def as_dict(self):
return {c.name: serialize(getattr(self, c.name)) for c in self.__table__.columns}
pass

@classmethod
def from_dict(cls, data: dict):
instance = cls()
for key,value in data.items():
setattr(instance, key, value)
return instance
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
from .base import Model
from .scene import Scene
from datetime import datetime
from typing import Optional

from pydantic import BaseModel, Field
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import relationship
from sqlalchemy import Integer, DateTime, ForeignKey, Float

from .base import Model

class Layer(Model):
__tablename__ = "layers"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
Expand All @@ -14,7 +18,7 @@ class Layer(Model):
cadence: Mapped[int] = mapped_column(Integer)
scale: Mapped[float] = mapped_column(Float)
scene_id = mapped_column(ForeignKey("scenes.id"))
scene: Mapped[Scene] = relationship(back_populates="layers")
scene: Mapped["Scene"] = relationship(back_populates="layers")
def __repr__(self) -> str:
return f"Layer(scene={self.scene_id!r}, id={self.id!r}, source={self.source!r}, dates: {self.start!r} to {self.end!r})"

Expand All @@ -24,4 +28,13 @@ def __repr__(self) -> str:
'end',
'cadence',
'scale'
)
)

class LayerData(BaseModel):
id: Optional[int] = None
scene_id: Optional[int] = None
source: int
start: datetime
end: datetime
cadence: int
scale: float
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
from .base import Model
from typing import List
from typing import List, Optional
from datetime import datetime

from pydantic import BaseModel
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import relationship
from sqlalchemy import Integer, DateTime, Text

from .base import Model
from .layer import LayerData

class Scene(Model):
__tablename__ = "scenes"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
Expand All @@ -20,4 +25,12 @@ def as_dict(self):
# super().as_dict manages serializing dates and other "non json serializable" types
out = super().as_dict()
out["layers"] = [l.as_dict() for l in self.layers]
return out
return out

class SceneData(BaseModel):
id: Optional[int] = None
created_at: datetime = datetime.now().isoformat()
start: datetime
end: datetime
thumbnail: str
layers: list[LayerData]
Loading