def read_multimodal_data(self, attach_zarrobj = False) -> MultimodalData: """ Read MultimodalData """ data = MultimodalData() for key, group in self.root.groups(): unidata = self.read_unimodal_data(group) data.add_data(unidata) if self.root.attrs.get('_selected', None) is not None: data.select_data(self.root.attrs['_selected']) if attach_zarrobj: data._zarrobj = self return data
def write_loom_file(data: MultimodalData, output_file: str) -> None: """ Write a MultimodalData to loom file. Will assert data only contain one type of experiment. """ keys = data.list_data() if len(keys) > 1: raise ValueError( f"Data contain multiple modalities: {','.join(keys)}!") data.select_data(keys[0]) matrices = data.list_keys() assert "X" in matrices if len(matrices) == 0: raise ValueError("Could not write empty matrix to a loom file!") def _process_attrs(key_name: str, attrs: pd.DataFrame, attrs_multi: dict) -> Dict[str, object]: res_dict = {key_name: attrs.index.values} for key in attrs.columns: res_dict[key] = np.array(attrs[key].values) for key, value in attrs_multi.items(): if value.ndim > 1: # value.ndim == 1 refers to np.recarray, which will not be written to a loom file. res_dict[key] = value if value.shape[1] > 1 else value[:, 0] return res_dict row_attrs = _process_attrs("Gene", data.var, data.varm) col_attrs = _process_attrs("CellID", data.obs, data.obsm) accession_key = "featureid" if "featureid" in row_attrs else ( "gene_ids" if "gene_ids" in row_attrs else None) if accession_key is not None: row_attrs["Accession"] = row_attrs.pop(accession_key) layers = {} for matkey in matrices: layers["" if matkey == "X" else matkey] = data.get_matrix(matkey).T file_attrs = {} for key, value in data.uns.items(): if isinstance(value, str): file_attrs[key] = value import loompy loompy.create(output_file, layers, row_attrs, col_attrs, file_attrs=file_attrs) logger.info(f"{output_file} is written.")