Commit 88539c7c authored by Duggan, John's avatar Duggan, John
Browse files

Everything except state reset works

parent 21775326
Loading
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -22,10 +22,13 @@ class DataSelectorModel:
    def __init__(self, state: DataSelectorState) -> None:
        self.state: DataSelectorState = state

    def set_binding_parameters(self, directory: str, extensions: List[str], subdirectory: str) -> None:
        self.state.directory = directory
        self.state.extensions = extensions
        self.state.subdirectory = subdirectory
    def set_binding_parameters(self, **kwargs: Any) -> None:
        if "directory" in kwargs:
            self.state.directory = kwargs["directory"]
        if "extensions" in kwargs:
            self.state.extensions = kwargs["extensions"]
        if "subdirectory" in kwargs:
            self.state.subdirectory = kwargs["subdirectory"]

    def sort_directories(self, directories: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        # Sort the current level of dictionaries
+13 −23
Original line number Diff line number Diff line
@@ -107,23 +107,21 @@ class NeutronDataSelectorState(DataSelectorState):
class NeutronDataSelectorModel(DataSelectorModel):
    """Manages file system interactions for the DataSelector widget."""

    def __init__(
        self,
        state: NeutronDataSelectorState,
        facility: str,
        instrument: str,
        extensions: List[str],
        prefix: str,
        allow_custom_directories: bool,
    ) -> None:
        super().__init__(state, "", extensions, prefix)
    def __init__(self, state: NeutronDataSelectorState) -> None:
        super().__init__(state)
        self.state: NeutronDataSelectorState = state

        self.state.facility = facility
        self.state.instrument = instrument
        self.state.extensions = extensions
        self.state.prefix = prefix
        self.state.allow_custom_directories = allow_custom_directories
    def set_binding_parameters(self, **kwargs: Any) -> None:
        super().set_binding_parameters(**kwargs)

        if "facility" in kwargs:
            self.state.facility = kwargs["facility"]
        if "instrument" in kwargs:
            self.state.instrument = kwargs["instrument"]
        if "experiment" in kwargs:
            self.state.experiment = kwargs["experiment"]
        if "allow_custom_directories" in kwargs:
            self.state.allow_custom_directories = kwargs["allow_custom_directories"]

    def get_facilities(self) -> List[str]:
        return natsorted(self.state.get_facilities())
@@ -183,11 +181,3 @@ class NeutronDataSelectorModel(DataSelectorModel):
            return []

        return self.get_datafiles_from_path(base_path)

    def set_state(self, facility: Optional[str], instrument: Optional[str], experiment: Optional[str]) -> None:
        if facility is not None:
            self.state.facility = facility
        if instrument is not None:
            self.state.instrument = instrument
        if experiment is not None:
            self.state.experiment = experiment
+12 −24
Original line number Diff line number Diff line
"""View Implementation for DataSelector."""

from asyncio import ensure_future, sleep
from pathlib import Path
from typing import Any, List, Tuple, Union, cast
from warnings import warn

@@ -117,11 +116,11 @@ class DataSelector(datagrid.VGrid):
            self._v_model_name_in_state = v_model[0].split(".")[0]

        self._directory = directory
        self._last_directory = self._directory
        self._last_directory = get_state_param(self.state, self._directory)
        self._extensions = extensions if extensions is not None else []
        self._last_extensions = self._extensions
        self._last_extensions = get_state_param(self.state, self._extensions)
        self._subdirectory = subdirectory
        self._last_subdirectory = self._subdirectory
        self._last_subdirectory = get_state_param(self.state, self._subdirectory)
        self._refresh_rate = refresh_rate
        self._select_strategy = select_strategy

@@ -138,7 +137,7 @@ class DataSelector(datagrid.VGrid):

        self.create_model()
        self.create_viewmodel()
        self.setup_binding_listeners()
        self.setup_bindings()
        self._vm.update_view()

        self.create_ui(**kwargs)
@@ -161,12 +160,6 @@ class DataSelector(datagrid.VGrid):

            with GridLayout(columns=2, classes="flex-1-0 h-0", valign="start"):
                if isinstance(self._subdirectory, tuple) or not self._subdirectory:
                    if self._subdirectory:
                        initial_subdirectory = str(
                            Path(get_state_param(self.state, self._directory))
                            / get_state_param(self.state, self._subdirectory)
                        )
                        print(initial_subdirectory)
                    with html.Div(classes="d-flex flex-column h-100 overflow-hidden"):
                        vuetify.VListSubheader("Available Directories", classes="flex-0-1 justify-center px-0")
                        vuetify.VTreeview(
@@ -195,6 +188,7 @@ class DataSelector(datagrid.VGrid):
                        "    prop: 'title',"
                        "}]",
                    ),
                    column_span=1 if isinstance(self._subdirectory, tuple) or not self._subdirectory else 2,
                    frame_size=10,
                    hide_attribution=True,
                    id=self._revogrid_id,
@@ -270,15 +264,15 @@ class DataSelector(datagrid.VGrid):
            "`nova.trame.view.components.ornl`."
        )

    def setup_binding_listeners(self) -> None:
    def setup_bindings(self) -> None:
        set_state_param(self.state, self._directory)
        set_state_param(self.state, self._extensions)
        set_state_param(self.state, self._subdirectory)

        self._vm.set_binding_parameters(
            get_state_param(self.state, self._directory),
            get_state_param(self.state, self._extensions),
            get_state_param(self.state, self._subdirectory),
            directory=get_state_param(self.state, self._directory),
            extensions=get_state_param(self.state, self._extensions),
            subdirectory=get_state_param(self.state, self._subdirectory),
        )
        if isinstance(self._subdirectory, tuple):
            self._subdirectory = (self._subdirectory[0],)
