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

Add Progress Tracking #775

Merged
merged 11 commits into from
Feb 7, 2025
26 changes: 25 additions & 1 deletion src/hubbleds/base_component_state.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import dataclass, field

from pydantic import computed_field
from cosmicds.state import BaseState
from hubbleds.base_marker import BaseMarker
from solara import Reactive
Expand Down Expand Up @@ -38,6 +38,30 @@ def transition_previous(component_state: Reactive[BaseComponentStateT], force=Tr

class BaseComponentState:
current_step: BaseMarker
_max_step: int = 0 # not included in model

# computed fields are included in the model when serialized
@computed_field
@property
def max_step(self) -> int:
self._max_step = max(self.current_step.value, self._max_step) # type: ignore
return self._max_step

@computed_field
@property
def total_steps(self) -> int:
# compute the total number of steps based on current_steps
# this may be overridden in subclasses
return len(self.current_step.__class__)

@computed_field
@property
def progress(self) -> float:
# first enum value is always 1
first = 1 #self.current_step.first().value
# last = self.total_steps + first #self.current_step.last().value
current = self.current_step.value
return (current - first + 1) / self.total_steps

def is_current_step(self, step: BaseMarker):
return self.current_step.value == step.value
Expand Down
2 changes: 1 addition & 1 deletion src/hubbleds/components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from .spectrum_viewer.spectrum_viewer import SpectrumViewer
from .spectrum_slideshow.spectrum_slideshow import SpectrumSlideshow
from .doppler_slideshow.doppler_slideshow import DopplerSlideshow
from .stage_2_slideshow.stage_2_slideshow import Stage2Slideshow
from .stage_2_slideshow.stage_2_slideshow import Stage2Slideshow, STAGE_2_SLIDESHOW_LENGTH
from .reflect_velocity_slideshow.reflect_velocity_slideshow import (
ReflectVelocitySlideshow,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import reacton.ipyvuetify as rv
from ipyvuetify import VuetifyTemplate

STAGE_2_SLIDESHOW_LENGTH = 13

@solara.component_vue("Stage2Slideshow.vue")
def Stage2Slideshow (
step,
Expand Down
9 changes: 8 additions & 1 deletion src/hubbleds/pages/01-spectra-&-velocity/component_state.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from pydantic import BaseModel, field_validator, Field
from pydantic import BaseModel, field_validator, Field, computed_field
from cosmicds.state import BaseState
from hubbleds.base_marker import BaseMarker
import enum
Expand Down Expand Up @@ -116,6 +116,13 @@ class ComponentState(BaseComponentState, BaseState):
reflection_complete: bool = False
show_dop_cal4_values: bool = False

# computed fields are included in the model when serialized
@computed_field
@property
def total_steps(self) -> int:
# ignore the last marker, which is a dummy marker
return len(Marker) - 1

@field_validator("current_step", mode="before")
def convert_int_to_enum(cls, v: Any) -> Marker:
if isinstance(v, int):
Expand Down
4 changes: 2 additions & 2 deletions src/hubbleds/pages/02-distance-introduction/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import solara
from solara.toestand import Ref

from hubbleds.components import Stage2Slideshow
from hubbleds.components import Stage2Slideshow, STAGE_2_SLIDESHOW_LENGTH
from hubbleds.state import LOCAL_STATE, GLOBAL_STATE, get_multiple_choice, mc_callback
from .component_state import COMPONENT_STATE
from hubbleds.remote import LOCAL_API
Expand Down Expand Up @@ -57,7 +57,7 @@ async def _write_component_state():
Stage2Slideshow(
step = COMPONENT_STATE.value.distance_slideshow_state.step,
max_step_completed = COMPONENT_STATE.value.distance_slideshow_state.max_step_completed,
length = 13,
length = STAGE_2_SLIDESHOW_LENGTH,
titles = [
"1920's Astronomy",
"1920's Astronomy",
Expand Down
15 changes: 13 additions & 2 deletions src/hubbleds/pages/02-distance-introduction/component_state.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import solara
import enum
from pydantic import BaseModel
from pydantic import BaseModel, computed_field
from cosmicds.state import BaseState
from hubbleds.base_marker import BaseMarker
from hubbleds.base_component_state import BaseComponentState
from hubbleds.components import STAGE_2_SLIDESHOW_LENGTH

class Marker(enum.Enum, BaseMarker):
mea_dis1 = enum.auto()
Expand All @@ -16,5 +17,15 @@ class ComponentState(BaseComponentState, BaseState):
current_step: Marker = Marker.mea_dis1
stage_id: str = "distance_introduction"
distance_slideshow_state: DistanceSlideshow = DistanceSlideshow()


@computed_field
@property
def total_steps(self) -> int:
return STAGE_2_SLIDESHOW_LENGTH

@computed_field
@property
def progress(self) -> float:
return (self.distance_slideshow_state.max_step_completed + 1) / self.total_steps

COMPONENT_STATE = solara.reactive(ComponentState())
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import solara
import enum

from pydantic import field_validator
from pydantic import field_validator, computed_field

from cosmicds.state import BaseState
from hubbleds.base_marker import BaseMarker
Expand Down Expand Up @@ -67,6 +67,13 @@ class ComponentState(BaseComponentState, BaseState):
angular_size_line: Optional[float | int] = None
distance_line: Optional[float | int] = None

@computed_field
@property
def total_steps(self) -> int:
# ignore the last marker, which is a dummy marker
return len(Marker) - 1


@field_validator("current_step", mode="before")
def convert_int_to_enum(cls, v: Any) -> Marker:
if isinstance(v, int):
Expand Down
13 changes: 12 additions & 1 deletion src/hubbleds/pages/04-explore-data/component_state.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import solara

from pydantic import BaseModel, field_validator
from pydantic import BaseModel, field_validator, computed_field

from cosmicds.state import BaseState
from hubbleds.base_marker import BaseMarker
Expand Down Expand Up @@ -49,6 +49,17 @@ class ComponentState(BaseComponentState, BaseState):
best_fit_gal_vel: float = 100
best_fit_gal_dist: float = 8000
class_data_displayed: bool = False

_max_step: int = 0 # not included in model

# computed fields are included in the model when serialized
@computed_field
@property
def total_steps(self) -> int:
# ignore the last marker, which is a dummy marker
return len(Marker) - 1



@field_validator("current_step", mode="before")
def convert_int_to_enum(cls, v: Any) -> Marker:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import solara

from pydantic import BaseModel, field_validator
from pydantic import BaseModel, field_validator, computed_field

from cosmicds.state import BaseState
from hubbleds.base_marker import BaseMarker
Expand Down Expand Up @@ -63,6 +63,14 @@ class ComponentState(BaseComponentState, BaseState):
uncertainty_state: UncertaintyState = UncertaintyState()
uncertainty_slideshow_finished: bool = False
class_best_fit_clicked: bool = False

@computed_field
@property
def total_steps(self) -> int:
# ignore the last marker, which is a dummy marker
return len(Marker) - 1



@field_validator("current_step", mode="before")
def convert_int_to_enum(cls, v: Any) -> Marker:
Expand Down
22 changes: 21 additions & 1 deletion src/hubbleds/pages/component_state.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import solara
import enum
from pydantic import BaseModel
from pydantic import BaseModel, computed_field
from cosmicds.state import BaseState
from hubbleds.base_marker import BaseMarker
from hubbleds.base_component_state import BaseComponentState
Expand All @@ -15,5 +15,25 @@ class ComponentState(BaseComponentState, BaseState):
current_step: Marker = Marker.int_sli1
stage_id: str = "introduction"
intro_slideshow_state: IntroSlideshow = IntroSlideshow()

_max_step: int = 0 # not included in model

@computed_field
@property
def total_steps(self) -> int:
return len(Marker)

# computed fields are included in the model when serialized
@computed_field
@property
def max_step(self) -> int:
self._max_step = max(self.current_step.value, self._max_step) # type: ignore
return self._max_step

@computed_field
@property
def progress(self) -> float:
return round((self._max_step + 1) / self.total_steps, 3)


COMPONENT_STATE = solara.reactive(ComponentState())