Commit bdf63914 authored by Duggan, John's avatar Duggan, John
Browse files

Update results tab to work with multiple files and allow configuration of plots

parent dac60b51
Loading
Loading
Loading
Loading
+16 −7
Original line number Diff line number Diff line
@@ -3,8 +3,7 @@
import logging
import zipfile
from io import BytesIO
from pathlib import Path
from typing import Tuple
from typing import List, Tuple

from nova.galaxy import Dataset, Parameters, Tool
from nova.galaxy.interfaces import BasicTool
@@ -38,16 +37,26 @@ class IPSFastranTool(BasicTool):
        tool_params.add_input(name="__job_resource|time", value=self.model.resource_params.time_limit)
        if self.model.resource_params.compute_resource == ComputeOptions.perlmutter:
            tool_params.add_input(name="__job_resource|remote_resource_cloud_nersc", value="nersc")
        self.tool = Tool(id="fusion_ips_fastran")
        self.tool = Tool(id="fusion_ips_fastran_test")

        return self.tool, tool_params

    def get_output_path(self) -> Path:
    def get_output_paths(self) -> List[str]:
        outputs = self.tool.get_results()
        dataset = outputs.get_dataset("output")
        collection = outputs.get_collection("outputs")
        elements = collection.get_content()

        dataset.download("output.nc")
        return Path("output.nc")
        paths = []
        for element in elements:
            dataset = Dataset()
            dataset.id = element["id"]
            dataset.store = collection.store

            path = element["element_identifier"]
            dataset.download(path)
            paths.append(path)

        return paths

    def get_results(self, tool: Tool) -> bytes:
        outputs = tool.get_results()
+23 −1
Original line number Diff line number Diff line
"""Module for the main model."""

import json
from enum import Enum
from pathlib import Path
from typing import Any, Dict, List

from pydantic import BaseModel, Field

with open(Path(__file__).parent / "plot.json") as file_pointer:
    PLOT_JSON = json.load(file_pointer)


class Config(BaseModel):
    """
@@ -18,6 +24,8 @@ class Config(BaseModel):
    shot_number: str = Field(default="000001", title="Shot Number")
    time_id: str = Field(default="00001", title="Time ID")
    file_contents: str = Field(default="")
    result_file: str = Field(default="", title="File to Plot")
    result_files: List[str] = Field(default=[])


class ComputeOptions(str, Enum):
@@ -36,15 +44,29 @@ class ResourceParameters(BaseModel):
    time_limit: int = Field(default=10, ge=1, le=10080, title="Time Limit (minutes)")


class PlotJSON(BaseModel):
    """Contains the plot.json file contents."""

    input_params: Dict[Any, Any] = Field(default=PLOT_JSON)


class MainModel:
    """Main model class."""

    def __init__(self) -> None:
        self.config = Config()
        self.plot_json = PlotJSON()
        self.resource_params = ResourceParameters()

    def get_config_file(self) -> str:
        return self.config.file_contents

    def set_from_json(self, json_data: str) -> None:
    def set_config(self, json_data: str) -> None:
        self.config.file_contents = json_data

    def set_plot(self, json_data: str) -> None:
        self.plot_json = PlotJSON.model_validate_json(json_data)

    def set_results(self, paths: List[str]) -> None:
        self.config.result_files = paths
        self.config.result_file = paths[0]
+6 −4
Original line number Diff line number Diff line
"""Fastran Plotter."""

import json
import os
from pathlib import Path
from typing import Any, Dict

# default plot preferences
import matplotlib
@@ -17,12 +17,14 @@ matplotlib.rcParams["figure.max_open_warning"] = 0
class PlotFastran:
    """Fastran Plotter."""

    def __init__(self, figure: Figure) -> None:
    def __init__(self, figure: Figure, input_params: Dict[str, Any]) -> None:
        self.figure = figure
        with open(Path(os.path.dirname(__file__)) / "plot.json") as plot_json:
            self.input_params = json.load(plot_json)
        self.input_params = input_params

    def load_fastran(self, fn_ncfile: Path) -> None:
        print(fn_ncfile)  # TODO: remove
        fn_ncfile = Path("test.nc")  # TODO: remove

        self.fastran = netCDF4.Dataset(fn_ncfile, "r", format="NETCDF4")
        self.basename = os.path.basename(fn_ncfile)

+4 −2
Original line number Diff line number Diff line
@@ -36,8 +36,10 @@ class ExecutionViewModel:

    async def on_progress(self, _sender: Any, state: WorkState, details: Dict[str, Any]) -> None:
        if state == WorkState.FINISHED:
            path = self.tool.get_output_path()
            self.completion_signal.send(output_path=path)
            paths = self.tool.get_output_paths()
            self.model.set_results(paths)

            self.completion_signal.send()

    def store_factory(self) -> str:
        return "ips_fastran"
+19 −6
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ class MainViewModel:
        self.resource_params_bind = binding.new_bind(
            self.model.resource_params, callback_after_update=self.on_change_resource_params
        )
        self.plot_json_bind = binding.new_bind()
        self.view_state_bind = binding.new_bind(self.view_state)

        # Signals to process events from other view models
@@ -57,6 +58,7 @@ class MainViewModel:

    def init_view(self) -> None:
        self.config_bind.update_in_view(self.model.config)
        self.plot_json_bind.update_in_view(self.model.plot_json.model_dump_json(indent=2))

    def on_change_config_file(self, json_data: str) -> None:
        # Monaco fires input events with internal data that need to be ignored.
@@ -65,7 +67,7 @@ class MainViewModel:

        self.view_state.errors = []
        try:
            self.model.set_from_json(json_data)
            self.model.set_config(json_data)
        except ValidationError as e:
            for error in e.errors():
                msg = ""
@@ -82,26 +84,37 @@ class MainViewModel:
            # You can take actions in Python when specific fields are changed here.
            pass

    def on_change_plot(self, json_data: str) -> None:
        if "_vts" in json_data:
            return

        try:
            self.model.set_plot(json_data)
        except ValidationError:
            pass

    def on_change_resource_params(self, results: Dict[str, Any]) -> None:
        if results["updated"]:
            # You can take actions in Python when specific fields are changed here.
            pass

    def on_completion(self, _sender: Any, output_path: Path) -> None:
        self.update_figure(output_path)
    def on_completion(self, _sender: Any) -> None:
        self.config_bind.update_in_view(self.model.config)

        self.view_state.results_disabled = False
        self.view_state_bind.update_in_view(self.view_state)

        self.update_figure()

    async def on_tool_command(self, _sender: Any, command: str) -> None:
        if command == ToolCommand.START:
            self.view_state.results_disabled = True
            self.view_state.active_tab = 2
            self.view_state_bind.update_in_view(self.view_state)

    def update_figure(self, output_path: Path) -> None:
        plotter = PlotFastran(self.figure)
        plotter.load_fastran(output_path)
    def update_figure(self) -> None:
        plotter = PlotFastran(self.figure, self.model.plot_json.input_params)
        plotter.load_fastran(Path(self.model.config.result_file))
        plotter.set_page()

        self.figure_bind.update_in_view(None)
Loading