brimfile.file
1import numpy as np 2import warnings 3 4from .data import Data 5 6from .utils import concatenate_paths 7from .constants import brim_obj_names 8from . import units 9 10from .file_abstraction import FileAbstraction, StoreType, sync 11from .validation import validate_json, ValidationError, ValidationLevel 12from .validation.json_descriptor import generate_json_descriptor 13 14# don't import _AbstractFile if running in pyodide (it is defined in js) 15import sys 16if "pyodide" not in sys.modules: 17 from .file_abstraction import _AbstractFile 18 19__docformat__ = "google" 20 21class File: 22 """ 23 Represents a brim file with Brillouin data, extending h5py.File. 24 """ 25 26 if "pyodide" in sys.modules: 27 def __init__(self, file): 28 self._file = file 29 if not self.is_valid(): 30 raise ValueError("The brim file is not valid!") 31 else: 32 def __init__(self, filename: str, mode: str = 'r', 33 store_type: StoreType = StoreType.AUTO, * , 34 validate: bool = False) -> None: 35 """ 36 Initialize the File object. 37 38 Args: 39 filename (str): Path to the brim file. 40 mode: {'r', 'r+', 'a', 'w', 'w-'} the mode for opening the file (default is 'r' for read-only). 41 See the definition of `mode` in `brimfile.file_abstraction._zarrFile.__init__()` for more details. 42 'r' means read only (must exist); 'r+' means read/write (must exist); 43 'a' means read/write (create if doesn't exist); 'w' means create (overwrite if exists); 'w-' means create (fail if exists). 44 store_type (StoreType): Type of the store to use, as defined in `brimfile.file_abstraction.StoreType`. Default is 'AUTO'. 45 validate (bool): Whether to validate the file upon initialization. Default is False. 46 """ 47 self._file = _AbstractFile( 48 filename, mode=mode, store_type=store_type) 49 if not self.is_valid(): 50 raise ValueError("The brim file is not valid!") 51 if validate: 52 validation_errors: list[ValidationError] = self.validate() 53 for err in validation_errors: 54 if err.level == ValidationLevel.WARNING or err.level == ValidationLevel.ERROR: 55 warnings.warn(f"Validation warning at {err.path}: {err.message}") 56 elif err.level == ValidationLevel.CRITICAL: 57 raise ValueError(f"Validation error at {err.path}: {err.message}") 58 59 def validate(self) -> list[ValidationError]: 60 """ 61 Validate the brim file and return a list of validation errors. 62 63 Returns: 64 list[ValidationError]: A list of validation errors found in the brim file. 65 If the list is empty, the file is valid. 66 """ 67 json_descriptor = generate_json_descriptor(self._file) 68 validation_errors: list[ValidationError] = validate_json(json_descriptor) 69 return validation_errors 70 71 def __del__(self): 72 try: 73 if hasattr(self, '_file'): 74 self.close() 75 except Exception as e: 76 # don't throw an error if the file cannot be closed 77 warnings.warn(f"Cannot close the file: {e}") 78 79 def close(self) -> None: 80 self._file.close() 81 82 def is_read_only(self) -> bool: 83 return sync(self._file.is_read_only()) 84 85 def is_valid(self) -> bool: 86 """ 87 Check if the file is a valid brim file. 88 89 Returns: 90 bool: True if the file is valid, False otherwise. 91 """ 92 # TODO validate file against https://github.com/brillouin-imaging/Brillouin-standard-file/blob/main/docs/brim_file_specs.md 93 return True 94 95 @classmethod 96 def create(cls, filename: str, store_type: StoreType = StoreType.AUTO, brim_version: str = '0.1') -> 'File': 97 """ 98 Create a new brim file with the specified filename. If the file exists already it will generate an error. 99 100 Args: 101 filename (str): Path to the brim file to be created. 102 store_type (StoreType): Type of the store to use, as defined in `brimfile.file_abstraction.StoreType`. Default is 'AUTO'. 103 brim_version (str): Version of the brim file format to use. Default is '0.1'. 104 105 Returns: 106 File: An instance of the File class representing the newly created brim file. 107 store_type (str): Type of the store to use, as defined in `brimfile.file_abstraction.StoreType`. Default is 'AUTO'. 108 """ 109 f = cls(filename, mode='w-', store_type=store_type) 110 111 # File version 112 sync(f._file.create_attr('/', 'brim_version', brim_version)) 113 114 # Root Brillouin_data group 115 sync(f._file.create_group(brim_obj_names.Brillouin_base_path)) 116 117 return f 118 119 def create_data_group(self, PSD: np.ndarray, frequency: np.ndarray, px_size_um: tuple, *, index: int = None, 120 name: str = None, compression: FileAbstraction.Compression = FileAbstraction.Compression()) -> 'Data': 121 """ 122 Adds a new data entry to the file. 123 Parameters: 124 PSD (np.ndarray): The Power Spectral Density (PSD) data to be added. It must be 4D with dimensions z, y, x, spectrum 125 frequency (np.ndarray): The frequency data corresponding to the PSD. It must be broadcastable to the PSD shape (the most common case is frequency being 1D, in which case the frequency axis is assumed the same for all the spatial coordinates) 126 px_size_um (tuple): A tuple of 3 elements, in the order z,y,x, corresponding to the pixel size in um. Unused dimensions can be set to None. 127 index (int, optional): The index for the new data group. If None, the next available index is used. Defaults to None. 128 name (str, optional): The name for the new data group. Defaults to None. 129 compression (FileAbstraction.Compression, optional): The compression method to use for the data. Defaults to FileAbstraction.Compression.DEFAULT. 130 Returns: 131 Data: The newly created Data object. 132 Raises: 133 IndexError: If the specified index already exists in the dataset. 134 ValueError: If any of the data provided is not valid or consistent 135 """ 136 if PSD.ndim != 4: 137 raise ValueError( 138 "'PSD' must have 4 dimensions (z, y, x, spectrum)") 139 try: 140 np.broadcast_shapes(tuple(frequency.shape), tuple(PSD.shape)) 141 except ValueError as e: 142 raise ValueError(f"frequency (shape: {frequency.shape}) is not broadcastable to PSD (shape: {PSD.shape}): {e}") 143 if len(px_size_um) != 3: 144 raise ValueError("'px_size_um' must have 3 elements (z,y,x); unused dimensions can be set to None") 145 146 return self._create_data_group_raw(PSD, frequency, scanning = None, sparse = False, px_size_um=px_size_um, 147 index=index, name=name, compression=compression) 148 149 def create_data_group_sparse(self, PSD: np.ndarray, frequency: np.ndarray, scanning: dict, *, timestamp: np.ndarray = None, 150 index: int = None, name: str = None, compression: FileAbstraction.Compression = FileAbstraction.Compression()) -> 'Data': 151 """ 152 Adds a new [sparse data entry](https://github.com/brillouin-imaging/Brillouin-standard-file/blob/main/docs/brim_file_specs.md) to the file. 153 154 Sparse data allows storage of spectra in a flattened format (first dimension is the spectrum index), 155 with spatial mapping provided separately. This is efficient for data with irregular sampling or missing pixels. 156 157 Parameters: 158 PSD (np.ndarray): The Power Spectral Density (PSD) data to be added. First dimension is spectrum index, 159 last dimension contains the spectral data. Shape: (n_spectra, ..., n_freq_points). 160 frequency (np.ndarray): The frequency data corresponding to the PSD. Must be broadcastable to the PSD array. 161 scanning (dict): Dictionary defining the spatial mapping. Must include at least 'Spatial_map' or 'Cartesian_visualisation'. 162 See `brimfile.data.Data._add_data` docstring for detailed structure of the scanning dictionary. 163 timestamp (np.ndarray, optional): Timestamps in milliseconds for the data. Defaults to None. 164 index (int, optional): The index for the new data group. If None, the next available index is used. Defaults to None. 165 name (str, optional): The name for the new data group. Defaults to None. 166 compression (FileAbstraction.Compression, optional): The compression method to use for the data. Defaults to FileAbstraction.Compression.DEFAULT. 167 Returns: 168 Data: The newly created Data object. 169 Raises: 170 IndexError: If the specified index already exists in the dataset. 171 ValueError: If any of the data provided is not valid or consistent 172 """ 173 return self._create_data_group_raw(PSD, frequency, scanning=scanning, timestamp=timestamp, sparse=True, index=index, name=name, compression=compression) 174 175 def _create_data_group_raw(self, PSD: np.ndarray, frequency: np.ndarray, *, scanning: dict = None, px_size_um = None, timestamp: np.ndarray = None, sparse: bool = False, 176 index: int = None, name: str = None, compression: FileAbstraction.Compression = FileAbstraction.Compression()) -> 'Data': 177 """ 178 Adds a new data entry to the file. Check the documentation for `brimfile.data.Data._add_data` for more details on the parameters. 179 Parameters: 180 PSD (np.ndarray): The Power Spectral Density (PSD) data to be added. The last dimension contains the spectra. 181 frequency (np.ndarray): The frequency data corresponding to the PSD. Must be broadcastable to the PSD array. 182 scanning (dict, optional): Spatial mapping metadata. Required for sparse=True, optional for sparse=False. 183 See `brimfile.data.Data._add_data` docstring for detailed structure. 184 px_size_um (tuple, optional): A tuple of 3 elements (z, y, x) for pixel size in μm. For non-sparse data only. 185 timestamp (np.ndarray, optional): Timestamps in milliseconds for the data. Defaults to None. 186 sparse (bool): Whether the data is sparse. See https://github.com/brillouin-imaging/Brillouin-standard-file/blob/main/docs/brim_file_specs.md for details. Defaults to False. 187 index (int, optional): The index for the new data group. If None, the next available index is used. Defaults to None. 188 name (str, optional): The name for the new data group. Defaults to None. 189 compression (FileAbstraction.Compression, optional): The compression method to use for the data. Defaults to FileAbstraction.Compression.DEFAULT. 190 Returns: 191 Data: The newly created Data object. 192 Raises: 193 IndexError: If the specified index already exists in the dataset. 194 ValueError: If any of the data provided is not valid or consistent 195 """ 196 if index is not None: 197 if Data._get_existing_group_name(self._file, index) is not None: 198 raise IndexError( 199 f"Data {index} already exists in {self._file.filename}") 200 else: 201 data_groups = self.list_data_groups() 202 indices = [dg['index'] for dg in data_groups] 203 indices.sort() 204 index = indices[-1] + 1 if indices else 0 # Next available index 205 206 # create the data group 207 d = Data._create_new(self._file, index, sparse, name) 208 # add the pixel size as an attribute of the data group 209 if px_size_um is not None: 210 sync(self._file.create_attr(d._group, 'element_size', tuple(px_size_um))) 211 units.add_to_attribute(self._file, d._group, 'element_size', 'um') 212 elif not sparse: 213 warnings.warn("Pixel size is not provided for non-sparse data. It is recommended to provide it for proper spatial calibration and visualization.") 214 # add the data to the data group 215 d._add_data(PSD, frequency, scanning = scanning, 216 timestamp=timestamp, compression=compression) 217 return d 218 219 def list_data_groups(self, retrieve_custom_name=False) -> list: 220 """ 221 List all data groups in the brim file. 222 223 Returns: 224 See documentation of brimfile.data.Data.list_data_groups 225 """ 226 return Data.list_data_groups(self._file, retrieve_custom_name) 227 228 def get_data(self, index: int = 0) -> 'Data': 229 """ 230 Retrieve a Data object for the specified index. 231 232 Args: 233 index (int): The index of the data group to retrieve. 234 235 Returns: 236 Data: The Data object corresponding to the specified index. 237 """ 238 group_name: str = Data._get_existing_group_name(self._file, index) 239 if group_name is None: 240 raise IndexError(f"Data {index} not found") 241 data = Data(self._file, concatenate_paths( 242 brim_obj_names.Brillouin_base_path, group_name)) 243 return data 244 245 @property 246 def filename(self) -> str: 247 """ 248 Get the filename of the brim file. 249 250 Returns: 251 str: The filename of the brim file. 252 """ 253 return self._file.filename
22class File: 23 """ 24 Represents a brim file with Brillouin data, extending h5py.File. 25 """ 26 27 if "pyodide" in sys.modules: 28 def __init__(self, file): 29 self._file = file 30 if not self.is_valid(): 31 raise ValueError("The brim file is not valid!") 32 else: 33 def __init__(self, filename: str, mode: str = 'r', 34 store_type: StoreType = StoreType.AUTO, * , 35 validate: bool = False) -> None: 36 """ 37 Initialize the File object. 38 39 Args: 40 filename (str): Path to the brim file. 41 mode: {'r', 'r+', 'a', 'w', 'w-'} the mode for opening the file (default is 'r' for read-only). 42 See the definition of `mode` in `brimfile.file_abstraction._zarrFile.__init__()` for more details. 43 'r' means read only (must exist); 'r+' means read/write (must exist); 44 'a' means read/write (create if doesn't exist); 'w' means create (overwrite if exists); 'w-' means create (fail if exists). 45 store_type (StoreType): Type of the store to use, as defined in `brimfile.file_abstraction.StoreType`. Default is 'AUTO'. 46 validate (bool): Whether to validate the file upon initialization. Default is False. 47 """ 48 self._file = _AbstractFile( 49 filename, mode=mode, store_type=store_type) 50 if not self.is_valid(): 51 raise ValueError("The brim file is not valid!") 52 if validate: 53 validation_errors: list[ValidationError] = self.validate() 54 for err in validation_errors: 55 if err.level == ValidationLevel.WARNING or err.level == ValidationLevel.ERROR: 56 warnings.warn(f"Validation warning at {err.path}: {err.message}") 57 elif err.level == ValidationLevel.CRITICAL: 58 raise ValueError(f"Validation error at {err.path}: {err.message}") 59 60 def validate(self) -> list[ValidationError]: 61 """ 62 Validate the brim file and return a list of validation errors. 63 64 Returns: 65 list[ValidationError]: A list of validation errors found in the brim file. 66 If the list is empty, the file is valid. 67 """ 68 json_descriptor = generate_json_descriptor(self._file) 69 validation_errors: list[ValidationError] = validate_json(json_descriptor) 70 return validation_errors 71 72 def __del__(self): 73 try: 74 if hasattr(self, '_file'): 75 self.close() 76 except Exception as e: 77 # don't throw an error if the file cannot be closed 78 warnings.warn(f"Cannot close the file: {e}") 79 80 def close(self) -> None: 81 self._file.close() 82 83 def is_read_only(self) -> bool: 84 return sync(self._file.is_read_only()) 85 86 def is_valid(self) -> bool: 87 """ 88 Check if the file is a valid brim file. 89 90 Returns: 91 bool: True if the file is valid, False otherwise. 92 """ 93 # TODO validate file against https://github.com/brillouin-imaging/Brillouin-standard-file/blob/main/docs/brim_file_specs.md 94 return True 95 96 @classmethod 97 def create(cls, filename: str, store_type: StoreType = StoreType.AUTO, brim_version: str = '0.1') -> 'File': 98 """ 99 Create a new brim file with the specified filename. If the file exists already it will generate an error. 100 101 Args: 102 filename (str): Path to the brim file to be created. 103 store_type (StoreType): Type of the store to use, as defined in `brimfile.file_abstraction.StoreType`. Default is 'AUTO'. 104 brim_version (str): Version of the brim file format to use. Default is '0.1'. 105 106 Returns: 107 File: An instance of the File class representing the newly created brim file. 108 store_type (str): Type of the store to use, as defined in `brimfile.file_abstraction.StoreType`. Default is 'AUTO'. 109 """ 110 f = cls(filename, mode='w-', store_type=store_type) 111 112 # File version 113 sync(f._file.create_attr('/', 'brim_version', brim_version)) 114 115 # Root Brillouin_data group 116 sync(f._file.create_group(brim_obj_names.Brillouin_base_path)) 117 118 return f 119 120 def create_data_group(self, PSD: np.ndarray, frequency: np.ndarray, px_size_um: tuple, *, index: int = None, 121 name: str = None, compression: FileAbstraction.Compression = FileAbstraction.Compression()) -> 'Data': 122 """ 123 Adds a new data entry to the file. 124 Parameters: 125 PSD (np.ndarray): The Power Spectral Density (PSD) data to be added. It must be 4D with dimensions z, y, x, spectrum 126 frequency (np.ndarray): The frequency data corresponding to the PSD. It must be broadcastable to the PSD shape (the most common case is frequency being 1D, in which case the frequency axis is assumed the same for all the spatial coordinates) 127 px_size_um (tuple): A tuple of 3 elements, in the order z,y,x, corresponding to the pixel size in um. Unused dimensions can be set to None. 128 index (int, optional): The index for the new data group. If None, the next available index is used. Defaults to None. 129 name (str, optional): The name for the new data group. Defaults to None. 130 compression (FileAbstraction.Compression, optional): The compression method to use for the data. Defaults to FileAbstraction.Compression.DEFAULT. 131 Returns: 132 Data: The newly created Data object. 133 Raises: 134 IndexError: If the specified index already exists in the dataset. 135 ValueError: If any of the data provided is not valid or consistent 136 """ 137 if PSD.ndim != 4: 138 raise ValueError( 139 "'PSD' must have 4 dimensions (z, y, x, spectrum)") 140 try: 141 np.broadcast_shapes(tuple(frequency.shape), tuple(PSD.shape)) 142 except ValueError as e: 143 raise ValueError(f"frequency (shape: {frequency.shape}) is not broadcastable to PSD (shape: {PSD.shape}): {e}") 144 if len(px_size_um) != 3: 145 raise ValueError("'px_size_um' must have 3 elements (z,y,x); unused dimensions can be set to None") 146 147 return self._create_data_group_raw(PSD, frequency, scanning = None, sparse = False, px_size_um=px_size_um, 148 index=index, name=name, compression=compression) 149 150 def create_data_group_sparse(self, PSD: np.ndarray, frequency: np.ndarray, scanning: dict, *, timestamp: np.ndarray = None, 151 index: int = None, name: str = None, compression: FileAbstraction.Compression = FileAbstraction.Compression()) -> 'Data': 152 """ 153 Adds a new [sparse data entry](https://github.com/brillouin-imaging/Brillouin-standard-file/blob/main/docs/brim_file_specs.md) to the file. 154 155 Sparse data allows storage of spectra in a flattened format (first dimension is the spectrum index), 156 with spatial mapping provided separately. This is efficient for data with irregular sampling or missing pixels. 157 158 Parameters: 159 PSD (np.ndarray): The Power Spectral Density (PSD) data to be added. First dimension is spectrum index, 160 last dimension contains the spectral data. Shape: (n_spectra, ..., n_freq_points). 161 frequency (np.ndarray): The frequency data corresponding to the PSD. Must be broadcastable to the PSD array. 162 scanning (dict): Dictionary defining the spatial mapping. Must include at least 'Spatial_map' or 'Cartesian_visualisation'. 163 See `brimfile.data.Data._add_data` docstring for detailed structure of the scanning dictionary. 164 timestamp (np.ndarray, optional): Timestamps in milliseconds for the data. Defaults to None. 165 index (int, optional): The index for the new data group. If None, the next available index is used. Defaults to None. 166 name (str, optional): The name for the new data group. Defaults to None. 167 compression (FileAbstraction.Compression, optional): The compression method to use for the data. Defaults to FileAbstraction.Compression.DEFAULT. 168 Returns: 169 Data: The newly created Data object. 170 Raises: 171 IndexError: If the specified index already exists in the dataset. 172 ValueError: If any of the data provided is not valid or consistent 173 """ 174 return self._create_data_group_raw(PSD, frequency, scanning=scanning, timestamp=timestamp, sparse=True, index=index, name=name, compression=compression) 175 176 def _create_data_group_raw(self, PSD: np.ndarray, frequency: np.ndarray, *, scanning: dict = None, px_size_um = None, timestamp: np.ndarray = None, sparse: bool = False, 177 index: int = None, name: str = None, compression: FileAbstraction.Compression = FileAbstraction.Compression()) -> 'Data': 178 """ 179 Adds a new data entry to the file. Check the documentation for `brimfile.data.Data._add_data` for more details on the parameters. 180 Parameters: 181 PSD (np.ndarray): The Power Spectral Density (PSD) data to be added. The last dimension contains the spectra. 182 frequency (np.ndarray): The frequency data corresponding to the PSD. Must be broadcastable to the PSD array. 183 scanning (dict, optional): Spatial mapping metadata. Required for sparse=True, optional for sparse=False. 184 See `brimfile.data.Data._add_data` docstring for detailed structure. 185 px_size_um (tuple, optional): A tuple of 3 elements (z, y, x) for pixel size in μm. For non-sparse data only. 186 timestamp (np.ndarray, optional): Timestamps in milliseconds for the data. Defaults to None. 187 sparse (bool): Whether the data is sparse. See https://github.com/brillouin-imaging/Brillouin-standard-file/blob/main/docs/brim_file_specs.md for details. Defaults to False. 188 index (int, optional): The index for the new data group. If None, the next available index is used. Defaults to None. 189 name (str, optional): The name for the new data group. Defaults to None. 190 compression (FileAbstraction.Compression, optional): The compression method to use for the data. Defaults to FileAbstraction.Compression.DEFAULT. 191 Returns: 192 Data: The newly created Data object. 193 Raises: 194 IndexError: If the specified index already exists in the dataset. 195 ValueError: If any of the data provided is not valid or consistent 196 """ 197 if index is not None: 198 if Data._get_existing_group_name(self._file, index) is not None: 199 raise IndexError( 200 f"Data {index} already exists in {self._file.filename}") 201 else: 202 data_groups = self.list_data_groups() 203 indices = [dg['index'] for dg in data_groups] 204 indices.sort() 205 index = indices[-1] + 1 if indices else 0 # Next available index 206 207 # create the data group 208 d = Data._create_new(self._file, index, sparse, name) 209 # add the pixel size as an attribute of the data group 210 if px_size_um is not None: 211 sync(self._file.create_attr(d._group, 'element_size', tuple(px_size_um))) 212 units.add_to_attribute(self._file, d._group, 'element_size', 'um') 213 elif not sparse: 214 warnings.warn("Pixel size is not provided for non-sparse data. It is recommended to provide it for proper spatial calibration and visualization.") 215 # add the data to the data group 216 d._add_data(PSD, frequency, scanning = scanning, 217 timestamp=timestamp, compression=compression) 218 return d 219 220 def list_data_groups(self, retrieve_custom_name=False) -> list: 221 """ 222 List all data groups in the brim file. 223 224 Returns: 225 See documentation of brimfile.data.Data.list_data_groups 226 """ 227 return Data.list_data_groups(self._file, retrieve_custom_name) 228 229 def get_data(self, index: int = 0) -> 'Data': 230 """ 231 Retrieve a Data object for the specified index. 232 233 Args: 234 index (int): The index of the data group to retrieve. 235 236 Returns: 237 Data: The Data object corresponding to the specified index. 238 """ 239 group_name: str = Data._get_existing_group_name(self._file, index) 240 if group_name is None: 241 raise IndexError(f"Data {index} not found") 242 data = Data(self._file, concatenate_paths( 243 brim_obj_names.Brillouin_base_path, group_name)) 244 return data 245 246 @property 247 def filename(self) -> str: 248 """ 249 Get the filename of the brim file. 250 251 Returns: 252 str: The filename of the brim file. 253 """ 254 return self._file.filename
Represents a brim file with Brillouin data, extending h5py.File.
33 def __init__(self, filename: str, mode: str = 'r', 34 store_type: StoreType = StoreType.AUTO, * , 35 validate: bool = False) -> None: 36 """ 37 Initialize the File object. 38 39 Args: 40 filename (str): Path to the brim file. 41 mode: {'r', 'r+', 'a', 'w', 'w-'} the mode for opening the file (default is 'r' for read-only). 42 See the definition of `mode` in `brimfile.file_abstraction._zarrFile.__init__()` for more details. 43 'r' means read only (must exist); 'r+' means read/write (must exist); 44 'a' means read/write (create if doesn't exist); 'w' means create (overwrite if exists); 'w-' means create (fail if exists). 45 store_type (StoreType): Type of the store to use, as defined in `brimfile.file_abstraction.StoreType`. Default is 'AUTO'. 46 validate (bool): Whether to validate the file upon initialization. Default is False. 47 """ 48 self._file = _AbstractFile( 49 filename, mode=mode, store_type=store_type) 50 if not self.is_valid(): 51 raise ValueError("The brim file is not valid!") 52 if validate: 53 validation_errors: list[ValidationError] = self.validate() 54 for err in validation_errors: 55 if err.level == ValidationLevel.WARNING or err.level == ValidationLevel.ERROR: 56 warnings.warn(f"Validation warning at {err.path}: {err.message}") 57 elif err.level == ValidationLevel.CRITICAL: 58 raise ValueError(f"Validation error at {err.path}: {err.message}")
Initialize the File object.
Arguments:
- filename (str): Path to the brim file.
- mode: {'r', 'r+', 'a', 'w', 'w-'} the mode for opening the file (default is 'r' for read-only).
See the definition of
modeinbrimfile.file_abstraction._zarrFile.__init__()for more details. 'r' means read only (must exist); 'r+' means read/write (must exist); 'a' means read/write (create if doesn't exist); 'w' means create (overwrite if exists); 'w-' means create (fail if exists). - store_type (StoreType): Type of the store to use, as defined in
brimfile.file_abstraction.StoreType. Default is 'AUTO'. - validate (bool): Whether to validate the file upon initialization. Default is False.
60 def validate(self) -> list[ValidationError]: 61 """ 62 Validate the brim file and return a list of validation errors. 63 64 Returns: 65 list[ValidationError]: A list of validation errors found in the brim file. 66 If the list is empty, the file is valid. 67 """ 68 json_descriptor = generate_json_descriptor(self._file) 69 validation_errors: list[ValidationError] = validate_json(json_descriptor) 70 return validation_errors
Validate the brim file and return a list of validation errors.
Returns:
list[ValidationError]: A list of validation errors found in the brim file. If the list is empty, the file is valid.
86 def is_valid(self) -> bool: 87 """ 88 Check if the file is a valid brim file. 89 90 Returns: 91 bool: True if the file is valid, False otherwise. 92 """ 93 # TODO validate file against https://github.com/brillouin-imaging/Brillouin-standard-file/blob/main/docs/brim_file_specs.md 94 return True
Check if the file is a valid brim file.
Returns:
bool: True if the file is valid, False otherwise.
96 @classmethod 97 def create(cls, filename: str, store_type: StoreType = StoreType.AUTO, brim_version: str = '0.1') -> 'File': 98 """ 99 Create a new brim file with the specified filename. If the file exists already it will generate an error. 100 101 Args: 102 filename (str): Path to the brim file to be created. 103 store_type (StoreType): Type of the store to use, as defined in `brimfile.file_abstraction.StoreType`. Default is 'AUTO'. 104 brim_version (str): Version of the brim file format to use. Default is '0.1'. 105 106 Returns: 107 File: An instance of the File class representing the newly created brim file. 108 store_type (str): Type of the store to use, as defined in `brimfile.file_abstraction.StoreType`. Default is 'AUTO'. 109 """ 110 f = cls(filename, mode='w-', store_type=store_type) 111 112 # File version 113 sync(f._file.create_attr('/', 'brim_version', brim_version)) 114 115 # Root Brillouin_data group 116 sync(f._file.create_group(brim_obj_names.Brillouin_base_path)) 117 118 return f
Create a new brim file with the specified filename. If the file exists already it will generate an error.
Arguments:
- filename (str): Path to the brim file to be created.
- store_type (StoreType): Type of the store to use, as defined in
brimfile.file_abstraction.StoreType. Default is 'AUTO'. - brim_version (str): Version of the brim file format to use. Default is '0.1'.
Returns:
File: An instance of the File class representing the newly created brim file. store_type (str): Type of the store to use, as defined in
brimfile.file_abstraction.StoreType. Default is 'AUTO'.
120 def create_data_group(self, PSD: np.ndarray, frequency: np.ndarray, px_size_um: tuple, *, index: int = None, 121 name: str = None, compression: FileAbstraction.Compression = FileAbstraction.Compression()) -> 'Data': 122 """ 123 Adds a new data entry to the file. 124 Parameters: 125 PSD (np.ndarray): The Power Spectral Density (PSD) data to be added. It must be 4D with dimensions z, y, x, spectrum 126 frequency (np.ndarray): The frequency data corresponding to the PSD. It must be broadcastable to the PSD shape (the most common case is frequency being 1D, in which case the frequency axis is assumed the same for all the spatial coordinates) 127 px_size_um (tuple): A tuple of 3 elements, in the order z,y,x, corresponding to the pixel size in um. Unused dimensions can be set to None. 128 index (int, optional): The index for the new data group. If None, the next available index is used. Defaults to None. 129 name (str, optional): The name for the new data group. Defaults to None. 130 compression (FileAbstraction.Compression, optional): The compression method to use for the data. Defaults to FileAbstraction.Compression.DEFAULT. 131 Returns: 132 Data: The newly created Data object. 133 Raises: 134 IndexError: If the specified index already exists in the dataset. 135 ValueError: If any of the data provided is not valid or consistent 136 """ 137 if PSD.ndim != 4: 138 raise ValueError( 139 "'PSD' must have 4 dimensions (z, y, x, spectrum)") 140 try: 141 np.broadcast_shapes(tuple(frequency.shape), tuple(PSD.shape)) 142 except ValueError as e: 143 raise ValueError(f"frequency (shape: {frequency.shape}) is not broadcastable to PSD (shape: {PSD.shape}): {e}") 144 if len(px_size_um) != 3: 145 raise ValueError("'px_size_um' must have 3 elements (z,y,x); unused dimensions can be set to None") 146 147 return self._create_data_group_raw(PSD, frequency, scanning = None, sparse = False, px_size_um=px_size_um, 148 index=index, name=name, compression=compression)
Adds a new data entry to the file.
Arguments:
- PSD (np.ndarray): The Power Spectral Density (PSD) data to be added. It must be 4D with dimensions z, y, x, spectrum
- frequency (np.ndarray): The frequency data corresponding to the PSD. It must be broadcastable to the PSD shape (the most common case is frequency being 1D, in which case the frequency axis is assumed the same for all the spatial coordinates)
- px_size_um (tuple): A tuple of 3 elements, in the order z,y,x, corresponding to the pixel size in um. Unused dimensions can be set to None.
- index (int, optional): The index for the new data group. If None, the next available index is used. Defaults to None.
- name (str, optional): The name for the new data group. Defaults to None.
- compression (FileAbstraction.Compression, optional): The compression method to use for the data. Defaults to FileAbstraction.Compression.DEFAULT.
Returns:
Data: The newly created Data object.
Raises:
- IndexError: If the specified index already exists in the dataset.
- ValueError: If any of the data provided is not valid or consistent
150 def create_data_group_sparse(self, PSD: np.ndarray, frequency: np.ndarray, scanning: dict, *, timestamp: np.ndarray = None, 151 index: int = None, name: str = None, compression: FileAbstraction.Compression = FileAbstraction.Compression()) -> 'Data': 152 """ 153 Adds a new [sparse data entry](https://github.com/brillouin-imaging/Brillouin-standard-file/blob/main/docs/brim_file_specs.md) to the file. 154 155 Sparse data allows storage of spectra in a flattened format (first dimension is the spectrum index), 156 with spatial mapping provided separately. This is efficient for data with irregular sampling or missing pixels. 157 158 Parameters: 159 PSD (np.ndarray): The Power Spectral Density (PSD) data to be added. First dimension is spectrum index, 160 last dimension contains the spectral data. Shape: (n_spectra, ..., n_freq_points). 161 frequency (np.ndarray): The frequency data corresponding to the PSD. Must be broadcastable to the PSD array. 162 scanning (dict): Dictionary defining the spatial mapping. Must include at least 'Spatial_map' or 'Cartesian_visualisation'. 163 See `brimfile.data.Data._add_data` docstring for detailed structure of the scanning dictionary. 164 timestamp (np.ndarray, optional): Timestamps in milliseconds for the data. Defaults to None. 165 index (int, optional): The index for the new data group. If None, the next available index is used. Defaults to None. 166 name (str, optional): The name for the new data group. Defaults to None. 167 compression (FileAbstraction.Compression, optional): The compression method to use for the data. Defaults to FileAbstraction.Compression.DEFAULT. 168 Returns: 169 Data: The newly created Data object. 170 Raises: 171 IndexError: If the specified index already exists in the dataset. 172 ValueError: If any of the data provided is not valid or consistent 173 """ 174 return self._create_data_group_raw(PSD, frequency, scanning=scanning, timestamp=timestamp, sparse=True, index=index, name=name, compression=compression)
Adds a new sparse data entry to the file.
Sparse data allows storage of spectra in a flattened format (first dimension is the spectrum index), with spatial mapping provided separately. This is efficient for data with irregular sampling or missing pixels.
Arguments:
- PSD (np.ndarray): The Power Spectral Density (PSD) data to be added. First dimension is spectrum index, last dimension contains the spectral data. Shape: (n_spectra, ..., n_freq_points).
- frequency (np.ndarray): The frequency data corresponding to the PSD. Must be broadcastable to the PSD array.
- scanning (dict): Dictionary defining the spatial mapping. Must include at least 'Spatial_map' or 'Cartesian_visualisation'.
See
brimfile.data.Data._add_datadocstring for detailed structure of the scanning dictionary. - timestamp (np.ndarray, optional): Timestamps in milliseconds for the data. Defaults to None.
- index (int, optional): The index for the new data group. If None, the next available index is used. Defaults to None.
- name (str, optional): The name for the new data group. Defaults to None.
- compression (FileAbstraction.Compression, optional): The compression method to use for the data. Defaults to FileAbstraction.Compression.DEFAULT.
Returns:
Data: The newly created Data object.
Raises:
- IndexError: If the specified index already exists in the dataset.
- ValueError: If any of the data provided is not valid or consistent
220 def list_data_groups(self, retrieve_custom_name=False) -> list: 221 """ 222 List all data groups in the brim file. 223 224 Returns: 225 See documentation of brimfile.data.Data.list_data_groups 226 """ 227 return Data.list_data_groups(self._file, retrieve_custom_name)
List all data groups in the brim file.
Returns:
See documentation of brimfile.data.Data.list_data_groups
229 def get_data(self, index: int = 0) -> 'Data': 230 """ 231 Retrieve a Data object for the specified index. 232 233 Args: 234 index (int): The index of the data group to retrieve. 235 236 Returns: 237 Data: The Data object corresponding to the specified index. 238 """ 239 group_name: str = Data._get_existing_group_name(self._file, index) 240 if group_name is None: 241 raise IndexError(f"Data {index} not found") 242 data = Data(self._file, concatenate_paths( 243 brim_obj_names.Brillouin_base_path, group_name)) 244 return data
Retrieve a Data object for the specified index.
Arguments:
- index (int): The index of the data group to retrieve.
Returns:
Data: The Data object corresponding to the specified index.