From 7008df4b414d829a59cb8d9c2d514300e4bf8db9 Mon Sep 17 00:00:00 2001 From: Florian Huber Date: Mon, 18 May 2026 17:45:32 +0200 Subject: [PATCH 1/3] rename meta to metadata --- graphconstructor/graph.py | 66 +++++++++---------- graphconstructor/importers.py | 49 +++++++++++--- graphconstructor/operators/disparity.py | 34 +++++----- .../operators/doubly_stochastic.py | 16 ++--- .../operators/enhanced_configuration_model.py | 6 +- graphconstructor/operators/knn_selector.py | 2 +- .../locally_adaptive_sparsification.py | 12 ++-- .../operators/marginal_likelihood.py | 52 ++++++++------- .../operators/minimum_spanning_tree.py | 4 +- graphconstructor/operators/noise_corrected.py | 12 ++-- .../operators/weight_threshold.py | 7 +- 11 files changed, 152 insertions(+), 108 deletions(-) diff --git a/graphconstructor/graph.py b/graphconstructor/graph.py index a6a4d5e..8f4460d 100644 --- a/graphconstructor/graph.py +++ b/graphconstructor/graph.py @@ -24,7 +24,7 @@ class Graph: - `directed`: True if directed, else undirected (stored symmetric) - `weighted`: True if edge weights are meaningful; if False, all edges are 1.0 - `mode`: "distance" or "similarity" (for interpretation of weights) - - `meta`: pandas DataFrame with n rows (optional). May have a 'name' column. + - `metadata`: pandas DataFrame with n rows (optional). May have a 'name' column. - `ignore_selfloops`: If True, self-loops are ignored/removed (default for undirected graphs) - `keep_explicit_zeros`: If True, explicit zeros in adjacency are kept (default for distance graphs) """ @@ -32,7 +32,7 @@ class Graph: directed: bool weighted: bool mode: str - meta: pd.DataFrame | None = None + metadata: pd.DataFrame | None = None ignore_selfloops: Optional[bool] = None keep_explicit_zeros: Optional[bool] = None @@ -107,7 +107,7 @@ def from_csr( *, directed: bool = False, weighted: bool = True, - meta: pd.DataFrame | None = None, + metadata: pd.DataFrame | None = None, ignore_selfloops: bool = None, keep_explicit_zeros: bool = None, sym_op: SymOp = "max", @@ -137,15 +137,15 @@ def from_csr( A = _drop_diagonal(A) n = A.shape[0] - if meta is not None: - if len(meta) != n: - raise ValueError(f"meta has {len(meta)} rows but adjacency is {n}x{n}.") - meta = meta.reset_index(drop=True) + if metadata is not None: + if len(metadata) != n: + raise ValueError(f"metadata has {len(metadata)} rows but adjacency is {n}x{n}.") + metadata = metadata.reset_index(drop=True) return cls( adj=A.astype(float, copy=False), directed=directed, weighted=weighted, mode=mode, ignore_selfloops=ignore_selfloops, - meta=meta, + metadata=metadata, keep_explicit_zeros=keep_explicit_zeros, ) @@ -168,7 +168,7 @@ def from_edges( *, directed: bool = False, weighted: bool = True, - meta: pd.DataFrame | None = None, + metadata: pd.DataFrame | None = None, ignore_selfloops: Optional[bool] = None, keep_explicit_zeros: Optional[bool] = None, sym_op: SymOp = "max", @@ -208,7 +208,7 @@ def from_edges( weighted=weighted_eff, mode=mode, ignore_selfloops=ignore_selfloops, - meta=meta, sym_op=sym_op, + metadata=metadata, sym_op=sym_op, keep_explicit_zeros=keep_explicit_zeros, ) @@ -298,9 +298,9 @@ def from_graphml( attrs = G_nx.nodes[node] row = {col: attrs.get(col, None) for col in all_cols} rows.append(row) - meta = pd.DataFrame(rows) + metadata = pd.DataFrame(rows) else: - meta = None + metadata = None # Build Graph via from_csr to respect the usual symmetrization / defaults return cls.from_csr( @@ -308,7 +308,7 @@ def from_graphml( mode=mode, directed=directed, weighted=weighted, - meta=meta, + metadata=metadata, ignore_selfloops=ignore_selfloops, keep_explicit_zeros=keep_explicit_zeros, ) @@ -333,8 +333,8 @@ def has_self_loops(self) -> bool: @property def node_names(self) -> list[str] | list[int]: - if self.meta is not None and "name" in self.meta.columns: - return self.meta["name"].tolist() + if self.metadata is not None and "name" in self.metadata.columns: + return self.metadata["name"].tolist() return list(range(self.n_nodes)) # -------- Editing -------- @@ -346,8 +346,8 @@ def drop(self, nodes: Iterable[int | str]) -> "Graph": nodes = [nodes] to_drop_idx: set[int] = set() - if self.meta is not None and "name" in self.meta.columns: - name_to_idx = {name: i for i, name in enumerate(self.meta["name"].tolist())} + if self.metadata is not None and "name" in self.metadata.columns: + name_to_idx = {name: i for i, name in enumerate(self.metadata["name"].tolist())} else: name_to_idx = {} @@ -368,8 +368,8 @@ def drop(self, nodes: Iterable[int | str]) -> "Graph": keep_mask[list(to_drop_idx)] = False A2 = self.adj[keep_mask][:, keep_mask].tocsr(copy=False) - meta2 = self.meta.loc[keep_mask].reset_index(drop=True) if self.meta is not None else None - return Graph(adj=A2, directed=self.directed, weighted=self.weighted, mode=self.mode, meta=meta2) + metadata2 = self.metadata.loc[keep_mask].reset_index(drop=True) if self.metadata is not None else None + return Graph(adj=A2, directed=self.directed, weighted=self.weighted, mode=self.mode, metadata=metadata2) # ----- Convert distance/similarity ----- def convert_mode( @@ -434,7 +434,7 @@ def convert_mode( mode=target_mode, directed=self.directed, weighted=self.weighted, - meta=None if self.meta is None else self.meta.copy(), + metadata=None if self.metadata is None else self.metadata.copy(), ) # -------- Exporters -------- @@ -447,10 +447,10 @@ def to_networkx(self): create_using = nx.DiGraph if self.directed else nx.Graph G = nx.from_scipy_sparse_array(self.adj, create_using=create_using) - # attach node attributes from meta - if self.meta is not None: - for col in self.meta.columns: - nx.set_node_attributes(G, {i: self.meta.iloc[i, self.meta.columns.get_loc(col)] + # attach node attributes from metadata + if self.metadata is not None: + for col in self.metadata.columns: + nx.set_node_attributes(G, {i: self.metadata.iloc[i, self.metadata.columns.get_loc(col)] for i in range(self.n_nodes)}, name=col) return G @@ -477,9 +477,9 @@ def to_igraph(self): g.es["weight"] = [1.0] * len(rows) # node attributes - if self.meta is not None: - for col in self.meta.columns: - g.vs[col] = self.meta[col].tolist() + if self.metadata is not None: + for col in self.metadata.columns: + g.vs[col] = self.metadata[col].tolist() return g def to_graphml(self, path, *, include_graph_attrs: bool = True) -> None: @@ -519,17 +519,17 @@ def copy(self) -> "Graph": directed=self.directed, weighted=self.weighted, mode=self.mode, - meta=None if self.meta is None else self.meta.copy(), + metadata=None if self.metadata is None else self.metadata.copy(), ) def sorted_by(self, col: str) -> "Graph": - """Return a new graph with nodes permuted by ascending meta[col].""" - if self.meta is None or col not in self.meta.columns: + """Return a new graph with nodes permuted by ascending metadata[col].""" + if self.metadata is None or col not in self.metadata.columns: raise KeyError(f"Column '{col}' not found in metadata.") - order = np.argsort(self.meta[col].to_numpy()) + order = np.argsort(self.metadata[col].to_numpy()) A2 = self.adj[order][:, order] - meta2 = self.meta.iloc[order].reset_index(drop=True) - return Graph(adj=A2, directed=self.directed, weighted=self.weighted, mode=self.mode, meta=meta2) + metadata2 = self.metadata.iloc[order].reset_index(drop=True) + return Graph(adj=A2, directed=self.directed, weighted=self.weighted, mode=self.mode, metadata=metadata2) def degree(self, ignore_weights: bool = False) -> np.ndarray | tuple[np.ndarray, np.ndarray]: """Return node degree(s). diff --git a/graphconstructor/importers.py b/graphconstructor/importers.py index 313e734..71bc602 100644 --- a/graphconstructor/importers.py +++ b/graphconstructor/importers.py @@ -7,15 +7,39 @@ Mode = Literal["distance", "similarity"] -def from_dense(arr, mode, *, directed=False, weighted=True, meta=None, sym_op="max") -> Graph: - return Graph.from_dense(arr, directed=directed, weighted=weighted, mode=mode, meta=meta, sym_op=sym_op) +def from_dense( + arr, + mode, + *, + directed=False, + weighted=True, + metadata=None, + sym_op="max" + ) -> Graph: + return Graph.from_dense(arr, directed=directed, weighted=weighted, mode=mode, metadata=metadata, sym_op=sym_op) -def from_csr(adj, mode, *, directed=False, weighted=True, meta=None, sym_op="max") -> Graph: - return Graph.from_csr(adj, directed=directed, weighted=weighted, mode=mode, meta=meta, sym_op=sym_op) +def from_csr( + adj, + mode, + *, + directed=False, + weighted=True, + metadata=None, + sym_op="max" + ) -> Graph: + return Graph.from_csr(adj, directed=directed, weighted=weighted, mode=mode, metadata=metadata, sym_op=sym_op) -def from_knn(indices, distances, *, store_weights=True, directed=False, meta=None, sym_op="max") -> Graph: +def from_knn( + indices, + distances, + *, + store_weights=True, + directed=False, + metadata=None, + sym_op="max" + ) -> Graph: ind, dist = _coerce_knn_inputs(indices, distances) n_query, k = ind.shape @@ -34,10 +58,19 @@ def from_knn(indices, distances, *, store_weights=True, directed=False, meta=Non n_full = _infer_n_from_indices(ind) A = sp.csr_matrix((weights, (rows, cols)), shape=(n_full, n_full)) return Graph.from_csr(A, directed=directed, weighted=store_weights, mode="distance", - meta=meta, sym_op=sym_op) + metadata=metadata, sym_op=sym_op) -def from_ann(ann, query_data, k: int, *, store_weights=True, directed=False, meta=None, sym_op="max") -> Graph: +def from_ann( + ann, + query_data, + k: int, + *, + store_weights=True, + directed=False, + metadata=None, + sym_op="max" + ) -> Graph: idx = ann.index if hasattr(ann, "index") else ann if hasattr(idx, "indices_") and getattr(idx, "indices_") is not None: ind = np.asarray(getattr(idx, "indices_"))[:, :k] @@ -47,7 +80,7 @@ def from_ann(ann, query_data, k: int, *, store_weights=True, directed=False, met raise TypeError("from_ann requires query_data when index has no cached neighbors.") ind, dist = idx.query(query_data, k=k) return from_knn(ind, dist, store_weights=store_weights, directed=directed, - meta=meta, sym_op=sym_op) + metadata=metadata, sym_op=sym_op) # helper functions --------------------------------------------- diff --git a/graphconstructor/operators/disparity.py b/graphconstructor/operators/disparity.py index d90913a..ca8f542 100644 --- a/graphconstructor/operators/disparity.py +++ b/graphconstructor/operators/disparity.py @@ -38,12 +38,12 @@ class DisparityFilter(GraphOperator): For undirected graphs only. If "or" (default), keep if either endpoint finds the edge significant (this matches the R backbone code). If "and", require both endpoints to be significant (stricter). - copy_meta : bool + copy_metadata : bool Copy metadata (True) or keep reference (False). """ alpha: float = 0.05 rule: UndirectedRule = "or" - copy_meta: bool = True + copy_metadata: bool = True supported_modes = ["similarity"] def _undirected(self, G: Graph) -> Graph: @@ -51,10 +51,11 @@ def _undirected(self, G: Graph) -> Graph: if (A.data < 0).any(): raise ValueError("DisparityFilter requires nonnegative weights.") if A.nnz == 0: - return Graph.from_csr(A.copy(), directed=False, weighted=G.weighted, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), - mode="similarity", - sym_op="max") + return Graph.from_csr( + A.copy(), directed=False, weighted=G.weighted, + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), + mode="similarity", + sym_op="max") # strengths and degrees (row-wise) strength = np.asarray(A.sum(axis=1)).ravel() @@ -92,18 +93,20 @@ def _undirected(self, G: Graph) -> Graph: A_f = sp.csr_matrix((w[keep], (rows[keep], cols[keep])), shape=A.shape) # Symmetrize to be safe (weights preserved as in input) A_f = A_f.maximum(A_f.T) - return Graph.from_csr(A_f, directed=False, weighted=G.weighted, - mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), - sym_op="max") + return Graph.from_csr( + A_f, directed=False, weighted=G.weighted, + mode=G.mode, + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), + sym_op="max") def _directed(self, G: Graph) -> Graph: A = G.adj.tocsr(copy=False) if (A.data < 0).any(): raise ValueError("DisparityFilter requires nonnegative weights.") if A.nnz == 0: - return Graph.from_csr(A.copy(), directed=True, weighted=G.weighted, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta)) + return Graph.from_csr( + A.copy(), directed=True, weighted=G.weighted, + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata)) s_out = np.asarray(A.sum(axis=1)).ravel() @@ -132,9 +135,10 @@ def _directed(self, G: Graph) -> Graph: keep = np.minimum(pval_out, pval_in) <= self.alpha A_f = sp.csr_matrix((w[keep], (rows[keep], cols[keep])), shape=A.shape) - return Graph.from_csr(A_f, directed=True, weighted=G.weighted, - mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta)) + return Graph.from_csr( + A_f, directed=True, weighted=G.weighted, + mode=G.mode, + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata)) def apply(self, G: Graph) -> Graph: self._check_mode_supported(G) diff --git a/graphconstructor/operators/doubly_stochastic.py b/graphconstructor/operators/doubly_stochastic.py index 406525c..9c07900 100644 --- a/graphconstructor/operators/doubly_stochastic.py +++ b/graphconstructor/operators/doubly_stochastic.py @@ -29,13 +29,13 @@ class DoublyStochasticNormalize(GraphOperator): sum is in [1 - tolerance, 1 + tolerance]. Default 1e-5. max_iter : int Maximum iterations. Default 10_000. - copy_meta : bool + copy_metadata : bool Copy metadata frame if present. Default True. """ tolerance: float = 1e-5 max_iter: int = 10_000 - copy_meta: bool = True + copy_metadata: bool = True supported_modes = ["similarity"] def apply(self, G: Graph) -> Graph: @@ -55,7 +55,7 @@ def apply(self, G: Graph) -> Graph: directed=G.directed, weighted=True, mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), sym_op="max", ) @@ -137,7 +137,7 @@ def apply(self, G: Graph) -> Graph: directed=G.directed, weighted=True, mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), sym_op="max", ) @@ -165,13 +165,13 @@ class DoublyStochasticBackbone(GraphOperator): max_iter : int Maximum Sinkhorn iterations passed to DoublyStochasticNormalize. Default 10_000. - copy_meta : bool + copy_metadata : bool Copy metadata frame if present. Default True. """ tolerance: float = 1e-5 max_iter: int = 10_000 - copy_meta: bool = True + copy_metadata: bool = True supported_modes = ["similarity"] def apply(self, G: Graph) -> Graph: @@ -185,7 +185,7 @@ def apply(self, G: Graph) -> Graph: normalized = DoublyStochasticNormalize( tolerance=self.tolerance, max_iter=self.max_iter, - copy_meta=self.copy_meta, + copy_metadata=self.copy_metadata, ).apply(G) A_scaled = normalized.adj.tocsr(copy=False) @@ -203,7 +203,7 @@ def apply(self, G: Graph) -> Graph: directed=G.directed, weighted=True, mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), sym_op="max", ) diff --git a/graphconstructor/operators/enhanced_configuration_model.py b/graphconstructor/operators/enhanced_configuration_model.py index 7d5089e..7262ff6 100644 --- a/graphconstructor/operators/enhanced_configuration_model.py +++ b/graphconstructor/operators/enhanced_configuration_model.py @@ -253,7 +253,7 @@ class EnhancedConfigurationModelFilter(GraphOperator): normalized similarities in [0, 1] using the quantile strategy. Use ``None`` to force raw weights, or ``"quantile"``/``"linear"`` to force pseudo-count conversion. - copy_meta : bool, default=True + copy_metadata : bool, default=True If ``True``, copy graph metadata to the returned graph. If ``False``, keep the original metadata reference. x_transform_idx : int, default=0 @@ -273,7 +273,7 @@ class EnhancedConfigurationModelFilter(GraphOperator): """ alpha: float = 0.05 replace_weights_by_p_values: bool = False - copy_meta: bool = True + copy_metadata: bool = True x_transform_idx: int = 0 y_transform_idx: int = 0 weight_conversion: str = "auto" @@ -404,7 +404,7 @@ def _undirected(self, G: Graph) -> Graph: directed=False, weighted=True, mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), sym_op="max", ) diff --git a/graphconstructor/operators/knn_selector.py b/graphconstructor/operators/knn_selector.py index 7c1756a..25a9b69 100644 --- a/graphconstructor/operators/knn_selector.py +++ b/graphconstructor/operators/knn_selector.py @@ -75,5 +75,5 @@ def apply(self, G: Graph) -> Graph: directed=G.directed, weighted=G.weighted, mode=self.mode, - meta=G.meta.copy() if G.meta is not None else None, + metadata=G.metadata.copy() if G.metadata is not None else None, ) diff --git a/graphconstructor/operators/locally_adaptive_sparsification.py b/graphconstructor/operators/locally_adaptive_sparsification.py index 43e6fc7..c6db57d 100644 --- a/graphconstructor/operators/locally_adaptive_sparsification.py +++ b/graphconstructor/operators/locally_adaptive_sparsification.py @@ -39,13 +39,13 @@ class LocallyAdaptiveSparsification(GraphOperator): Significance level in (0,1]. rule : {"or","and"} Combination rule for UNDIRECTED graphs. Ignored for directed graphs. - copy_meta : bool + copy_metadata : bool If True, copy metadata frame onto the result graph. """ alpha: float = 0.05 rule: UndirectedRule = "or" - copy_meta: bool = True + copy_metadata: bool = True supported_modes = ["similarity"] # ---- helpers ---- @@ -109,7 +109,7 @@ def _apply_directed(self, G: Graph) -> Graph: if A.nnz == 0: return Graph.from_csr( A.copy(), directed=True, weighted=G.weighted, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta) + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata) ) # Out-side mask on A @@ -129,7 +129,7 @@ def _apply_directed(self, G: Graph) -> Graph: return Graph.from_csr( A_kept, directed=True, weighted=G.weighted, mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta) + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata) ) def _apply_undirected(self, G: Graph) -> Graph: @@ -140,7 +140,7 @@ def _apply_undirected(self, G: Graph) -> Graph: return Graph.from_csr( A.copy(), directed=False, weighted=G.weighted, mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), sym_op="max", ) @@ -163,7 +163,7 @@ def _apply_undirected(self, G: Graph) -> Graph: return Graph.from_csr( A_kept, directed=False, weighted=G.weighted, mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), sym_op="max", ) diff --git a/graphconstructor/operators/marginal_likelihood.py b/graphconstructor/operators/marginal_likelihood.py index 2898b7f..a3a29fb 100644 --- a/graphconstructor/operators/marginal_likelihood.py +++ b/graphconstructor/operators/marginal_likelihood.py @@ -36,7 +36,7 @@ class MarginalLikelihoodFilter(GraphOperator): If True, self-loops are excluded from testing. Graph already drops self-loops by construction; this flag is here for clarity and future loopless corrections. Currently it only ensures i != j in filtering. - copy_meta : bool, default True + copy_metadata : bool, default True If True, copies metadata frame; set to False to reuse reference. Notes @@ -50,7 +50,7 @@ class MarginalLikelihoodFilter(GraphOperator): alpha: float float_scaling: float = 20. assume_loopless: bool = False - copy_meta: bool = True + copy_metadata: bool = True supported_modes = ["similarity"] def _cast_weights_to_int(self, w: np.ndarray, max_weight=None) -> np.ndarray: @@ -72,18 +72,20 @@ def _undirected_filter(self, G: Graph) -> Graph: T = 0.5 * float(k.sum()) # total unit edges if T <= 0: # degenerate: no edges to keep - return Graph.from_csr(A.copy() * 0.0, directed=False, weighted=G.weighted, - mode=G.mode, - meta=G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta, - sym_op="max") + return Graph.from_csr( + A.copy() * 0.0, directed=False, weighted=G.weighted, + mode=G.mode, + metadata=G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata, + sym_op="max") # Work on upper triangle to avoid double-testing undirected pairs Au = sp.triu(A, k=1).tocoo() if Au.nnz == 0: - return Graph.from_csr(A.copy() * 0.0, directed=False, weighted=G.weighted, - mode=G.mode, - meta=G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta, - sym_op="max") + return Graph.from_csr( + A.copy() * 0.0, directed=False, weighted=G.weighted, + mode=G.mode, + metadata=G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata, + sym_op="max") # integerized realized weights w = self._cast_weights_to_int(Au.data, max_weight=Au.data.max()) @@ -114,10 +116,11 @@ def _undirected_filter(self, G: Graph) -> Graph: data_full = np.concatenate([data, data]) A_f = sp.csr_matrix((data_full, (rows_full, cols_full)), shape=A.shape) - return Graph.from_csr(A_f, directed=False, weighted=G.weighted, - mode=G.mode, - meta=G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta, - sym_op="max") + return Graph.from_csr( + A_f, directed=False, weighted=G.weighted, + mode=G.mode, + metadata=G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata, + sym_op="max") def _directed_filter(self, G: Graph) -> Graph: A = G.adj.tocsr(copy=False) @@ -126,15 +129,17 @@ def _directed_filter(self, G: Graph) -> Graph: kin = np.asarray(A.sum(axis=0)).ravel() T = float(kout.sum()) if T <= 0: - return Graph.from_csr(A.copy() * 0.0, directed=True, weighted=G.weighted, - mode=G.mode, - meta=G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta) + return Graph.from_csr( + A.copy() * 0.0, directed=True, weighted=G.weighted, + mode=G.mode, + metadata=G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata) coo = A.tocoo() if coo.nnz == 0: - return Graph.from_csr(A.copy() * 0.0, directed=True, weighted=G.weighted, - mode=G.mode, - meta=G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta) + return Graph.from_csr( + A.copy() * 0.0, directed=True, weighted=G.weighted, + mode=G.mode, + metadata=G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata) # Optionally exclude self-edges (currently Graph anyway drops them) if self.assume_loopless: @@ -157,9 +162,10 @@ def _directed_filter(self, G: Graph) -> Graph: data = coo.data[keep] if G.weighted else np.ones(keep.sum(), dtype=float) A_f = sp.csr_matrix((data, (rows, cols)), shape=A.shape) - return Graph.from_csr(A_f, directed=True, weighted=G.weighted, - mode=G.mode, - meta=G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta) + return Graph.from_csr( + A_f, directed=True, weighted=G.weighted, + mode=G.mode, + metadata=G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata) def apply(self, G: Graph) -> Graph: self._check_mode_supported(G) diff --git a/graphconstructor/operators/minimum_spanning_tree.py b/graphconstructor/operators/minimum_spanning_tree.py index ce4d702..e66907b 100644 --- a/graphconstructor/operators/minimum_spanning_tree.py +++ b/graphconstructor/operators/minimum_spanning_tree.py @@ -27,7 +27,7 @@ class MinimumSpanningTree(GraphOperator): but with exactly n_nodes - 1 edges (if n_nodes > 0). """ - copy_meta: bool = True + copy_metadata: bool = True # Distance: classical MST; Similarity: maximum spanning tree supported_modes = ["distance", "similarity"] @@ -91,7 +91,7 @@ def apply(self, G: Graph) -> Graph: directed=False, weighted=G.weighted, mode=G.mode, - meta=G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta, + metadata=G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata, sym_op="max", ignore_selfloops=G.ignore_selfloops, keep_explicit_zeros=G.keep_explicit_zeros, diff --git a/graphconstructor/operators/noise_corrected.py b/graphconstructor/operators/noise_corrected.py index 868cf7a..def8347 100644 --- a/graphconstructor/operators/noise_corrected.py +++ b/graphconstructor/operators/noise_corrected.py @@ -23,12 +23,12 @@ class NoiseCorrected(GraphOperator): - "constant": g'(n) = 2*kappa / (kappa*n + 1)^2 (hold margins fixed) - "full": g'(n) = 2*(kappa + n*dκ/dn) / (kappa*n + 1)^2, where dκ/dn = 1/(Ni*Nj) - Ntot*(Ni+Nj)/(Ni*Nj)^2 - copy_meta : bool + copy_metadata : bool If True, copy metadata DataFrame; otherwise keep reference. """ delta: float = 1.64 derivative: str = "constant" - copy_meta: bool = True + copy_metadata: bool = True supported_modes = ["similarity"] # ---------- Bayesian shrinkage for P_ij ---------- @@ -118,7 +118,7 @@ def _apply_directed(self, G: Graph) -> Graph: directed=True, weighted=G.weighted, mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), ) row_sum = np.asarray(A.sum(axis=1)).ravel() @@ -136,7 +136,7 @@ def _apply_directed(self, G: Graph) -> Graph: directed=True, weighted=G.weighted, mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), ) def _apply_undirected(self, G: Graph) -> Graph: @@ -149,7 +149,7 @@ def _apply_undirected(self, G: Graph) -> Graph: directed=False, weighted=G.weighted, mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), sym_op="max", ) @@ -175,7 +175,7 @@ def _apply_undirected(self, G: Graph) -> Graph: directed=False, weighted=G.weighted, mode=G.mode, - meta=(G.meta.copy() if (self.copy_meta and G.meta is not None) else G.meta), + metadata=(G.metadata.copy() if (self.copy_metadata and G.metadata is not None) else G.metadata), sym_op="max", ) diff --git a/graphconstructor/operators/weight_threshold.py b/graphconstructor/operators/weight_threshold.py index b0ec12d..87e6d8c 100644 --- a/graphconstructor/operators/weight_threshold.py +++ b/graphconstructor/operators/weight_threshold.py @@ -32,6 +32,7 @@ def apply(self, G: Graph) -> Graph: rows, cols = coo.row[keep], coo.col[keep] w = coo.data[keep] if G.weighted else np.ones(keep.sum(), dtype=float) A = sp.csr_matrix((w, (rows, cols)), shape=csr.shape) - return Graph.from_csr(A, directed=G.directed, weighted=G.weighted, - mode=self.mode, - meta=None if G.meta is None else G.meta.copy(), sym_op="max") + return Graph.from_csr( + A, directed=G.directed, weighted=G.weighted, + mode=self.mode, + metadata=None if G.metadata is None else G.metadata.copy(), sym_op="max") From 930d3693eb444dbaf3f1b35531403e0df4093443 Mon Sep 17 00:00:00 2001 From: Florian Huber Date: Mon, 18 May 2026 17:45:45 +0200 Subject: [PATCH 2/3] rename meta to metadata --- tests/test_disparity.py | 8 ++-- tests/test_doubly_stochastic.py | 8 ++-- tests/test_graph.py | 48 +++++++++---------- tests/test_importers.py | 2 +- tests/test_locally_adaptive_sparsification.py | 10 ++-- tests/test_marginal_likelihood_filter.py | 8 ++-- tests/test_minimum_spanning_tree.py | 22 ++++----- tests/test_noise_corrected.py | 8 ++-- 8 files changed, 57 insertions(+), 57 deletions(-) diff --git a/tests/test_disparity.py b/tests/test_disparity.py index 41a4add..98f7e75 100644 --- a/tests/test_disparity.py +++ b/tests/test_disparity.py @@ -109,10 +109,10 @@ def test_disparity_rejects_negative_weights(): def test_disparity_preserves_flags_and_copies_metadata(): meta = pd.DataFrame({"name": ["a", "b", "c"], "grp": [1, 0, 1]}) A = _csr([0.6, 0.4, 0.7], [0, 1, 2], [1, 2, 0], 3) - G0 = Graph.from_csr(A, directed=False, weighted=True, mode="similarity", meta=meta, sym_op="max") + G0 = Graph.from_csr(A, directed=False, weighted=True, mode="similarity", metadata=meta, sym_op="max") - out = DisparityFilter(alpha=0.2, rule="or", copy_meta=True).apply(G0) + out = DisparityFilter(alpha=0.2, rule="or", copy_metadata=True).apply(G0) assert not out.directed and out.weighted - if out.meta is not None: + if out.metadata is not None: meta.loc[0, "grp"] = 999 - assert out.meta.loc[0, "grp"] == 1 + assert out.metadata.loc[0, "grp"] == 1 diff --git a/tests/test_doubly_stochastic.py b/tests/test_doubly_stochastic.py index 2a5c792..d321ed2 100644 --- a/tests/test_doubly_stochastic.py +++ b/tests/test_doubly_stochastic.py @@ -275,15 +275,15 @@ def test_doubly_stochastic_all_zero_matrix_noop(): def test_doubly_stochastic_preserves_flags_and_copies_metadata(): meta = pd.DataFrame({"name": ["a", "b", "c"], "group": [1, 0, 1]}) A = _csr([0.4, 0.6, 0.3], [0, 1, 2], [1, 2, 0], 3) - G0 = Graph.from_csr(A, directed=False, weighted=True, mode="similarity", meta=meta, sym_op="max") + G0 = Graph.from_csr(A, directed=False, weighted=True, mode="similarity", metadata=meta, sym_op="max") - op = DoublyStochasticNormalize(tolerance=1e-6, max_iter=10_000, copy_meta=True) + op = DoublyStochasticNormalize(tolerance=1e-6, max_iter=10_000, copy_metadata=True) G = op.apply(G0) # Flags assert not G.directed and G.weighted # Metadata copied: changing original shouldn't affect result - if G.meta is not None: + if G.metadata is not None: meta.loc[0, "group"] = 999 - assert G.meta.loc[0, "group"] == 1 + assert G.metadata.loc[0, "group"] == 1 diff --git a/tests/test_graph.py b/tests/test_graph.py index da3f498..f28cced 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -132,12 +132,12 @@ def test_from_csr_unweighted_forces_unit_weights(): def test_from_csr_metadata_alignment_and_names(): A = _csr([1.0], [0], [1], 2) meta = pd.DataFrame({"name": ["a", "b"], "cls": [0, 1]}) - G = Graph.from_csr(A, directed=False, weighted=True, mode="distance", meta=meta) + G = Graph.from_csr(A, directed=False, weighted=True, mode="distance", metadata=meta) assert G.node_names == ["a", "b"] - assert list(G.meta.columns) == ["name", "cls"] + assert list(G.metadata.columns) == ["name", "cls"] - with pytest.raises(ValueError, match="meta has .* rows"): - Graph.from_csr(A, directed=False, weighted=True, mode="distance", meta=meta.iloc[:1]) + with pytest.raises(ValueError, match="metadata has .* rows"): + Graph.from_csr(A, directed=False, weighted=True, mode="distance", metadata=meta.iloc[:1]) def test_from_edges_missing_weights(): @@ -197,7 +197,7 @@ def test_has_self_loops_property_false_by_default(): def test_drop_by_index_and_name_updates_adj_and_meta(): A = _csr([1, 1, 1], [0, 0, 1], [1, 2, 2], 3) meta = pd.DataFrame({"name": ["a", "b", "c"], "cls": [0, 1, 1]}) - G = Graph.from_csr(A, directed=False, weighted=True, mode="distance", meta=meta) + G = Graph.from_csr(A, directed=False, weighted=True, mode="distance", metadata=meta) G2 = G.drop(["b"]) # drop name "b" (index 1) assert G2.n_nodes == 2 @@ -231,7 +231,7 @@ def test_drop_single_value(): """Test dropping a single int/str (not in list).""" A = _csr([1], [0], [1], 3) meta = pd.DataFrame({"name": ["a", "b", "c"]}) - G = Graph.from_csr(A, directed=False, mode="distance", meta=meta) + G = Graph.from_csr(A, directed=False, mode="distance", metadata=meta) G2 = G.drop(1) # single int assert G2.n_nodes == 2 @@ -243,7 +243,7 @@ def test_drop_single_value(): def test_sorted_by_permuted_order(): A = _csr([1, 1], [0, 1], [1, 2], 3) meta = pd.DataFrame({"name": ["c", "a", "b"], "score": [3, 1, 2]}) - G = Graph.from_csr(A, directed=False, weighted=True, mode="distance", meta=meta) + G = Graph.from_csr(A, directed=False, weighted=True, mode="distance", metadata=meta) G2 = G.sorted_by("score") # names should be ordered by score ascending: a, b, c assert G2.node_names == ["a", "b", "c"] @@ -255,14 +255,14 @@ def test_copy_creates_independent_graph(): """Modifications to copy shouldn't affect original.""" A = _csr([1], [0], [1], 2) meta = pd.DataFrame({"name": ["a", "b"]}) - G = Graph.from_csr(A, mode="distance", meta=meta) + G = Graph.from_csr(A, mode="distance", metadata=meta) G2 = G.copy() G2.adj.data[0] = 999.0 assert G.adj.data[0] != 999.0 # original unchanged - G2.meta.iloc[0, 0] = "changed" - assert G.meta.iloc[0, 0] == "a" # original unchanged + G2.metadata.iloc[0, 0] = "changed" + assert G.metadata.iloc[0, 0] == "a" # original unchanged # ----------------- utilities ----------------- @@ -353,7 +353,7 @@ def test_graph_degree_method_selfloops_counted_twice_weighted(): def test_to_networkx_types_and_node_attributes(): A = _csr([0.5, 0.7], [0, 1], [1, 2], 3) meta = pd.DataFrame({"name": ["n0", "n1", "n2"], "cls": [0, 1, 1]}) - G = Graph.from_csr(A, directed=False, weighted=True, mode="distance", meta=meta) + G = Graph.from_csr(A, directed=False, weighted=True, mode="distance", metadata=meta) nxG = G.to_networkx() import networkx as nx @@ -373,7 +373,7 @@ def test_graphml_roundtrip_undirected_with_meta(tmp_path, S_dense, meta_df): directed=False, weighted=True, mode="similarity", - meta=meta_df, + metadata=meta_df, ) path = tmp_path / "graph_undirected.graphml" @@ -392,11 +392,11 @@ def test_graphml_roundtrip_undirected_with_meta(tmp_path, S_dense, meta_df): np.testing.assert_array_almost_equal(G2.adj.toarray(), G.adj.toarray()) # Metadata should be preserved (content-wise) - assert G2.meta is not None + assert G2.metadata is not None # Compare metadata ignoring column order and dtype - meta1 = G2.meta.reindex(sorted(G2.meta.columns), axis=1).reset_index(drop=True) - meta2 = G.meta.reindex(sorted(G.meta.columns), axis=1).reset_index(drop=True) + meta1 = G2.metadata.reindex(sorted(G2.metadata.columns), axis=1).reset_index(drop=True) + meta2 = G.metadata.reindex(sorted(G.metadata.columns), axis=1).reset_index(drop=True) pd.testing.assert_frame_equal(meta1, meta2, check_dtype=False) @@ -460,10 +460,10 @@ def test_from_graphml_builds_metadata_from_node_attributes(tmp_path): G = Graph.from_graphml(path, default_mode="similarity") assert G.n_nodes == 2 - assert G.meta is not None - assert list(G.meta.columns) == ["group", "name"] or sorted(G.meta.columns) == ["group", "name"] + assert G.metadata is not None + assert list(G.metadata.columns) == ["group", "name"] or sorted(G.metadata.columns) == ["group", "name"] # Check content, ignoring column order and dtype - meta_sorted = G.meta.reindex(sorted(G.meta.columns), axis=1) + meta_sorted = G.metadata.reindex(sorted(G.metadata.columns), axis=1) expected = pd.DataFrame({"name": ["a", "b"], "group": [1, 2]}) expected_sorted = expected.reindex(sorted(expected.columns), axis=1) pd.testing.assert_frame_equal( @@ -482,7 +482,7 @@ def test_from_graphml_builds_metadata_from_node_attributes(tmp_path): def test_to_igraph_types_and_attributes(): A = _csr([0.2, 0.9, 0.3], [0, 1, 2], [1, 2, 0], 3) meta = pd.DataFrame({"name": ["a", "b", "c"], "label": [10, 20, 30]}) - G = Graph.from_csr(A, directed=True, weighted=True, mode="distance", meta=meta) + G = Graph.from_csr(A, directed=True, weighted=True, mode="distance", metadata=meta) igG = G.to_igraph() import igraph as ig @@ -499,7 +499,7 @@ def test_to_igraph_types_and_attributes(): # ----------------- Distance/similarity conversion ----------------- def test_convert_mode_distance_to_similarity_and_back_dense(S_dense, meta_df): G = Graph.from_dense( - S_dense, directed=False, weighted=True, mode="similarity", meta=meta_df + S_dense, directed=False, weighted=True, mode="similarity", metadata=meta_df ) G_dist = G.convert_mode("distance") assert G_dist.mode == "distance" @@ -507,12 +507,12 @@ def test_convert_mode_distance_to_similarity_and_back_dense(S_dense, meta_df): assert G_sim.mode == "similarity" assert np.allclose(G_sim.adj.toarray(), G.adj.toarray()) # Metadata preserved - assert G_sim.meta.equals(G.meta) + assert G_sim.metadata.equals(G.metadata) def test_convert_mode_distance_to_similarity_and_back_csr(S_csr, meta_df): G = Graph.from_csr( - S_csr, directed=False, weighted=True, mode="similarity", meta=meta_df + S_csr, directed=False, weighted=True, mode="similarity", metadata=meta_df ) G_dist = G.convert_mode("distance") assert G_dist.mode == "distance" @@ -520,11 +520,11 @@ def test_convert_mode_distance_to_similarity_and_back_csr(S_csr, meta_df): assert G_sim.mode == "similarity" assert np.allclose(G_sim.adj.toarray(), G.adj.toarray()) # Metadata preserved - assert G_sim.meta.equals(G.meta) + assert G_sim.metadata.equals(G.metadata) # Conversion to dense should lead to different values (in place of 0s) G_dense = Graph.from_dense( - S_csr.toarray(), directed=False, weighted=True, mode="similarity", meta=meta_df + S_csr.toarray(), directed=False, weighted=True, mode="similarity", metadata=meta_df ) G_dist_dense = G_dense.convert_mode("distance") assert G_dense.adj.data.shape == G.adj.data.shape # no change in dense conversion diff --git a/tests/test_importers.py b/tests/test_importers.py index 114b65f..3423d31 100644 --- a/tests/test_importers.py +++ b/tests/test_importers.py @@ -97,5 +97,5 @@ def test_importers_preserve_directed_flag_and_allow_metadata(): [0.0, 0.0, 0.0], ]) meta = None # can replace with a DataFrame; here we just test directed flag - G = from_dense(D, directed=True, weighted=True, mode="similarity", meta=meta) + G = from_dense(D, directed=True, weighted=True, mode="similarity", metadata=meta) assert G.directed and G.weighted diff --git a/tests/test_locally_adaptive_sparsification.py b/tests/test_locally_adaptive_sparsification.py index 01efeee..f66ae74 100644 --- a/tests/test_locally_adaptive_sparsification.py +++ b/tests/test_locally_adaptive_sparsification.py @@ -110,15 +110,15 @@ def test_lans_handles_zero_strength_rows(): assert (G.adj.toarray() >= 0).all() -# ----------------- Metadata preserved (if copy_meta=True) ----------------- +# ----------------- Metadata preserved (if copy_metadata=True) ----------------- def test_lans_preserves_metadata(): meta = pd.DataFrame({"name": ["a", "b", "c"], "grp": [1, 0, 1]}) A = _csr([0.6, 0.4, 0.7], [0, 1, 2], [1, 2, 0], 3) - G0 = Graph.from_csr(A, directed=False, weighted=True, mode="similarity", meta=meta, sym_op="max") + G0 = Graph.from_csr(A, directed=False, weighted=True, mode="similarity", metadata=meta, sym_op="max") - out = LocallyAdaptiveSparsification(alpha=0.25, rule="or", copy_meta=True).apply(G0) + out = LocallyAdaptiveSparsification(alpha=0.25, rule="or", copy_metadata=True).apply(G0) assert not out.directed and out.weighted # metadata should be copied, not referenced - if out.meta is not None: + if out.metadata is not None: meta.loc[0, "grp"] = 999 - assert out.meta.loc[0, "grp"] == 1 + assert out.metadata.loc[0, "grp"] == 1 diff --git a/tests/test_marginal_likelihood_filter.py b/tests/test_marginal_likelihood_filter.py index bf17d68..f9da3f8 100644 --- a/tests/test_marginal_likelihood_filter.py +++ b/tests/test_marginal_likelihood_filter.py @@ -134,14 +134,14 @@ def test_mlf_handles_no_edges_T_zero(): def test_mlf_preserves_flags_and_copies_metadata_when_requested(): meta = pd.DataFrame({"name": ["a", "b", "c"], "group": [1, 0, 1]}) A = _csr([1, 2], [0, 1], [1, 2], 3) - G0 = Graph.from_csr(A, directed=False, weighted=True, mode="similarity", meta=meta) + G0 = Graph.from_csr(A, directed=False, weighted=True, mode="similarity", metadata=meta) - op = MarginalLikelihoodFilter(alpha=0.5, copy_meta=True) + op = MarginalLikelihoodFilter(alpha=0.5, copy_metadata=True) out = op.apply(G0) # Flags preserved assert not out.directed and out.weighted # Metadata copied (modifying original should not affect the result) - if out.meta is not None: + if out.metadata is not None: meta.loc[0, "group"] = 999 - assert out.meta.loc[0, "group"] == 1 + assert out.metadata.loc[0, "group"] == 1 diff --git a/tests/test_minimum_spanning_tree.py b/tests/test_minimum_spanning_tree.py index 63fbce9..449a256 100644 --- a/tests/test_minimum_spanning_tree.py +++ b/tests/test_minimum_spanning_tree.py @@ -255,7 +255,7 @@ def test_mst_raises_on_directed_graph(): # --------------------------------------------------------------------------- def test_mst_preserves_metadata_copy_meta_true(): """ - When copy_meta=True (default), MST result should have a deep copy of meta. + When copy_metadata=True (default), MST result should have a deep copy of meta. """ adj = np.array( [ @@ -265,24 +265,24 @@ def test_mst_preserves_metadata_copy_meta_true(): dtype=float, ) meta = pd.DataFrame({"name": ["a", "b"], "group": [1, 2]}) - G = Graph.from_dense(adj, mode="distance", directed=False, weighted=True, meta=meta) - op = MinimumSpanningTree(copy_meta=True) + G = Graph.from_dense(adj, mode="distance", directed=False, weighted=True, metadata=meta) + op = MinimumSpanningTree(copy_metadata=True) T = op.apply(G) - assert T.meta is not None - assert G.meta is not None + assert T.metadata is not None + assert G.metadata is not None # Different objects, but equal content - assert T.meta is not G.meta - pd.testing.assert_frame_equal(T.meta, G.meta) + assert T.metadata is not G.metadata + pd.testing.assert_frame_equal(T.metadata, G.metadata) ''' # TODO: check why this fails!! def test_mst_reuses_metadata_copy_meta_false(): """ - When copy_meta=False, MST result should reuse the same metadata object. + When copy_metadata=False, MST result should reuse the same metadata object. """ adj = np.array( [ @@ -292,13 +292,13 @@ def test_mst_reuses_metadata_copy_meta_false(): dtype=float, ) meta = pd.DataFrame({"name": ["a", "b"], "group": [1, 2]}) - G = Graph.from_dense(adj, mode="distance", directed=False, weighted=True, meta=meta) - op = MinimumSpanningTree(copy_meta=False) + G = Graph.from_dense(adj, mode="distance", directed=False, weighted=True, metadata=meta) + op = MinimumSpanningTree(copy_metadata=False) T = op.apply(G) # Same object - assert T.meta is G.meta + assert T.metadata is G.meta ''' diff --git a/tests/test_noise_corrected.py b/tests/test_noise_corrected.py index c5b46c2..7ceedab 100644 --- a/tests/test_noise_corrected.py +++ b/tests/test_noise_corrected.py @@ -87,10 +87,10 @@ def test_nc_all_zero_noop(): def test_nc_preserves_flags_and_copies_metadata(): meta = pd.DataFrame({"name": ["a", "b", "c"], "grp": [1, 0, 1]}) A = _csr([0.5, 0.3, 0.7], [0, 1, 2], [1, 2, 0], 3) - G0 = Graph.from_csr(A, directed=False, weighted=True, mode="similarity", meta=meta, sym_op="max") + G0 = Graph.from_csr(A, directed=False, weighted=True, mode="similarity", metadata=meta, sym_op="max") - out = NoiseCorrected(delta=1.64, copy_meta=True).apply(G0) + out = NoiseCorrected(delta=1.64, copy_metadata=True).apply(G0) assert not out.directed and out.weighted - if out.meta is not None: + if out.metadata is not None: meta.loc[0, "grp"] = 999 - assert out.meta.loc[0, "grp"] == 1 + assert out.metadata.loc[0, "grp"] == 1 From 8f77e5cacc1d59c1854cc08661d71ed904a9a676 Mon Sep 17 00:00:00 2001 From: Florian Huber Date: Thu, 28 May 2026 16:55:33 +0200 Subject: [PATCH 3/3] rename meta to metadata --- graphconstructor/graph.py | 16 ++++++++-------- graphconstructor/operators/metric_distance.py | 2 +- tests/test_graph.py | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/graphconstructor/graph.py b/graphconstructor/graph.py index fd6300c..fe55fe1 100644 --- a/graphconstructor/graph.py +++ b/graphconstructor/graph.py @@ -536,9 +536,9 @@ def to_cytoscape( """ if node_id_col is not None: - if self.meta is None or node_id_col not in self.meta.columns: + if self.metadata is None or node_id_col not in self.metadata.columns: raise KeyError(f"Column '{node_id_col}' not found in metadata.") - node_ids = self.meta[node_id_col].astype(str).tolist() + node_ids = self.metadata[node_id_col].astype(str).tolist() else: node_ids = [str(i) for i in range(self.n_nodes)] @@ -554,14 +554,14 @@ def to_cytoscape( if ( node_label_col is not None - and self.meta is not None - and node_label_col in self.meta.columns + and self.metadata is not None + and node_label_col in self.metadata.columns ): - data["label"] = self.meta.iloc[i][node_label_col] + data["label"] = self.metadata.iloc[i][node_label_col] - if self.meta is not None: - for col in self.meta.columns: - value = self.meta.iloc[i][col] + if self.metadata is not None: + for col in self.metadata.columns: + value = self.metadata.iloc[i][col] if pd.isna(value): value = None data[col] = value diff --git a/graphconstructor/operators/metric_distance.py b/graphconstructor/operators/metric_distance.py index 717f462..ff7fa18 100644 --- a/graphconstructor/operators/metric_distance.py +++ b/graphconstructor/operators/metric_distance.py @@ -93,7 +93,7 @@ def _undirected_filter(self, D): directed=False, weighted=True, mode="distance", - meta=None if D.meta is None else D.meta.copy(), + metadata=None if D.metadata is None else D.metadata.copy(), ) # Optional output conversion. diff --git a/tests/test_graph.py b/tests/test_graph.py index 0c948e4..cea3764 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -506,7 +506,7 @@ def test_to_cytoscape_returns_expected_nodes_edges_and_metadata(): directed=False, weighted=True, mode="similarity", - meta=meta, + metadata=meta, ) cy = G.to_cytoscape() @@ -548,7 +548,7 @@ def test_to_cytoscape_writes_json_and_uses_custom_node_ids(tmp_path): directed=True, weighted=True, mode="distance", - meta=meta, + metadata=meta, ) path = tmp_path / "graph.cyjs" @@ -577,7 +577,7 @@ def test_to_cytoscape_writes_json_and_uses_custom_node_ids(tmp_path): def test_to_cytoscape_rejects_duplicate_custom_node_ids(): A = _csr([1.0], [0], [1], 2) meta = pd.DataFrame({"id": ["same", "same"]}) - G = Graph.from_csr(A, directed=False, weighted=True, mode="distance", meta=meta) + G = Graph.from_csr(A, directed=False, weighted=True, mode="distance", metadata=meta) with pytest.raises(ValueError, match="node IDs must be unique"): G.to_cytoscape(node_id_col="id")