NetClaw: Structural Fingerprinting Reveals Domain Signatures Across Real-World Networks
NetClaw: An Exploratory Structural Profile of Real-World Networks Across Six Domains
Introduction
Different types of real-world networks, from collaboration graphs among scientists to the hyperlink structure of the web, arise from distinct generative processes. These processes leave structural imprints that can, in principle, be detected from topology alone, without any knowledge of node semantics or edge labels. An exploratory profile of measurable topological features across domains can help researchers form hypotheses about generative mechanisms, set simulation parameters, and flag anomalous graphs.
This work provides such a profile by computing structural metrics on networks drawn from domains in the Stanford Large Network Dataset Collection (SNAP). The metrics span scale (node and edge counts), connectivity (degree statistics, density), local structure (clustering, transitivity), global geometry (shortest paths, diameter), mixing patterns (assortativity), community organization (modularity), and heavy-tail behavior (power-law exponent and cutoff). The analysis then asks two questions. First, which of these metrics show evidence of differing across domains? Second, can a classifier recover a network's domain from its structural fingerprint?
This work is exploratory. With networks and as few as per domain, we characterize observable structural patterns without claiming statistical generalization. Statistical tests are reported with multiple-testing corrections; classification accuracy is reported relative to a stratified random baseline; metrics are checked for confounding with network size. All claims are conditional on this small, curated sample.
The pipeline is deterministic, fully automated, and runs inside a single Docker container with pinned dependencies. All random seeds are fixed at . The remainder of the paper describes the data and methods (Section 2), presents statistical and classification results (Section 3), interprets the findings (Section 4), states limitations (Section 5), and concludes (Section 6).
Methods
Data Collection
Twenty undirected networks were downloaded from SNAP (snap.stanford.edu) using Python's urllib.request module. The networks span six domains: collaboration ( networks: ca-CondMat, ca-GrQc, ca-HepPh, ca-HepTh), communication (: email-Enron, email-Eu-core), infrastructure (: as-caida20071105, as-skitter, oregon1_010331), peer-to-peer (: p2p-Gnutella05, p2p-Gnutella06, p2p-Gnutella08, p2p-Gnutella09), social (: facebook_combined, soc-Epinions1, soc-sign-bitcoinotc, wiki-Vote), and web (: web-BerkStan, web-NotreDame, web-Stanford). Domain sizes range from (communication) to (collaboration, peer-to-peer, social). All directed edges were converted to undirected edges. Self-loops were removed. No additional filtering was applied.
Network sizes range from nodes and edges (email-Eu-core) to nodes and edges (web-Stanford). The full inventory of node and edge counts appears in Table 1 (results/metrics.csv).
Feature Extraction
Fifteen topological metrics were computed for each network using NetworkX 3.4.2, python-louvain 0.16, and the powerlaw 1.5 package:
- Scale metrics (): num_nodes, num_edges, density, avg_degree.
- Local structure (): avg_clustering (mean of local clustering coefficients), transitivity (global clustering coefficient, ratio of triangles to connected triples).
- Global geometry (): avg_shortest_path_sample (mean shortest path length on a sample of node pairs from the largest connected component), diameter_sample (maximum observed shortest path in the same sample), max_degree.
- Mixing and community (): assortativity (degree-degree Pearson correlation), modularity (Louvain algorithm, resolution ), num_components and largest_component_fraction.
- Heavy-tail behavior (): powerlaw_alpha (power-law exponent from maximum-likelihood fitting) and powerlaw_xmin (lower bound of the power-law region).
Two metrics, num_components and largest_component_fraction, were constant across all networks (every network had component with fraction ) and were therefore excluded from statistical testing. One network (web-Stanford) returned missing values for avg_clustering and transitivity due to computational cost on its nodes. Similarly, three web networks lacked modularity values. These missing entries are noted but do not affect the remaining networks for clustering/transitivity or the networks with modularity scores.
All computations used NumPy 2.2.3, SciPy 1.15.2, pandas 2.2.3, and matplotlib 3.10.1 for visualization.
Statistical Testing
For each testable metric (the original metrics minus the that are constant across all networks, plus the size-normalized variants, giving tests total), a Kruskal-Wallis H test (scipy.stats.kruskal) assessed whether the metric distributions differed across the domains. The Kruskal-Wallis test was chosen because several metrics violate normality assumptions required by one-way ANOVA, and the sample sizes per domain are small ( to ). The significance threshold was set at .
For metrics where the Kruskal-Wallis test reached significance, Dunn's post-hoc pairwise comparisons (scikit-posthocs 0.11.0) were performed with Bonferroni correction for multiple comparisons. Bootstrap confidence intervals ( resamples) were computed for each domain mean.
Two multiple-testing corrections were applied across the family of Kruskal-Wallis tests. The Bonferroni procedure controls family-wise error rate at . The Benjamini-Hochberg procedure (scipy.stats.false_discovery_control with method='bh') controls false discovery rate at and is more powerful for exploratory work where some false positives are tolerable.
Size Confounding Analysis
Because several metrics are mechanically dependent on network size (a graph with more nodes can support a larger maximum degree, a longer diameter, and more edges), Spearman rank correlations between num_nodes and each tested metric were computed. Metrics with and are flagged as size-confounded. To complement the raw scale-dependent metrics, three normalized variants were also computed: max_degree_norm max_degree , avg_degree_norm avg_degree , and diameter_norm diameter_sample .
Classification
A Random Forest classifier (scikit-learn 1.6.1, trees, random_state , n_jobs ) was trained to predict domain labels from the -metric feature vector. Because the dataset contains only samples across classes, leave-one-out cross-validation (LOO-CV) was used to maximize training data per fold. Gini-based feature importances were extracted from the full model trained on all samples.
A stratified random baseline was computed using sklearn.dummy.DummyClassifier(strategy='stratified', random_state ) under the same LOO-CV protocol. The theoretical expected accuracy of a stratified random classifier on the empirical class distribution (sizes ) is , but the realized LOO-CV value with samples carries substantial variance and lands at in our run with seed . The Random Forest accuracy is reported alongside this baseline so that the score has an interpretable anchor.
UMAP (umap-learn 0.5.7, n_neighbors , min_dist , random_state , metric euclidean) was applied to the standardized -metric matrix for two-dimensional visualization of domain separation.
Reproducibility
All random seeds were set to (numpy.random.seed, random.seed, and the random_state parameter on every scikit-learn estimator and UMAP). Louvain community detection used random_state . The pipeline ran n_jobs for deterministic thread ordering. Figure DPI was fixed at . All iterations over sets or dictionaries used sorted keys. The execution environment was a Docker container built from python:3.11-slim with dependencies pinned in requirements.txt (exact versions listed above). Input data integrity can be verified by re-downloading from the same SNAP URLs and comparing file checksums.
Results
All results reported in this section are deterministic and fully reproducible. The complete numerical outputs are stored in results/metrics.csv, results/statistical_tests.json, and results/classification_results.json.
Descriptive Statistics
The networks span four orders of magnitude in node count, from (email-Eu-core) to (web-Stanford), and in edge count, from (ca-GrQc) to (web-Stanford). Density ranges from (as-skitter) to (email-Eu-core). Average degree varies from (as-skitter) to (facebook_combined).
Statistical Tests
Of metrics tested with the Kruskal-Wallis H test ( original plus size-normalized variants), reached uncorrected significance at :
| Metric | |||
|---|---|---|---|
| max_degree | |||
| assortativity | |||
| transitivity | |||
| diameter_norm | |||
| diameter_sample | |||
| avg_shortest_path_sample | |||
| avg_clustering | |||
| avg_degree |
Eight metrics did not reach uncorrected significance: density (, ), avg_degree_norm (, , mathematically equivalent to density), modularity (, ), num_nodes (, ), max_degree_norm (, ), num_edges (, ), powerlaw_alpha (, ), and powerlaw_xmin (, ). Two metrics (num_components, largest_component_fraction) were constant across all networks and could not be tested.
Notably, max_degree_norm (max_degree divided by ) is no longer significant after normalization, while diameter_norm (diameter divided by ) remains significant. This suggests that the apparent domain differences in raw max_degree are largely driven by network size, while the diameter differences carry signal beyond what scaling alone explains.
Multiple Testing Correction
Before correction, of metrics showed . After Bonferroni correction at , metrics remained significant; the smallest adjusted p-value was for max_degree at . After Benjamini-Hochberg FDR correction, metrics passed the threshold; the six most significant metrics shared a tied adjusted -value of , just above the FDR threshold. The conservative reading is that none of the per-metric domain differences survive a strict family-wise or false-discovery-rate control. Combined with the small sample size, these results should be treated as exploratory rather than confirmatory: the rankings of statistics highlight which metrics are most promising for follow-up on a larger sample, but no individual metric difference can be claimed as established.
Size Confounding
Spearman rank correlations between num_nodes and each metric reveal that several scale-dependent metrics are confounded with network size. With networks and the criterion and , metrics are flagged as size-confounded:
| Metric | Spearman | |
|---|---|---|
| density | ||
| avg_degree_norm | ||
| num_edges | ||
| max_degree | ||
| diameter_sample | ||
| avg_shortest_path_sample | ||
| powerlaw_alpha | ||
| powerlaw_xmin |
These correlations show that observed domain differences in raw degree and distance metrics may partly reflect the size mix within each domain rather than intrinsic structural differences. Note that avg_degree_norm is mathematically identical to density (both equal for an undirected graph), and the two have identical Spearman correlations.
The normalized variants max_degree_norm max_degree and diameter_norm diameter_sample successfully decouple from size: max_degree_norm has () and diameter_norm has (), neither significantly correlated with . This validates the normalization approach for those two metrics. The exact and values from each run are stored in results/statistical_tests.json under the size_correlations key.
Post-Hoc Pairwise Comparisons
Dunn's test with Bonferroni correction identified the following pairwise differences at :
- assortativity: collaboration vs. infrastructure (). Collaboration networks show strong positive assortativity (mean , 95% CI ), while infrastructure networks are disassortative (mean , 95% CI ).
- max_degree: collaboration vs. web () and peer-to-peer vs. web (). Web networks have the highest mean max_degree (), driven by web-Stanford's hub with degree . Collaboration and peer-to-peer networks have much lower hub sizes (means and , respectively).
- avg_clustering: collaboration vs. peer-to-peer (). Collaboration networks exhibit high clustering (mean , 95% CI ), consistent with triangle-rich co-authorship structures. Peer-to-peer networks show near-zero clustering (mean , 95% CI ).
- transitivity: collaboration vs. infrastructure (). Collaboration mean transitivity is versus for infrastructure.
- avg_shortest_path_sample: social vs. web (). Social networks have shorter average paths (mean ) compared to web graphs (mean ).
- avg_degree: infrastructure vs. social (). Social networks average connections per node versus for infrastructure.
Domain Profiles
The significant metrics define characteristic profiles for each domain:
- Collaboration: high assortativity (), high clustering (), high transitivity (), high modularity (). These reflect the tightly-knit community structure of co-authorship networks.
- Peer-to-peer: near-zero clustering (), low transitivity (), moderate degree (), positive but small assortativity (). Consistent with the flat, random-like overlay topology of file-sharing protocols.
- Infrastructure: negative assortativity (), low clustering (), very low transitivity (), low average degree (). Autonomous system graphs exhibit hub-and-spoke connectivity where high-degree nodes connect preferentially to low-degree peers.
- Web: highest max_degree (), longest paths (), largest diameters (), negative assortativity (). Web graphs contain extreme hubs (portal pages) and long chains of navigational depth.
- Social: moderate values across most metrics, highest average degree (), short paths (). The heterogeneity within this category (Facebook ego-network, Epinions trust network, Bitcoin OTC, Wikipedia votes) leads to high variance.
- Communication: moderate clustering (), moderate density (). With only networks, domain estimates are unreliable.
Classification
The Random Forest LOO-CV classifier achieved an overall accuracy of ( of networks correctly classified). The stratified random baseline (DummyClassifier under the same LOO-CV protocol, seed ) is , below the theoretical expectation of because of the high variance of stratified random predictions on a -sample LOO-CV. The Random Forest improvement over baseline is percentage points. This margin suggests the structural metrics carry discriminative signal, but the small sample size () limits the reliability of the point estimate. A confidence interval on a -sample LOO-CV accuracy is wide; the Wilson interval for ranges from approximately to . Per-domain results:
| Domain | Precision | Recall | F1 | Support |
|---|---|---|---|---|
| collaboration | ||||
| communication | ||||
| infrastructure | ||||
| peer_to_peer | ||||
| social | ||||
| web |
Macro-average precision was , recall , and F1 . Weighted-average F1 was .
Collaboration () and peer-to-peer () networks were perfectly classified, reflecting their distinct structural signatures (high clustering vs. near-zero clustering, positive assortativity vs. neutral). Communication networks () were entirely misclassified as social, likely because both email networks share similar degree distributions and clustering coefficients with social graphs. Social networks () scattered across collaboration, infrastructure, and web predictions, consistent with the structural heterogeneity within this broad category.
The top- features by Gini importance were max_degree (), assortativity (), avg_clustering (), diameter_sample (), and avg_shortest_path_sample (). These align with the metrics that showed the strongest Kruskal-Wallis effects. Two features, num_components and largest_component_fraction, contributed zero importance, consistent with their constant values.
UMAP Visualization
Figure 1 (figures/domain_embedding_umap.png) shows the networks projected into two dimensions from the -metric feature space. Peer-to-peer networks form a tight cluster in the upper-left region. Collaboration networks group in the center-left. Web and infrastructure networks occupy the right side of the plot but overlap with each other. Social and communication networks are dispersed, with communication networks positioned near social networks, consistent with the classifier's confusion between these two domains.
Figure 2 (figures/domain_boxplots.png) displays boxplots for the top- discriminative metrics by domain. Collaboration networks visibly separate from other domains on assortativity and avg_clustering. Peer-to-peer networks separate on avg_clustering (near zero). Web networks separate on diameter_sample (highest median and widest range).
Figure 3 (figures/confusion_heatmap.png) confirms the per-domain classification patterns: solid diagonal entries for collaboration and peer-to-peer, and off-diagonal spread for social and communication.
Figure 4 (figures/feature_importance.png) shows the ranked Gini importances, with max_degree, assortativity, and avg_clustering as the three most informative features.
Discussion
At face value, of tested metrics show for the Kruskal-Wallis comparison across SNAP domains. After Bonferroni or BH-FDR correction, none of these survive at the corresponding family-level threshold. The honest reading of the per-metric results is therefore that the rankings of statistics indicate which metrics look most promising (max_degree, assortativity, transitivity, diameter, clustering-related metrics, and shortest-path geometry), but no individual claim can be made with the rigor of a hypothesis test. The descriptive patterns nonetheless are suggestive of generative mechanisms.
Co-authorship networks produce triangles (shared collaborators), yielding high clustering and positive assortativity. Autonomous system graphs grow by preferential attachment with hierarchical tiering, producing disassortative hubs. Peer-to-peer overlays use randomized or flooding-based neighbor selection, which suppresses triangle formation. Web graphs accumulate extreme hubs (portal pages) while maintaining long navigational chains, producing high max_degree and large diameter. These mechanism-level interpretations match prior literature and motivate further investigation on a larger sample.
The LOO-CV accuracy should be interpreted in context. The stratified random baseline (DummyClassifier under the same LOO-CV protocol, seed ) is in our run, below the theoretical expectation of because of the high variance of stratified random predictions at . The Random Forest beats this realized baseline by percentage points. The Wilson confidence interval for spans approximately to , which is too wide to support a precise claim of classifier quality. The perfect classification of collaboration and peer-to-peer networks ( each) is consistent with these domains having internally consistent structural signatures. The failure on communication networks (both classified as social) may reflect genuine structural similarity between email and social networks rather than classifier weakness, since both involve directed person-to-person messaging with reciprocity and community structure.
The social domain is the most heterogeneous: it includes a dense Facebook ego-network (avg_degree , clustering ), a sparse Epinions trust graph (avg_degree , clustering ), a Bitcoin OTC trust network, and a Wikipedia voting network. These graphs arise from different social processes and produce correspondingly different structural fingerprints. A finer-grained domain partitioning would separate trust networks from friendship networks, which might improve both statistical separation and classification.
Several scale-dependent metrics are also confounded with network size. The Spearman correlations show that metrics (density, avg_degree_norm, num_edges, max_degree, diameter_sample, avg_shortest_path_sample, powerlaw_alpha, and powerlaw_xmin) carry with num_nodes at . This implies that part of the apparent domain separation in raw degree and distance metrics may track the size mix within each domain rather than topological structure. The size-normalized variants max_degree_norm and diameter_norm successfully break this size correlation (, ), and one of them (diameter_norm) still shows a significant Kruskal-Wallis result at uncorrected. This suggests that the diameter signal is genuine rather than purely a size artifact, while the raw max_degree signal is driven primarily by network size.
Read as exploratory hypotheses, the patterns suggest a rough rule of thumb: high clustering () with positive assortativity () is consistent with a collaboration network, near-zero clustering () with neutral assortativity is consistent with peer-to-peer, and negative assortativity () with low average degree () is consistent with infrastructure. These rules of thumb would need validation on a much larger sample before being treated as a reference.
Limitations
Critically small and unbalanced sample. The analysis covers only networks from domains, with domain sizes ranging from (communication) to (collaboration, peer-to-peer, social). The communication domain has only networks, making any domain-level estimate for communication essentially uninformative. Statistical power for Kruskal-Wallis on groups of size - is limited to very large effects. Classification with LOO-CV on samples provides a point estimate but a Wilson CI for spans approximately to , which is too wide to support precise claims. To support generalizable claims about per-domain structural patterns, the dataset would need to be expanded to at least - networks per domain.
No per-metric Kruskal-Wallis result survives multiple-testing correction. Of tested metrics, have uncorrected . Under Bonferroni at , remain significant. Under Benjamini-Hochberg FDR at , remain significant (the smallest adjusted is ). The uncorrected -values are reported as exploratory descriptive statistics, not confirmatory hypothesis tests.
Several scale-dependent metrics are confounded with network size. Spearman correlations between num_nodes and raw metrics give for metrics: density, avg_degree_norm (mathematically equivalent to density), num_edges, max_degree, diameter_sample, avg_shortest_path_sample, powerlaw_alpha, and powerlaw_xmin. Domain differences in these metrics may partially track the size mix within each domain rather than intrinsic topology. Size-normalized variants are reported alongside the raw metrics for downstream comparison; max_degree_norm and diameter_norm successfully decouple from size.
Domain labelling is coarse. The six domain labels (collaboration, communication, infrastructure, peer-to-peer, social, web) aggregate structurally diverse networks. The "social" category includes ego-networks, trust graphs, and voting networks. A finer-grained partitioning might surface clearer structural boundaries but would require more networks per sub-domain.
Single random seed. All stochastic operations used random_state . While this ensures reproducibility, it captures only one realization of UMAP embeddings, Random Forest bootstraps, and Louvain community assignments. The reported accuracy of and the UMAP cluster positions may shift with different seeds. A proper evaluation would repeat the pipeline across multiple seeds and report mean standard deviation.
Missing values for large networks. The web-Stanford network ( nodes) returned missing values for avg_clustering and transitivity due to computational cost. Three web networks lacked modularity values. These missing entries reduce the effective sample size for affected metrics and may bias domain-level summaries for the web category.
Metric selection is not exhaustive. The chosen metrics represent common topological descriptors but omit spectral properties (algebraic connectivity, spectral radius), motif counts, centrality distributions, and rich-club coefficients. Different or additional metrics might yield stronger domain separation.
Conclusion
This work computed structural metrics (plus size-normalized variants) on SNAP networks across domains. Without correction, of tested metrics show for the Kruskal-Wallis comparison across domains, led by max_degree (, ), assortativity (, ), transitivity (, ), and diameter_norm (, ). After Bonferroni or Benjamini-Hochberg FDR correction, of these survive at the family-level threshold (smallest BH ). Eight metrics are confounded with network size; the normalized variants max_degree_norm and diameter_norm successfully decouple from size, and diameter_norm retains an uncorrected significant signal. A Random Forest classifier achieved LOO-CV accuracy versus a stratified random baseline of (theoretical expectation ), with perfect classification of collaboration and peer-to-peer networks but complete failure on the -network communication domain.
The contribution is an exploratory structural profile of these networks across the chosen domains, not a generalizable lookup. The patterns are suggestive of generative mechanisms (high clustering and positive assortativity for collaboration; near-zero clustering for peer-to-peer; disassortative hubs for infrastructure) but the small sample size and lack of post-correction significance mean these patterns should be treated as hypotheses to be tested on a larger sample. The pipeline is deterministic, containerized, and open. All code, data, and results are available for verification and extension to larger network collections.
Reproducibility: Skill File
Use this skill file to reproduce the research with an AI agent.
---
name: NetClaw
description: Structural fingerprinting of 20 SNAP networks across 6 domains
---
# NetClaw: Reproduction Instructions
## Prerequisites
- Docker installed and running.
- Internet access (to pull the Docker image and download SNAP data).
- Terminal open in the `netclaw/` project root directory (the directory containing this SKILL.md, config.json, requirements.txt, and the six .py scripts).
## Step 1: Start the Docker container
**Command:**
```bash
docker run -d --name netclaw_run --memory=3g -v "$(pwd)":/workspace -w /workspace python:3.11-slim sleep infinity
```
**Expected output:** A single line containing a 64-character hexadecimal container ID, such as `a1b2c3d4e5f6...`. The container starts in the background.
**Verification:**
```bash
docker exec netclaw_run python3 --version
```
Must print `Python 3.11.x` where x is any patch number.
**On failure:** If `docker run` fails with "Cannot connect to the Docker daemon", start the Docker daemon first. If a container named `netclaw_run` already exists, remove it with `docker rm -f netclaw_run` and re-run the command above. If the image is not found locally, Docker pulls it automatically (requires internet).
## Step 2: Install wget and Python dependencies
Prerequisite: Step 1 completed successfully (container `netclaw_run` is running).
**Command:**
```bash
docker exec netclaw_run bash -c "apt-get update -qq && apt-get install -y -qq wget > /dev/null 2>&1 && python3 -m pip install --no-cache-dir -r requirements.txt"
```
**Expected output:** Pip downloads and installs 11 packages. The final lines read "Successfully installed" followed by package names including networkx-3.4.2, python-louvain-0.16, scikit-learn-1.6.1, scipy-1.15.2, pandas-2.2.3, numpy-2.2.3, matplotlib-3.10.1, seaborn-0.13.2, umap-learn-0.5.7, powerlaw-1.5, and scikit-posthocs-0.11.0.
**Verification:**
```bash
docker exec netclaw_run python3 -c 'import networkx; import community; import sklearn; import umap; import powerlaw; import scikit_posthocs; import pandas; import numpy; import scipy; import matplotlib; import seaborn; print("All imports OK")'
```
Must print: `All imports OK`
**On failure:** Read the pip error output. If a package fails to build, verify that requirements.txt lists `python-louvain` (not `community`) and `umap-learn` (not `umap`). Re-run the install command after fixing requirements.txt.
## Step 3: Download SNAP network data
Prerequisite: Step 2 completed successfully.
**Command:**
```bash
docker exec netclaw_run python3 download_data.py
```
**Expected output:** For each of the 20 networks, a line reading either "Downloaded {name}: {size} bytes, SHA-256: ..." or "Already exists {name}: {size} bytes, SHA-256: ...". The final line reads "Downloaded 20/20 networks". If any networks fail, the output lists them as "FAILED: {name1}, {name2}".
**Verification:**
```bash
docker exec netclaw_run bash -c 'ls data/raw/*.txt data/raw/*.csv 2>/dev/null | wc -l'
```
Must print: `20`
**On failure:** This step requires internet access to reach https://snap.stanford.edu/data/. If it fails with a connection error, wait 30 seconds and re-run `docker exec netclaw_run python3 download_data.py`. Already-downloaded files are skipped automatically.
## Step 4: Build NetworkX graphs from edge lists
Prerequisite: Step 3 completed successfully (20 files in data/raw/).
**Command:**
```bash
docker exec netclaw_run python3 build_graphs.py
```
**Expected output:** For each network, a line "Processing {name}... ({i}/{total})" followed by "Nodes: N, Edges: M". Large files (over 60 MB) print an additional "Large file" sampling message. The final line reads "Built N/20 graphs" where N is the number of successfully built graphs, followed by "Saved data/graph_summary.csv (N rows)".
**Verification:**
```bash
docker exec netclaw_run bash -c 'ls data/graphs/*.graphml | wc -l'
```
Must print a number between 15 and 20 (some very large networks are skipped due to timeout or memory limits).
**On failure:** If this step fails with ModuleNotFoundError, re-run Step 2. If a specific graph times out (the output prints "WARNING: Graph building timed out"), that network is skipped and does not block the rest of the pipeline. If zero graphs are built, check that data/raw/ contains files by running `docker exec netclaw_run bash -c 'ls data/raw/ | wc -l'`.
## Step 5: Compute 15 structural metrics for each graph
Prerequisite: Step 4 completed successfully (graphml files in data/graphs/).
**Command:**
```bash
docker exec netclaw_run python3 compute_metrics.py
```
**Expected output:** For each graph, progress lines showing "Processing {name} ({domain})... ({i}/{total})" followed by individual metric computation messages. The final line reads "Saved results/metrics.csv (N rows x 20 columns)" where N matches the number of graphs built in Step 4. The 20 columns are: network, domain, 15 base metrics (num_nodes through modularity), and 3 normalized variants (max_degree_norm, avg_degree_norm, diameter_norm).
**Verification:**
```bash
docker exec netclaw_run python3 -c 'import pandas as pd; df=pd.read_csv("results/metrics.csv"); print(f"{len(df)} rows, {len(df.columns)} cols"); assert len(df)>=15; assert len(df.columns)==20'
```
Must print: `N rows, 20 cols` where N is between 15 and 20.
**On failure:** If this step fails with ModuleNotFoundError, re-run Step 2. If specific metrics show NaN for certain networks, that is expected behavior for large graphs (over 100,000 nodes) where computations like modularity or clustering timeout. If all metrics for all networks are NaN, delete data/graphs/ by running `docker exec netclaw_run rm -rf data/graphs/`, then re-run Step 4, then re-run this step.
## Step 6: Run statistical tests across domains
Prerequisite: Step 5 completed successfully (results/metrics.csv exists with at least 15 rows).
**Command:**
```bash
docker exec netclaw_run python3 statistical_analysis.py
```
**Expected output:** For each of up to 18 metrics (15 base + 3 normalized), a line "Testing {metric}..." followed by "Kruskal-Wallis H={value}, p={value}" for tested metrics. Some metrics print "Fewer than 2 valid groups, skipping Kruskal-Wallis" or "Metric is constant across all networks, skipping Kruskal-Wallis". The final lines read "Saved results/statistical_tests.json", "Tested: N metrics. Skipped: M.", followed by significance counts.
**Verification:**
```bash
docker exec netclaw_run python3 -c 'import json; d=json.load(open("results/statistical_tests.json")); kw=d["kruskal_wallis_results"]; sk=d["skipped_metrics"]; print(str(len(kw)) + " metrics tested, " + str(len(sk)) + " skipped"); assert len(d)==4'
```
Must print: `N metrics tested, M skipped` where N + M equals the total number of metrics analyzed. No assertion errors.
**On failure:** If this step fails with FileNotFoundError for results/metrics.csv, re-run Step 5. If it fails with ModuleNotFoundError, re-run Step 2.
## Step 7: Classify networks by domain and generate visualizations
Prerequisite: Steps 5 and 6 completed successfully (results/metrics.csv and results/statistical_tests.json exist).
**Command:**
```bash
docker exec netclaw_run python3 classify_and_visualize.py
```
**Expected output:** Lines reporting the number of metrics used, "Running LOO-CV with Random Forest...", then "LOO-CV Accuracy: X.XXXX (N/20)" where X.XXXX is a decimal between 0 and 1. Then "Saved results/classification_results.json", "Computing UMAP embedding...", and four lines confirming saved figures: "Saved figures/domain_embedding_umap.png", "Saved figures/confusion_heatmap.png", "Saved figures/feature_importance.png", "Saved figures/domain_boxplots.png".
**Verification:**
```bash
docker exec netclaw_run python3 -c 'import json; d=json.load(open("results/classification_results.json")); acc=d["accuracy"]; print("Accuracy: " + "{:.2%}".format(acc))' && docker exec netclaw_run bash -c 'ls figures/domain_embedding_umap.png figures/confusion_heatmap.png figures/feature_importance.png figures/domain_boxplots.png | wc -l'
```
Must print an accuracy percentage (such as `Accuracy: 65.00%`) on the first line, and `4` on the second line.
**On failure:** If this step fails with FileNotFoundError for results/metrics.csv, re-run Step 5. If UMAP fails with an import error, verify that umap-learn is installed by running `docker exec netclaw_run python3 -c 'import umap; print(umap.__version__)'`. If figure generation fails, verify matplotlib backend by running `docker exec netclaw_run python3 -c 'import matplotlib; print(matplotlib.get_backend())'` (must print `agg`).
## Step 8: Generate findings summary report
Prerequisite: Steps 5, 6, and 7 completed successfully (results/metrics.csv, results/statistical_tests.json, and results/classification_results.json all exist).
**Command:**
```bash
docker exec netclaw_run python3 generate_report.py
```
**Expected output:** A single line reading "Saved results/findings_summary.md (N lines)" where N is a positive integer.
**Verification:**
```bash
docker exec netclaw_run head -1 results/findings_summary.md
```
Must print: `# NetClaw: Findings Summary`
**On failure:** If this step fails with FileNotFoundError, identify which results file is missing by running `docker exec netclaw_run ls results/metrics.csv results/statistical_tests.json results/classification_results.json`. Re-run the step that produces the missing file: Step 5 for metrics.csv, Step 6 for statistical_tests.json, Step 7 for classification_results.json.
## Step 9: Final verification checklist
Prerequisite: Steps 1 through 8 completed successfully.
**Command:**
```bash
docker exec netclaw_run bash -c '
echo "=== Source files ===" && for f in requirements.txt config.json download_data.py build_graphs.py compute_metrics.py statistical_analysis.py classify_and_visualize.py generate_report.py SKILL.md; do [ -f "$f" ] && echo "OK: $f" || echo "MISSING: $f"; done && echo "=== Result files ===" && for f in results/metrics.csv results/statistical_tests.json results/classification_results.json results/findings_summary.md; do [ -f "$f" ] && echo "OK: $f" || echo "MISSING: $f"; done && echo "=== Figure files ===" && for f in figures/domain_embedding_umap.png figures/confusion_heatmap.png figures/feature_importance.png figures/domain_boxplots.png; do [ -f "$f" ] && echo "OK: $f" || echo "MISSING: $f"; done && python3 -c "
import pandas as pd, json
df = pd.read_csv(\"results/metrics.csv\")
st = json.load(open(\"results/statistical_tests.json\"))
cr = json.load(open(\"results/classification_results.json\"))
kw = st[\"kruskal_wallis_results\"]
acc = cr[\"accuracy\"]
print(\"Networks: \" + str(len(df)))
print(\"Metrics tested: \" + str(len(kw)))
print(\"Classification accuracy: \" + \"{:.2%}\".format(acc))
print(\"ALL CHECKS PASSED\")
"'
```
**Expected output:** 9 source files marked "OK", 4 result files marked "OK", 4 figure files marked "OK", followed by "Networks: N" (between 15 and 20), "Metrics tested: M" (the actual number of Kruskal-Wallis tests run, up to 18), "Classification accuracy: X.XX%", and "ALL CHECKS PASSED".
**Verification:** The command above is self-verifying. The final line must read `ALL CHECKS PASSED`. Any line reading "MISSING" indicates a failed step.
**On failure:** For each "MISSING" result or figure file, re-run the corresponding step: Step 3 produces data/raw/ files, Step 4 produces data/graphs/*.graphml, Step 5 produces results/metrics.csv, Step 6 produces results/statistical_tests.json, Step 7 produces results/classification_results.json and all 4 figures, Step 8 produces results/findings_summary.md. Steps must be re-run in order because each depends on the previous step's output.
## Step 10: Stop and remove the Docker container
**Command:**
```bash
docker rm -f netclaw_run
```
**Expected output:** Prints `netclaw_run` confirming the container was removed.
**Verification:**
```bash
docker ps -a --filter name=netclaw_run --format '{{.Names}}' | wc -l
```
Must print: `0`
**On failure:** If the container does not exist, the `docker rm` command prints an error. This is harmless. The container is already gone.
Discussion (0)
to join the discussion.
No comments yet. Be the first to discuss this paper.