@@ -291,9 +285,7 @@ class DataSelector(datagrid.VGrid):
                if directory != self._last_directory:
                    self._last_directory = directory
                    self._vm.set_binding_parameters(
                        get_state_param(self.state, self._directory),
                        get_state_param(self.state, self._extensions),
                        get_state_param(self.state, self._subdirectory),
                        directory=set_state_param(self.state, self._directory, directory),
                    )

        if isinstance(self._extensions, tuple):
@@ -304,9 +296,7 @@ class DataSelector(datagrid.VGrid):
                if extensions != self._last_extensions:
                    self._last_extensions = extensions
                    self._vm.set_binding_parameters(
                        get_state_param(self.state, self._directory),
                        get_state_param(self.state, self._extensions),
                        get_state_param(self.state, self._subdirectory),
                        extensions=set_state_param(self.state, self._extensions, extensions),
                    )

        if isinstance(self._subdirectory, tuple):
@@ -317,9 +307,7 @@ class DataSelector(datagrid.VGrid):
                if subdirectory != self._last_subdirectory:
                    self._last_subdirectory = subdirectory
                    self._vm.set_binding_parameters(
                        get_state_param(self.state, self._directory),
                        get_state_param(self.state, self._extensions),
                        get_state_param(self.state, self._subdirectory),
                        subdirectory=set_state_param(self.state, self._subdirectory, subdirectory),
                    )

    async def _refresh_loop(self) -> None:
+120 −40
Original line number Diff line number Diff line
"""View Implementation for DataSelector."""

from typing import Any, List, Optional, Tuple, Union
from typing import Any, Dict, List, Tuple, Union
from warnings import warn

from trame.app import get_server
from trame.widgets import vuetify3 as vuetify

