Loading code/episode_5/src/nova_tutorial/app/models/fractal.py +12 −12 Original line number Diff line number Diff line import os from base64 import b64encode from pydantic import BaseModel, Field from nova.galaxy import Connection, Parameters, Tool class Fractal(BaseModel): fractal_type: str = Field(default="mandelbrot", description="Type of fractal to generate") fractal_type_options: list[str] = ["mandelbrot", "julia", "random", "markus"] fractal_type: str = Field(default="mandelbrot") galaxy_url: str = Field(default_factory=lambda: os.getenv("GALAXY_URL"), description="NDIP Galaxy URL") galaxy_key: str = Field(default_factory=lambda: os.getenv("GALAXY_API_KEY"), description="NDIP Galaxy API Key") def set_fractal_type(self, fractal_type: str): self.fractal_type = fractal_type image_data: str = Field(default="", description="Base64 encoded PNG") def run_fractal_tool(self): """Runs the fractal tool with the current fractal type.""" if not self.galaxy_url or not self.galaxy_key: raise Exception( "You must specify GALAXY_URL and GALAXY_API_KEY as environment variables." ) conn = Connection(galaxy_url=self.galaxy_url, galaxy_key=self.galaxy_key) tool = Tool(id="neutrons_fractal") params = Parameters() params.add_input(name="option", value=self.fractal_type) with conn.connect() as galaxy_connection: data_store = galaxy_connection.create_data_store(name="fractal_store") data_store.persist() tool.run(data_store, params) print("Executing fractal tool. This might take a few minutes.") output = tool.run(data_store, params) output.get_dataset("output").download("tmp.png") with open("tmp.png", "rb") as image_file: self.image_data = f"data:image/png;base64,{b64encode(image_file.read()).decode()}" print("Fractal tool finished successfully.") code/episode_5/src/nova_tutorial/app/view_models/main.py +1 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ class MainViewModel: fractal_tool_thread = Thread(target=self.run_fractal_in_background, daemon=True) fractal_tool_thread.start() # We also need to know when the tool is done running so that we can know when to update the view. create_task(self.monitor_fractal()) def run_fractal_in_background(self) -> None: Loading code/episode_5/src/nova_tutorial/app/views/fractal_tab.py +8 −7 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ from trame.widgets import vuetify3 as vuetify from nova.trame.view.components import InputField from nova_tutorial.app.view_models.main import MainViewModel class FractalTab: def __init__(self, view_model: MainViewModel) -> None: self.view_model = view_model Loading @@ -10,11 +11,11 @@ class FractalTab: self.create_ui() def create_ui(self) -> None: InputField(v_model="config.fractal.fractal_type", classes="mb-2") vuetify.VProgressCircular(v_if="running", indeterminate=True) vuetify.VBtn( "Run Fractal", v_else=True, click=self.view_model.run_fractal, # calls the run_fractal_tool method InputField( v_model="config.fractal.fractal_type", classes="mb-2", items="config.fractal.fractal_type_options", type="select", ) vuetify.VImg(src=("config.fractal.image_data",), height="400", width="400") vuetify.VProgressCircular(v_if="running", indeterminate=True) vuetify.VImg(v_else=True, src=("config.fractal.image_data",), height="400", width="400") code/episode_5/src/nova_tutorial/app/views/main.py +9 −5 Original line number Diff line number Diff line Loading @@ -4,14 +4,15 @@ import logging from nova.mvvm.trame_binding import TrameBinding from nova.trame import ThemedApp from nova.trame.view import layouts from trame.app import get_server from trame.widgets import vuetify3 as vuetify from ..mvvm_factory import create_viewmodels from ..view_models.main import MainViewModel from .tab_content_panel import TabContentPanel from .tabs_panel import TabsPanel logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) Loading @@ -23,16 +24,15 @@ class MainApp(ThemedApp): super().__init__() self.server = get_server(None, client_type="vue3") binding = TrameBinding(self.server.state) self.server.state.trame__title = "Nova Tutorial" self.view_models = create_viewmodels(binding) self.view_model: MainViewModel = self.view_models["main"] self.create_ui() def create_ui(self) -> None: self.state.trame__title = "Nova Tutorial" self.state.trame__title = "Fractal Tool GUI" with super().create_ui() as layout: layout.toolbar_title.set_text("Nova Tutorial") layout.toolbar_title.set_text("Fractal Tool GUI") with layout.pre_content: TabsPanel(self.view_models["main"]) with layout.content: Loading @@ -41,5 +41,9 @@ class MainApp(ThemedApp): self.view_models["main"], ) with layout.post_content: pass with layouts.HBoxLayout(classes="my-2", halign="center"): vuetify.VBtn( "Run Fractal", click=self.view_model.run_fractal, # calls the run_fractal_tool method ) return layout code/episode_5/src/nova_tutorial/app/views/sample_tab_1.py +3 −10 Original line number Diff line number Diff line """Module for the Sample Tab 1.""" from nova.trame.view.components import InputField, RemoteFileInput from nova.trame.view import layouts from trame.widgets import vuetify3 as vuetify class SampleTab1: """Sample tab 1 view class. Renders text input for username.""" Loading @@ -11,11 +10,5 @@ class SampleTab1: self.create_ui() def create_ui(self) -> None: with layouts.VBoxLayout(classes="ma-2"): # Overall vertical layout InputField(v_model="config.username", label="Username") with layouts.HBoxLayout(): # Horizontal layout for first and last name InputField(v_model="config.firstName", label="First Name") InputField(v_model="config.lastName", label="Last Name") vuetify.VCheckbox(label="Remember me") vuetify.VSwitch(label="Enable Notifications") RemoteFileInput(v_model="config.file", base_paths=["/SNS"]) RemoteFileInput(v_model="file", base_paths=["/HFIR", "/SNS"]) InputField(v_model="config.username") Loading
code/episode_5/src/nova_tutorial/app/models/fractal.py +12 −12 Original line number Diff line number Diff line import os from base64 import b64encode from pydantic import BaseModel, Field from nova.galaxy import Connection, Parameters, Tool class Fractal(BaseModel): fractal_type: str = Field(default="mandelbrot", description="Type of fractal to generate") fractal_type_options: list[str] = ["mandelbrot", "julia", "random", "markus"] fractal_type: str = Field(default="mandelbrot") galaxy_url: str = Field(default_factory=lambda: os.getenv("GALAXY_URL"), description="NDIP Galaxy URL") galaxy_key: str = Field(default_factory=lambda: os.getenv("GALAXY_API_KEY"), description="NDIP Galaxy API Key") def set_fractal_type(self, fractal_type: str): self.fractal_type = fractal_type image_data: str = Field(default="", description="Base64 encoded PNG") def run_fractal_tool(self): """Runs the fractal tool with the current fractal type.""" if not self.galaxy_url or not self.galaxy_key: raise Exception( "You must specify GALAXY_URL and GALAXY_API_KEY as environment variables." ) conn = Connection(galaxy_url=self.galaxy_url, galaxy_key=self.galaxy_key) tool = Tool(id="neutrons_fractal") params = Parameters() params.add_input(name="option", value=self.fractal_type) with conn.connect() as galaxy_connection: data_store = galaxy_connection.create_data_store(name="fractal_store") data_store.persist() tool.run(data_store, params) print("Executing fractal tool. This might take a few minutes.") output = tool.run(data_store, params) output.get_dataset("output").download("tmp.png") with open("tmp.png", "rb") as image_file: self.image_data = f"data:image/png;base64,{b64encode(image_file.read()).decode()}" print("Fractal tool finished successfully.")
code/episode_5/src/nova_tutorial/app/view_models/main.py +1 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ class MainViewModel: fractal_tool_thread = Thread(target=self.run_fractal_in_background, daemon=True) fractal_tool_thread.start() # We also need to know when the tool is done running so that we can know when to update the view. create_task(self.monitor_fractal()) def run_fractal_in_background(self) -> None: Loading
code/episode_5/src/nova_tutorial/app/views/fractal_tab.py +8 −7 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ from trame.widgets import vuetify3 as vuetify from nova.trame.view.components import InputField from nova_tutorial.app.view_models.main import MainViewModel class FractalTab: def __init__(self, view_model: MainViewModel) -> None: self.view_model = view_model Loading @@ -10,11 +11,11 @@ class FractalTab: self.create_ui() def create_ui(self) -> None: InputField(v_model="config.fractal.fractal_type", classes="mb-2") vuetify.VProgressCircular(v_if="running", indeterminate=True) vuetify.VBtn( "Run Fractal", v_else=True, click=self.view_model.run_fractal, # calls the run_fractal_tool method InputField( v_model="config.fractal.fractal_type", classes="mb-2", items="config.fractal.fractal_type_options", type="select", ) vuetify.VImg(src=("config.fractal.image_data",), height="400", width="400") vuetify.VProgressCircular(v_if="running", indeterminate=True) vuetify.VImg(v_else=True, src=("config.fractal.image_data",), height="400", width="400")
code/episode_5/src/nova_tutorial/app/views/main.py +9 −5 Original line number Diff line number Diff line Loading @@ -4,14 +4,15 @@ import logging from nova.mvvm.trame_binding import TrameBinding from nova.trame import ThemedApp from nova.trame.view import layouts from trame.app import get_server from trame.widgets import vuetify3 as vuetify from ..mvvm_factory import create_viewmodels from ..view_models.main import MainViewModel from .tab_content_panel import TabContentPanel from .tabs_panel import TabsPanel logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) Loading @@ -23,16 +24,15 @@ class MainApp(ThemedApp): super().__init__() self.server = get_server(None, client_type="vue3") binding = TrameBinding(self.server.state) self.server.state.trame__title = "Nova Tutorial" self.view_models = create_viewmodels(binding) self.view_model: MainViewModel = self.view_models["main"] self.create_ui() def create_ui(self) -> None: self.state.trame__title = "Nova Tutorial" self.state.trame__title = "Fractal Tool GUI" with super().create_ui() as layout: layout.toolbar_title.set_text("Nova Tutorial") layout.toolbar_title.set_text("Fractal Tool GUI") with layout.pre_content: TabsPanel(self.view_models["main"]) with layout.content: Loading @@ -41,5 +41,9 @@ class MainApp(ThemedApp): self.view_models["main"], ) with layout.post_content: pass with layouts.HBoxLayout(classes="my-2", halign="center"): vuetify.VBtn( "Run Fractal", click=self.view_model.run_fractal, # calls the run_fractal_tool method ) return layout
code/episode_5/src/nova_tutorial/app/views/sample_tab_1.py +3 −10 Original line number Diff line number Diff line """Module for the Sample Tab 1.""" from nova.trame.view.components import InputField, RemoteFileInput from nova.trame.view import layouts from trame.widgets import vuetify3 as vuetify class SampleTab1: """Sample tab 1 view class. Renders text input for username.""" Loading @@ -11,11 +10,5 @@ class SampleTab1: self.create_ui() def create_ui(self) -> None: with layouts.VBoxLayout(classes="ma-2"): # Overall vertical layout InputField(v_model="config.username", label="Username") with layouts.HBoxLayout(): # Horizontal layout for first and last name InputField(v_model="config.firstName", label="First Name") InputField(v_model="config.lastName", label="Last Name") vuetify.VCheckbox(label="Remember me") vuetify.VSwitch(label="Enable Notifications") RemoteFileInput(v_model="config.file", base_paths=["/SNS"]) RemoteFileInput(v_model="file", base_paths=["/HFIR", "/SNS"]) InputField(v_model="config.username")