diff --git a/src/pandablocks_ioc/_hdf_ioc.py b/src/pandablocks_ioc/_hdf_ioc.py index 636f6abb..b4e5b22b 100644 --- a/src/pandablocks_ioc/_hdf_ioc.py +++ b/src/pandablocks_ioc/_hdf_ioc.py @@ -71,7 +71,7 @@ def __init__( status_message_setter: Callable, number_received_setter: Callable, number_captured_setter_pipeline: NumCapturedSetter, - dataset_name_cache: Dict[EpicsName, Dict[str, str]], + dataset_name_cache: Dict[str, Dict[str, str]], ): # Only one filename - user must stop capture and set new FileName/FilePath # for new files @@ -334,7 +334,7 @@ class HDF5RecordController: def __init__( self, client: AsyncioClient, - dataset_name_cache: Dict[str, Callable[[str], str]], + dataset_name_cache: Dict[str, Dict[str, str]], record_prefix: str, ): if find_spec("h5py") is None: diff --git a/src/pandablocks_ioc/_tables.py b/src/pandablocks_ioc/_tables.py index 3f3c70e3..8b9fce0e 100644 --- a/src/pandablocks_ioc/_tables.py +++ b/src/pandablocks_ioc/_tables.py @@ -81,7 +81,7 @@ def __init__( ): self.epics_table_name = epics_table_name self.pva_table_name = RecordName(epics_table_name) - self.rows = {} + self.rows: Dict[str, RecordWrapper] = {} block, field = self.epics_table_name.split(":", maxsplit=1) @@ -124,12 +124,12 @@ def add_row( full_name = EpicsName(self.epics_table_name + ":" + row_name) pva_row_name = row_name.replace(":", "_").lower() length = length or len(initial_value) - initial_value = np.array(initial_value, dtype=datatype) + initial_value_np = np.array(initial_value, dtype=datatype) field_record: RecordWrapper = builder.WaveformIn( full_name, DESC="", # Description not provided yet - initial_value=initial_value, + initial_value=initial_value_np, length=length, ) diff --git a/src/pandablocks_ioc/ioc.py b/src/pandablocks_ioc/ioc.py index f83680ad..595a31f6 100644 --- a/src/pandablocks_ioc/ioc.py +++ b/src/pandablocks_ioc/ioc.py @@ -526,29 +526,25 @@ def update_cache( self.cache[field_name] = capture_names = {} # Only consider explicitly named datsets if dataset_name and capture_mode != "No": - # The last capture option is the one that should take the dataset name + # Keep a reference to just the dataset name for `DATA:DATASETS` + self._record_name_to_dataset_name[record_name] = dataset_name capture_names[capture_mode.split(" ")[-1]] = dataset_name - # But also suffix -min and -max if both are present + # Suffix -min and -max if both are present if "Min Max" in capture_mode: capture_names["Min"] = f"{dataset_name}-min" capture_names["Max"] = f"{dataset_name}-min" - self._record_name_to_dataset_name[record_name] = dataset_name else: self._record_name_to_dataset_name.pop(record_name, None) self.update_dataset_name_to_type() def update_dataset_name_to_type(self): - self._datasets_table.update_row( - "Name", list(self._record_name_to_dataset_name.values()) - ) + dataset_name_list = list(self._record_name_to_dataset_name.values()) + self._datasets_table.update_row("Name", dataset_name_list) self._datasets_table.update_row( "Type", - [ - "uint32" if "EXT_OUT" in record_name else "float64" - for record_name in self._record_name_to_dataset_name.keys() - ], + ["float64"] * len(dataset_name_list), ) @@ -1062,16 +1058,30 @@ def _make_ext_out( record_dict: Dict[EpicsName, RecordInfo] = {} # There is no record for the ext_out field itself - the only thing - # you do with them is to turn their Capture attribute on/off. - # The field itself has no value. + # you do with them is to turn their Capture attribute on/off, and give it + # an alternative dataset name capture_record_name = EpicsName(record_name + ":CAPTURE") + dataset_record_name = EpicsName(record_name + ":DATASET") labels, capture_index = self._process_labels( field_info.capture_labels, values[capture_record_name] ) + record_dict[dataset_record_name] = self._create_record_info( + dataset_record_name, + "Used to adjust the dataset name to one more scientifically relevant", + builder.stringOut, + str, + PviGroup.OUTPUTS, + initial_value="", + on_update=lambda new_dataset_name: ( + self._dataset_name_cache.update_cache( + record_name, + new_dataset_name, + labels[record_dict[capture_record_name].record.get()], + ) + ), + ) - # TODO :DATASET on ext out, you don't need to add this to all - # position capture table, though we want it in `DATA:DATASETS` record_dict[capture_record_name] = self._create_record_info( capture_record_name, field_info.description, @@ -1080,6 +1090,13 @@ def _make_ext_out( PviGroup.OUTPUTS, labels=labels, initial_value=capture_index, + on_update=lambda new_capture_mode: ( + self._dataset_name_cache.update_cache( + record_name, + record_dict[dataset_record_name].record.get(), + labels[new_capture_mode], + ) + ), ) return record_dict diff --git a/tests/test_hdf_ioc.py b/tests/test_hdf_ioc.py index e32985b0..83414d68 100644 --- a/tests/test_hdf_ioc.py +++ b/tests/test_hdf_ioc.py @@ -228,15 +228,13 @@ async def hdf5_controller( test_prefix, hdf5_test_prefix = new_random_hdf5_prefix - dataset_name_getters = { - "COUNTER1": lambda: "some_other_dataset_name", + dataset_name_cache = { + "COUNTER1.OUT": {"Value": "some_other_dataset_name"}, # these datasets haven't been overwritten, they should be the default - "COUNTER2": lambda: "", - "COUNTER3": lambda: "", } hdf5_controller = HDF5RecordController( - AsyncioClient("localhost"), dataset_name_getters, test_prefix + AsyncioClient("localhost"), dataset_name_cache, test_prefix ) # When using tests w/o CA, need to manually set _directory_exists to 1 diff --git a/tests/test_ioc.py b/tests/test_ioc.py index b660ddc4..1236a5db 100644 --- a/tests/test_ioc.py +++ b/tests/test_ioc.py @@ -219,18 +219,19 @@ def idfn(val): ), { f"{TEST_RECORD}:CAPTURE": "Diff", + f"{TEST_RECORD}:DATASET": "MyDataset", }, - [ - f"{TEST_RECORD}:CAPTURE", - ], + [f"{TEST_RECORD}:CAPTURE", f"{TEST_RECORD}:DATASET"], ), ( ExtOutFieldInfo("ext_out", "samples", None, capture_labels=["No", "Diff"]), { f"{TEST_RECORD}:CAPTURE": "Diff", + f"{TEST_RECORD}:DATASET": "MyDataset", }, [ f"{TEST_RECORD}:CAPTURE", + f"{TEST_RECORD}:DATASET", ], ), (