from nova.mvvm._internal.utils import rgetdictvalue
from nova.mvvm.trame_binding import TrameBinding
from nova.trame.model.ornl.neutron_data_selector import (
    CUSTOM_DIRECTORIES_LABEL,
@@ -15,7 +16,7 @@ from nova.trame.model.ornl.neutron_data_selector import (
from nova.trame.view.layouts import GridLayout
from nova.trame.view_model.ornl.neutron_data_selector import NeutronDataSelectorViewModel

from ..data_selector import DataSelector
from ..data_selector import DataSelector, get_state_param, set_state_param
from ..input_field import InputField

vuetify.enable_lab()
@@ -31,9 +32,9 @@ class NeutronDataSelector(DataSelector):
        facility: Union[str, Tuple] = "",
        instrument: Union[str, Tuple] = "",
        experiment: Union[str, Tuple] = "",
        selected_directory: Union[str, Tuple] = "",
        extensions: Union[List[str], Tuple, None] = None,
        prefix: Union[str, Tuple] = "",
        subdirectory: Union[str, Tuple] = "",
        refresh_rate: Union[int, Tuple] = 30,
        select_strategy: Union[str, Tuple] = "all",
        **kwargs: Any,
@@ -54,13 +55,13 @@ class NeutronDataSelector(DataSelector):
            The instrument to restrict data selection to. Please use the instrument acronym (e.g. CG-2).
        experiment : Union[str, Tuple], optional
            The experiment to restrict data selection to.
        selected_directory : Union[str, Tuple], optional
            The directory containing the visible datafiles.
        extensions : Union[List[str], Tuple], optional
            A list of file extensions to restrict selection to. If unset, then all files will be shown.
        prefix : Union[str, Tuple], optional
            A subdirectory within the user's chosen experiment to show files. If not specified, the user will be shown a
            folder browser and will be able to see all files in the experiment that they have access to.
            Deprecated. Please refer to the `subdirectory` parameter.
        subdirectory : Union[str, Tuple], optional
            A subdirectory within the user's chosen experiment to show files. If not specified as a string, the user
            will be shown a folder browser and will be able to see all files in the experiment that they have access to.
        refresh_rate : Union[str, Tuple], optional
            The number of seconds between attempts to automatically refresh the file list. Set to zero to disable this
            feature. Defaults to 30 seconds.
@@ -75,40 +76,65 @@ class NeutronDataSelector(DataSelector):
        -------
        None
        """
        if facility and allow_custom_directories:
            warn("allow_custom_directories will be ignored since the facility parameter is set.", stacklevel=1)
        if isinstance(facility, str) and allow_custom_directories:
            warn("allow_custom_directories will be ignored since the facility parameter is fixed.", stacklevel=1)

        self._facility = facility
        self._last_facility = get_state_param(self.state, self._facility)
        self._instrument = instrument
        self._last_instrument = get_state_param(self.state, self._instrument)
        self._experiment = experiment
        self._last_experiment = get_state_param(self.state, self._experiment)
        self._allow_custom_directories = allow_custom_directories
        self._last_allow_custom_directories = self._allow_custom_directories

        self._facilities_name = f"nova__neutrondataselector_{self._next_id}_facilities"
        self._selected_facility_name = (
            self._facility[0] if isinstance(self._facility, tuple) else f"{self._state_name}.facility"
        )
        self._instruments_name = f"nova__neutrondataselector_{self._next_id}_instruments"
        self._selected_instrument_name = (
            self._instrument[0] if isinstance(self._instrument, tuple) else f"{self._state_name}.instrument"
        )
        self._experiments_name = f"nova__neutrondataselector_{self._next_id}_experiments"
        self._selected_experiment_name = (
            self._experiment[0] if isinstance(self._experiment, tuple) else f"{self._state_name}.experiment"
        )

        super().__init__(v_model, "", extensions, prefix, refresh_rate, select_strategy, **kwargs)
        super().__init__(
            v_model,
            "",
            extensions=extensions,
            subdirectory=subdirectory,
            refresh_rate=refresh_rate,
            select_strategy=select_strategy,
            **kwargs,
        )

    def create_ui(self, **kwargs: Any) -> None:
        super().create_ui(**kwargs)
        with self._layout.filter:
            with GridLayout(columns=3):
                columns = 3
                if self._facility == "":
                if isinstance(self._facility, tuple) or not self._facility:
                    columns -= 1
                    InputField(
                        v_model=f"{self._state_name}.facility", items=(self._facilities_name,), type="autocomplete"
                        v_model=self._selected_facility_name,
                        items=(self._facilities_name,),
                        type="autocomplete",
                        update_modelValue=(self.update_facility, "[$event]"),
                    )
                if self._instrument == "":
                if isinstance(self._instrument, tuple) or not self._instrument:
                    columns -= 1
                    InputField(
                        v_if=f"{self._state_name}.facility !== '{CUSTOM_DIRECTORIES_LABEL}'",
                        v_model=f"{self._state_name}.instrument",
                        v_if=f"{self._selected_facility_name} !== '{CUSTOM_DIRECTORIES_LABEL}'",
                        v_model=self._selected_instrument_name,
                        items=(self._instruments_name,),
                        type="autocomplete",
                    )
                InputField(
                    v_if=f"{self._state_name}.facility !== '{CUSTOM_DIRECTORIES_LABEL}'",
                    v_model=f"{self._state_name}.experiment",
                    v_if=f"{self._selected_facility_name} !== '{CUSTOM_DIRECTORIES_LABEL}'",
                    v_model=self._selected_experiment_name,
                    column_span=columns,
                    items=(self._experiments_name,),
                    type="autocomplete",
@@ -117,9 +143,7 @@ class NeutronDataSelector(DataSelector):

    def create_model(self) -> None:
        state = NeutronDataSelectorState()
        self._model: NeutronDataSelectorModel = NeutronDataSelectorModel(
            state, self._facility, self._instrument, self._extensions, self._prefix, self._allow_custom_directories
        )
        self._model: NeutronDataSelectorModel = NeutronDataSelectorModel(state)

    def create_viewmodel(self) -> None:
        server = get_server(None, client_type="vue3")
@@ -136,26 +160,82 @@ class NeutronDataSelector(DataSelector):

        self._vm.update_view()

    def set_state(
        self, facility: Optional[str] = None, instrument: Optional[str] = None, experiment: Optional[str] = None
    ) -> None:
        """Programmatically set the facility, instrument, and/or experiment to restrict data selection to.
    def on_update(self, results: Dict[str, Any]) -> None:
        self._vm.set_binding_parameters(
            facility=get_state_param(self.state, self._facility),
            instrument=get_state_param(self.state, self._instrument),
            experiment=get_state_param(self.state, self._experiment),
            allow_custom_directories=get_state_param(self.state, self._allow_custom_directories),
        )

        If a parameter is None, then it will not be updated.
    def setup_bindings(self) -> None:
        set_state_param(self.state, self._facility)
        set_state_param(self.state, self._instrument)
        set_state_param(self.state, self._experiment)
        set_state_param(self.state, self._allow_custom_directories)

        self._vm.set_binding_parameters(
            facility=get_state_param(self.state, self._facility),
            instrument=get_state_param(self.state, self._instrument),
            experiment=get_state_param(self.state, self._experiment),
            allow_custom_directories=get_state_param(self.state, self._allow_custom_directories),
        )

        Parameters
        ----------
        facility : str, optional
            The facility to restrict data selection to. Options: HFIR, SNS
        instrument : str, optional
            The instrument to restrict data selection to. Must be at the selected facility.
        experiment : str, optional
            The experiment to restrict data selection to. Must begin with "IPTS-". It is your responsibility to validate
            that the provided experiment exists within the instrument directory. If it doesn't then no datafiles will be
            shown to the user.
        if isinstance(self._facility, tuple):

        Returns
        -------
        None
        """
        self._vm.set_state(facility, instrument, experiment)
            @self.state.change(self._facility[0].split(".")[0])
            def on_facility_change(**kwargs: Any) -> None:
                facility = rgetdictvalue(kwargs, self._facility[0])
                if facility != self._last_facility:
                    self._last_facility = facility
                    self._vm.set_binding_parameters(facility=set_state_param(self.state, self._facility, facility))

        if isinstance(self._instrument, tuple):

            @self.state.change(self._instrument[0].split(".")[0])
            def on_instrument_change(**kwargs: Any) -> None:
                instrument = rgetdictvalue(kwargs, self._instrument[0])
                if instrument != self._last_instrument:
                    self._last_instrument = instrument
                    self._vm.set_binding_parameters(
                        instrument=set_state_param(self.state, self._instrument, instrument)
                    )

        if isinstance(self._experiment, tuple):

            @self.state.change(self._experiment[0].split(".")[0])
            def on_experiment_change(**kwargs: Any) -> None:
                experiment = rgetdictvalue(kwargs, self._experiment[0])
                if experiment != self._last_experiment:
                    self._last_experiment = experiment
                    self._vm.set_binding_parameters(
                        experiment=set_state_param(self.state, self._experiment, experiment)
                    )

        if isinstance(self._allow_custom_directories, tuple):

            @self.state.change(self._allow_custom_directories[0].split(".")[0])
            def on_allow_custom_directories_change(**kwargs: Any) -> None:
                allow_custom_directories = rgetdictvalue(kwargs, self._allow_custom_directories[0])  # type: ignore
                if allow_custom_directories != self._last_allow_custom_directories:
                    self._last_allow_custom_directories = allow_custom_directories
                    self._vm.set_binding_parameters(
                        allow_custom_directories=set_state_param(
                            self.state, self._allow_custom_directories, allow_custom_directories
                        )
                    )

    def update_facility(self, facility: str) -> None:
        self._vm.set_binding_parameters(
            facility=set_state_param(self.state, self._facility, facility),
        )

    def update_instrument(self, instrument: str) -> None:
        self._vm.set_binding_parameters(
            instrument=set_state_param(self.state, self._instrument, instrument),
        )

    def update_experiment(self, experiment: str) -> None:
        self._vm.set_binding_parameters(
            experiment=set_state_param(self.state, self._experiment, experiment),
        )
+2 −2
Original line number Diff line number Diff line
@@ -57,8 +57,8 @@ class DataSelectorViewModel:
    def on_state_updated(self, results: Dict[str, Any]) -> None:
        pass

    def set_binding_parameters(self, directory: str, extensions: List[str], prefix: str) -> None:
        self.model.set_binding_parameters(directory, extensions, prefix)
    def set_binding_parameters(self, **kwargs: Any) -> None:
        self.model.set_binding_parameters(**kwargs)
        self.update_view()

    def set_subdirectory(self, subdirectory_path: str = "") -> None:
Loading