Loading src/nova/trame/model/data_selector.py +7 −4 Original line number Diff line number Diff line Loading @@ -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 Loading src/nova/trame/model/ornl/neutron_data_selector.py +13 −23 Original line number Diff line number Diff line Loading @@ -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()) Loading Loading @@ -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 src/nova/trame/view/components/data_selector.py +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 Loading Loading @@ -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 Loading @@ -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) Loading @@ -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( Loading Loading @@ -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, Loading Loading @@ -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],) Loading @@ -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): Loading @@ -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): Loading @@ -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: Loading src/nova/trame/view/components/ornl/neutron_data_selector.py +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, Loading @@ -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() Loading @@ -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, Loading @@ -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. Loading @@ -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", Loading @@ -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") Loading @@ -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), ) src/nova/trame/view_model/data_selector.py +2 −2 Original line number Diff line number Diff line Loading @@ -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 Loading
src/nova/trame/model/data_selector.py +7 −4 Original line number Diff line number Diff line Loading @@ -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 Loading
src/nova/trame/model/ornl/neutron_data_selector.py +13 −23 Original line number Diff line number Diff line Loading @@ -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()) Loading Loading @@ -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
src/nova/trame/view/components/data_selector.py +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 Loading Loading @@ -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 Loading @@ -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) Loading @@ -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( Loading Loading @@ -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, Loading Loading @@ -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],) Loading @@ -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): Loading @@ -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): Loading @@ -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: Loading
src/nova/trame/view/components/ornl/neutron_data_selector.py +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, Loading @@ -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() Loading @@ -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, Loading @@ -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. Loading @@ -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", Loading @@ -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") Loading @@ -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), )
src/nova/trame/view_model/data_selector.py +2 −2 Original line number Diff line number Diff line Loading @@ -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