gistory¶
Story
¶
Source code in maeson/gistory.py
class Story:
def __init__(self, scenes):
"""
A sequence of scenes forming a narrative.
"""
self.scenes = scenes
self.index = 0
def _current_scene(self):
return self.scenes[self.index]
def _next_scene(self):
if self.index < len(self.scenes) - 1:
self.index += 1
return self._current_scene()
def _previous_scene(self):
if self.index > 0:
self.index -= 1
return self._current_scene()
__init__(self, scenes)
special
¶
A sequence of scenes forming a narrative.
Source code in maeson/gistory.py
def __init__(self, scenes):
"""
A sequence of scenes forming a narrative.
"""
self.scenes = scenes
self.index = 0
StoryController
¶
Source code in maeson/gistory.py
class StoryController:
def __init__(self, story, map_obj: Map):
"""
Connects a Story object to a map and widget-based UI.
"""
self.story = story
self.map = map_obj
self.current_layers = []
self.next_button = widgets.Button(description="Next")
self.back_button = widgets.Button(description="Back")
self.next_button.on_click(self._next_scene)
self.back_button.on_click(self._previous_scene)
self.controls = widgets.HBox([self.back_button, self.next_button])
self.interface = widgets.VBox([self.map, self.controls])
self._update_scene()
def _update_scene(self):
scene = self.story._current_scene()
# 1) Reset view
self.map.center = scene.center
self.map.zoom = scene.zoom
# 2) Clear out any previous overlays
self._clear_overlays()
self.current_layers.clear()
# 3) Re‑add each layer using your Map methods
for ld in scene.layers:
t = ld["type"]
name = ld.get("name")
try:
if t == "geojson":
if "data" in ld:
layer = GeoJSON(data=ld["data"], name=name)
self.map.add_layer(layer)
else:
layer = self.map.add_geojson(ld["path"], name=name)
elif t == "tile":
layer = self.map.add_tile(url=ld["url"], name=name)
elif t == "image":
layer = self.map.add_image(
url=ld["path"],
bounds=tuple(tuple(c) for c in ld["bounds"]),
name=name,
)
elif t == "video":
layer = self.map.add_video(
url=ld["path"],
bounds=tuple(tuple(c) for c in ld["bounds"]),
name=name,
)
elif t == "raster":
layer = self.map.add_raster(
ld["path"], name=name, zoom_to_layer=False
)
elif t == "wms":
layer = self.map.add_wms_layer(url=ld["url"], name=name)
elif t == "earthengine":
# your Map.add_earthengine takes ee_object + vis_params
layer = self.map.add_earthengine(
ee_object=ld["ee_id"],
vis_params=ld.get("vis_params", {}),
name=name,
)
else:
print(f"Unsupported layer type: {t}")
continue
self.current_layers.append(layer)
except Exception as e:
print(f"❌ Failed to add {t} layer “{name}”: {e}")
# 4) Finally, run any custom code
if scene.custom_code.strip():
try:
exec(scene.custom_code, {}, {"map": self.map})
except Exception as e:
print(f"⚠️ Error in scene code: {e}")
def _clear_overlays(self):
# 1) Remove map overlays
for lyr in list(self.map.layers)[1:]:
self.map.remove_layer(lyr)
def _next_scene(self, _=None):
self.story._next_scene()
self._update_scene()
def _previous_scene(self, _=None):
self.story._previous_scene()
self._update_scene()
def display(self):
from IPython.display import display
display(self.interface)
__init__(self, story, map_obj)
special
¶
Connects a Story object to a map and widget-based UI.
Source code in maeson/gistory.py
def __init__(self, story, map_obj: Map):
"""
Connects a Story object to a map and widget-based UI.
"""
self.story = story
self.map = map_obj
self.current_layers = []
self.next_button = widgets.Button(description="Next")
self.back_button = widgets.Button(description="Back")
self.next_button.on_click(self._next_scene)
self.back_button.on_click(self._previous_scene)
self.controls = widgets.HBox([self.back_button, self.next_button])
self.interface = widgets.VBox([self.map, self.controls])
self._update_scene()