Loading code/episode_7/poetry.lock +3 −3 Original line number Diff line number Diff line Loading @@ -1410,12 +1410,12 @@ tomli = ">=2.0.2,<3.0.0" [[package]] name = "nova-mvvm" version = "0.8.0" version = "0.9.0" description = "A Python Package for Model-View-ViewModel pattern" optional = false python-versions = "<4.0,>=3.10" files = [ {file = "nova_mvvm-0.8.0-py3-none-any.whl", hash = "sha256:494e87915785dee46f01d06bc723dd29fba1724042fdf7fa102789a2e524d055"}, {file = "nova_mvvm-0.9.0-py3-none-any.whl", hash = "sha256:60c70f8579b155e7081548e8aec9e77de497fa33ac569096015cffe27ef0f796"}, ] [package.dependencies] Loading Loading @@ -3003,4 +3003,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = "^3.10" content-hash = "f9931d7baca4d3cc5354430155449d43e5364af4fa95648bd39137bb8b05f375" content-hash = "5cb22adddafd5b2416c7533855cfdaac1ca49f636272dcf41713f76fceb65da1" code/episode_7/pyproject.toml +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ packages = [ [tool.poetry.dependencies] python = "^3.10" nova-galaxy = "^0.4.0" nova-mvvm = "0.8.0" nova-mvvm = "0.9.0" nova-trame = "0.14.0" pandas = "^2.2.3" plotly = "^5.24.1" Loading code/episode_7/src/nova_tutorial/main.py +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ from nova_tutorial.views.visualization import VisualizationApp def main(): def main() -> None: app = VisualizationApp() app.server.start() Loading code/episode_7/src/nova_tutorial/models/plotly.py +24 −28 Original line number Diff line number Diff line """Configuration for the Plotly example.""" from typing import Any from plotly.data import iris # type: ignore import plotly.graph_objects as go from plotly.data import iris from pydantic import BaseModel, Field, computed_field IRIS_DATA = iris() Loading @@ -11,35 +10,32 @@ IRIS_DATA = iris() class PlotlyConfig(BaseModel): """Configuration class for the Plotly example.""" axis_options: list[str] = ["sepal_length", "sepal_width", "petal_length", "petal_width", "species", "species_id"] axis_options: list[str] = ["sepal_length", "sepal_width", "petal_length", "petal_width"] x_axis: str = Field(default="sepal_length", title="X Axis") y_axis: str = Field(default="sepal_width", title="Y Axis") z_axis: str = Field(default="petal_length", title="Z Axis") plot_data: Any = None z_axis: str = Field(default="petal_length", title="Color") plot_type: str = Field(default="scatter", title="Plot Type") plot_type_options: list[str] = ["heatmap", "scatter"] @computed_field # type: ignore @property def is_scatter(self) -> bool: return self.plot_type == "scatter" def update(self) -> None: self.plot_data = { "data": [ { "x": IRIS_DATA[self.x_axis].tolist(), "y": IRIS_DATA[self.y_axis].tolist(), "z": IRIS_DATA[self.z_axis].tolist(), "type": self.plot_type, "mode": "markers", "colorbar": {"title": self.z_axis}, "colorscale": "Viridis", } ], "layout": { "title": "Iris Flower Data Set", "xaxis": {"fixedrange": True, "title": self.x_axis}, "yaxis": {"fixedrange": True, "title": self.y_axis}, }, } def is_not_heatmap(self) -> bool: return self.plot_type != "heatmap" def get_figure(self) -> go.Figure: match self.plot_type: case "heatmap": plot_data = go.Heatmap(x=IRIS_DATA[self.x_axis], y=IRIS_DATA[self.y_axis], z=IRIS_DATA[self.z_axis]) case "scatter": plot_data = go.Scatter(x=IRIS_DATA[self.x_axis], y=IRIS_DATA[self.y_axis], mode="markers") case _: raise ValueError(f"Invalid plot type: {self.plot_type}") figure = go.Figure(plot_data) figure.update_layout( title={"text": f"{self.plot_type}"}, xaxis={"title": {"text": self.x_axis}}, yaxis={"title": {"text": self.y_axis}}, ) return figure code/episode_7/src/nova_tutorial/models/pyvista.py +7 −10 Original line number Diff line number Diff line """Configuration for the PyVista example.""" from typing import Optional from pydantic import BaseModel, Field from pyvista import Plotter, examples Loading @@ -16,12 +14,11 @@ class PyVistaConfig(BaseModel): colormap: str = Field(default="viridis", title="Color Transfer Function") opacity: str = Field(default="linear", title="Opacity Transfer Function") def update(self, plotter: Optional[Plotter]) -> None: # TODO: This should not need to fully re-render each time. However, something about this setup is making # view.update() not work. if plotter: def render(self, plotter: Plotter) -> None: # If re-rendering the volume on changes isn't acceptable, then you may need to switch to using VTK directly due # limitations of the PyVista volume rendering engine. plotter.clear() plotter.add_volume(KNEE_DATA, cmap=self.colormap, opacity=self.opacity, show_scalar_bar=False) plotter.render() plotter.view_isometric() # type: ignore plotter.view_isometric() Loading
code/episode_7/poetry.lock +3 −3 Original line number Diff line number Diff line Loading @@ -1410,12 +1410,12 @@ tomli = ">=2.0.2,<3.0.0" [[package]] name = "nova-mvvm" version = "0.8.0" version = "0.9.0" description = "A Python Package for Model-View-ViewModel pattern" optional = false python-versions = "<4.0,>=3.10" files = [ {file = "nova_mvvm-0.8.0-py3-none-any.whl", hash = "sha256:494e87915785dee46f01d06bc723dd29fba1724042fdf7fa102789a2e524d055"}, {file = "nova_mvvm-0.9.0-py3-none-any.whl", hash = "sha256:60c70f8579b155e7081548e8aec9e77de497fa33ac569096015cffe27ef0f796"}, ] [package.dependencies] Loading Loading @@ -3003,4 +3003,4 @@ propcache = ">=0.2.0" [metadata] lock-version = "2.0" python-versions = "^3.10" content-hash = "f9931d7baca4d3cc5354430155449d43e5364af4fa95648bd39137bb8b05f375" content-hash = "5cb22adddafd5b2416c7533855cfdaac1ca49f636272dcf41713f76fceb65da1"
code/episode_7/pyproject.toml +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ packages = [ [tool.poetry.dependencies] python = "^3.10" nova-galaxy = "^0.4.0" nova-mvvm = "0.8.0" nova-mvvm = "0.9.0" nova-trame = "0.14.0" pandas = "^2.2.3" plotly = "^5.24.1" Loading
code/episode_7/src/nova_tutorial/main.py +1 −1 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ from nova_tutorial.views.visualization import VisualizationApp def main(): def main() -> None: app = VisualizationApp() app.server.start() Loading
code/episode_7/src/nova_tutorial/models/plotly.py +24 −28 Original line number Diff line number Diff line """Configuration for the Plotly example.""" from typing import Any from plotly.data import iris # type: ignore import plotly.graph_objects as go from plotly.data import iris from pydantic import BaseModel, Field, computed_field IRIS_DATA = iris() Loading @@ -11,35 +10,32 @@ IRIS_DATA = iris() class PlotlyConfig(BaseModel): """Configuration class for the Plotly example.""" axis_options: list[str] = ["sepal_length", "sepal_width", "petal_length", "petal_width", "species", "species_id"] axis_options: list[str] = ["sepal_length", "sepal_width", "petal_length", "petal_width"] x_axis: str = Field(default="sepal_length", title="X Axis") y_axis: str = Field(default="sepal_width", title="Y Axis") z_axis: str = Field(default="petal_length", title="Z Axis") plot_data: Any = None z_axis: str = Field(default="petal_length", title="Color") plot_type: str = Field(default="scatter", title="Plot Type") plot_type_options: list[str] = ["heatmap", "scatter"] @computed_field # type: ignore @property def is_scatter(self) -> bool: return self.plot_type == "scatter" def update(self) -> None: self.plot_data = { "data": [ { "x": IRIS_DATA[self.x_axis].tolist(), "y": IRIS_DATA[self.y_axis].tolist(), "z": IRIS_DATA[self.z_axis].tolist(), "type": self.plot_type, "mode": "markers", "colorbar": {"title": self.z_axis}, "colorscale": "Viridis", } ], "layout": { "title": "Iris Flower Data Set", "xaxis": {"fixedrange": True, "title": self.x_axis}, "yaxis": {"fixedrange": True, "title": self.y_axis}, }, } def is_not_heatmap(self) -> bool: return self.plot_type != "heatmap" def get_figure(self) -> go.Figure: match self.plot_type: case "heatmap": plot_data = go.Heatmap(x=IRIS_DATA[self.x_axis], y=IRIS_DATA[self.y_axis], z=IRIS_DATA[self.z_axis]) case "scatter": plot_data = go.Scatter(x=IRIS_DATA[self.x_axis], y=IRIS_DATA[self.y_axis], mode="markers") case _: raise ValueError(f"Invalid plot type: {self.plot_type}") figure = go.Figure(plot_data) figure.update_layout( title={"text": f"{self.plot_type}"}, xaxis={"title": {"text": self.x_axis}}, yaxis={"title": {"text": self.y_axis}}, ) return figure
code/episode_7/src/nova_tutorial/models/pyvista.py +7 −10 Original line number Diff line number Diff line """Configuration for the PyVista example.""" from typing import Optional from pydantic import BaseModel, Field from pyvista import Plotter, examples Loading @@ -16,12 +14,11 @@ class PyVistaConfig(BaseModel): colormap: str = Field(default="viridis", title="Color Transfer Function") opacity: str = Field(default="linear", title="Opacity Transfer Function") def update(self, plotter: Optional[Plotter]) -> None: # TODO: This should not need to fully re-render each time. However, something about this setup is making # view.update() not work. if plotter: def render(self, plotter: Plotter) -> None: # If re-rendering the volume on changes isn't acceptable, then you may need to switch to using VTK directly due # limitations of the PyVista volume rendering engine. plotter.clear() plotter.add_volume(KNEE_DATA, cmap=self.colormap, opacity=self.opacity, show_scalar_bar=False) plotter.render() plotter.view_isometric() # type: ignore plotter.view_isometric()