def __setattr__(self, name: str, val: Any) -> None: if name.startswith("!"): super(GlobalAttributeManager, self).__setattr__(name[1:], val) elif "/" in name: raise KeyError("Attribute name cannot contain slash (/)") else: if self.f is not None: if loompy.compare_loom_spec_version(self.f, "3.0.0") < 0 and "attrs" not in self.f["/"]: normalized = loompy.normalize_attr_values(val, False) self.f.attrs[name] = normalized self.f.flush() val = self.f.attrs[name] # Read it back in to ensure it's synced and normalized normalized = loompy.materialize_attr_values(val) self.__dict__["storage"][name] = normalized else: normalized = loompy.normalize_attr_values(val, True) if name in self.f["attrs"]: del self.f["attrs"][name] if not np.isscalar(normalized) and normalized.dtype == np.object_: self.ds._file.create_dataset("attrs/" + name, data=normalized, dtype=h5py.special_dtype(vlen=str)) else: self.f["attrs"][name] = normalized self.f.flush() val = self.f["attrs"][name][()] # Read it back in to ensure it's synced and normalized normalized = loompy.materialize_attr_values(val) self.__dict__["storage"][name] = normalized
def __init__(self, f: h5py.File) -> None: setattr(self, "!f", f) storage: Dict[str, str] = {} setattr(self, "!storage", storage) if "attrs" not in self.f: for key, val in f.attrs.items(): materialized = loompy.materialize_attr_values(val) self.__dict__["storage"][key] = materialized else: for key, val in f["attrs"].items(): materialized = loompy.materialize_attr_values(val[()]) self.__dict__["storage"][key] = materialized
def __setattr__(self, name: str, val: np.ndarray) -> None: """ Set the value of a named attribute Args: name (str) Name of the attribute val (np.ndarray) Value of the attribute Remarks: Length must match the corresponding matrix dimension The values are automatically HMTL escaped and converted to ASCII for storage """ if name.startswith("!"): super(AttributeManager, self).__setattr__(name[1:], val) else: if self.ds is not None: values = loompy.normalize_attr_values(val) a = ["/row_attrs/", "/col_attrs/"][self.axis] if self.ds.shape[self.axis] != 0 and values.shape[0] != self.ds.shape[self.axis]: raise ValueError(f"Attribute must have exactly {self.ds.shape[self.axis]} values but {len(values)} were given") if self.ds._file[a].__contains__(name): del self.ds._file[a + name] self.ds._file[a + name] = values # TODO: for 2D arrays, use block compression along columns/rows self.ds._file.flush() self.__dict__["storage"][name] = loompy.materialize_attr_values(self.ds._file[a][name][:]) else: self.__dict__["storage"][name] = val
def __setattr__(self, name: str, val: np.ndarray) -> None: """ Set the value of a named attribute Args: name (str) Name of the attribute val (np.ndarray) Value of the attribute Remarks: Length must match the corresponding matrix dimension The values are automatically HMTL escaped and converted to ASCII for storage """ if name.startswith("!"): super(AttributeManager, self).__setattr__(name[1:], val) elif "/" in name: raise KeyError("Attribute name cannot contain slash (/)") else: if self.ds is not None: values = loompy.normalize_attr_values( val, compare_loom_spec_version(self.ds._file, "3.0.0") >= 0) a = ["/row_attrs/", "/col_attrs/"][self.axis] if self.ds.shape[self.axis] != 0 and values.shape[ 0] != self.ds.shape[self.axis]: raise ValueError( f"Attribute '{name}' must have exactly {self.ds.shape[self.axis]} values but {len(values)} were given" ) if self.ds._file[a].__contains__(name): del self.ds._file[a + name] if isinstance(self.ds._file, h5py.File): self.ds._file.create_dataset( a + name, data=values, dtype=h5py.special_dtype(vlen=str) if values.dtype == np.object_ else values.dtype, maxshape=(values.shape[0], ) if len(values.shape) == 1 else (values.shape[0], None), fletcher32=False, compression="gzip", shuffle=False, compression_opts=2) else: self.ds._file.create_dataset( a + name, data=values.astype(np.string_) if values.dtype == np.object_ else values) self.ds._file[a + name].attrs["last_modified"] = timestamp() self.ds._file[a].attrs["last_modified"] = timestamp() self.ds._file.attrs["last_modified"] = timestamp() if isinstance(self.ds._file, h5py.File): self.ds._file.flush() self.__dict__["storage"][ name] = loompy.materialize_attr_values( self.ds._file[a][name][:]) else: self.__dict__["storage"][name] = val
def __getattr__(self, name: str) -> np.ndarray: try: return self.__dict__["storage"][name] except KeyError: if self.f is not None: if name in self.f.attrs: val = self.f.attrs[name] materialized = loompy.materialize_attr_values(val) self.__dict__["storage"][name] = materialized return materialized raise AttributeError( f"'{type(self)}' object has no attribute '{name}'")
def __setattr__(self, name: str, val: Any) -> None: if name.startswith("!"): super(FileAttributeManager, self).__setattr__(name[1:], val) else: if self.f is not None: normalized = loompy.normalize_attr_values(val) self.f.attrs[name] = normalized self.f.flush() val = self.f.attrs[name] # Read it back in to ensure it's synced and normalized normalized = loompy.materialize_attr_values(val) self.__dict__["storage"][name] = normalized
def __getattr__(self, name: str) -> np.ndarray: try: return self.__dict__["storage"][name] except KeyError: if self.f is not None: if loompy.compare_loom_spec_version(self.f, "3.0.0") < 0: if name in self.f.attrs: val = self.f.attrs[name] else: raise AttributeError(f"File has no global attribute '{name}'") else: if name in self.f["attrs"]: val = self.f["attrs"][name] else: raise AttributeError(f"File has no global attribute '{name}'") materialized = loompy.materialize_attr_values(val) self.__dict__["storage"][name] = materialized return materialized
def __getattr__(self, name: str) -> np.ndarray: """ Return the named attribute Args: name (str) Name of the attribute Remarks: The values will be loaded from file, and properly HTML unescaped """ try: vals = self.__dict__["storage"][name] if vals is None: # Read values from the HDF5 file a = ["/row_attrs/", "/col_attrs/"][self.axis] vals = loompy.materialize_attr_values(self.ds._file[a][name][:]) self.__dict__["storage"][name] = vals return vals except KeyError: raise AttributeError(f"'{type(self)}' object has no attribute '{name}'")