Skip to content

Commit b8086b8

Browse files
committed
update readme
1 parent decc59f commit b8086b8

File tree

2 files changed

+137
-60
lines changed

2 files changed

+137
-60
lines changed

README.MD

Lines changed: 31 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Q-analysis Package
22

3-
This package provides tools for performing Q-analysis on complex networks, implementing key Q-analysis metrics, visualization tools, and statistical utilities with scikit-learn compatible interfaces.
3+
This package provides tools for performing Q-analysis on complex networks. It implements methods for constructing simplicial complexes, computing Q-analysis metrics, and includes statistical and visualization utilities. The core computations are accelerated with Rust, and the package provides scikit-learn compatible interfaces.
44

55
## Installation
66

@@ -18,84 +18,49 @@ q_analysis/
1818
├── simplicial_complex.py
1919
├── stat.py
2020
├── transformers.py
21-
├── utils.py
21+
├── datasets.py
2222
├── viz.py
23-
├── connected_components.py
2423
└── examples/
2524
└── scale_free_configurational.py
25+
scripts/
26+
├──usage_example.py
2627
README.md
2728
pyproject.toml
28-
requirements.txt
2929
```
3030

3131
## Usage
3232

33-
Here's a basic example of how to use the package:
33+
This example demonstrates how to compare two ensembles of networks (Scale-Free vs. Configurational), compute their structure vectors, and visualize the results.
3434

3535
```python
3636
import numpy as np
37-
from q_analysis.simplicial_complex import IncidenceSimplicialComplex
38-
from q_analysis.transformers import QReducer
39-
from q_analysis.utils import get_incidence
40-
41-
# Create an adjacency matrix
42-
adj_matrix = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]])
43-
44-
# Create an IncidenceSimplicialComplex
45-
incidence = get_incidence(adj_matrix)
46-
complex = IncidenceSimplicialComplex(incidence)
47-
48-
# Calculate the Q-analysis vectors
49-
q_vectors = complex.q_analysis_vectors(as_dataframe=True)
50-
print("Q-analysis vectors:\n", q_vectors)
51-
52-
# Calculate topological entropy
53-
entropy = complex.topological_entropy(q=1)
54-
print("Topological Entropy (q=1):", entropy)
55-
56-
# Use the QReducer transformer
57-
reducer = QReducer(q=1)
58-
reduced_adj = reducer.fit_transform([adj_matrix])[0]
59-
print("Reduced Adjacency Matrix:\n", reduced_adj)
60-
```
61-
62-
### Advanced Example: Network Comparison
63-
64-
Here's a more advanced example comparing scale-free and configurational networks:
37+
import pandas as pd
38+
import matplotlib.pyplot as plt
39+
from itertools import product
6540

66-
```python
6741
from q_analysis.examples.scale_free_configurational import generate_networks
68-
from q_analysis.simplicial_complex import IncidenceSimplicialComplex
42+
from q_analysis.simplicial_complex import SimplicialComplex
6943
from q_analysis.viz import plot_q_analysis_vectors
70-
from q_analysis.stat import consensus_statistic
71-
from q_analysis.utils import calculate_consensus_adjacency_matrix
72-
import numpy as np
73-
import pandas as pd
74-
import matplotlib.pyplot as plt
75-
from scipy import stats
7644

77-
# Generate sample networks
45+
# 1. Generate sample networks
7846
N_SAMPLES, N_NODES, M_PARAMETER = 100, 100, 8
7947
scale_free_networks, configurational_networks = generate_networks(
8048
N_NODES, M_PARAMETER, N_SAMPLES
8149
)
82-
83-
# Create simplicial complexes and extract Q-analysis vectors
8450
networks = np.concatenate([scale_free_networks, configurational_networks])
85-
from itertools import product
86-
index = product(['Scale free', 'Configurational'], range(N_SAMPLES))
8751

88-
# Create simplicial complexes and get structure vectors
89-
structure_vectors_dfs = [
90-
IncidenceSimplicialComplex
91-
.from_adjacency_matrix(network)
92-
.q_analysis_vectors(as_dataframe=True)
93-
.assign(Network=net_type, Sample=sample_id)
52+
# 2. Compute graded parameters for each network
53+
index = product(['Scale free', 'Configurational'], range(N_SAMPLES))
54+
simplicial_complex_metrics = [
55+
SimplicialComplex.from_adjacency_matrix(network)
56+
.graded_parameters()
57+
.to_dataframe()
58+
.assign(Network=net_type, Sample=sample_id)
9459
for network, (net_type, sample_id) in zip(networks, index)
9560
]
61+
structure_vectors_df = pd.concat(simplicial_complex_metrics, ignore_index=True)
9662

97-
# Combine results and visualize
98-
structure_vectors_df = pd.concat(structure_vectors_dfs, ignore_index=True)
63+
# 3. Visualize the aggregated results
9964
plot_q_analysis_vectors(
10065
structure_vectors_df,
10166
hue="Network",
@@ -106,14 +71,20 @@ plot_q_analysis_vectors(
10671
plt.show()
10772
```
10873

74+
You can find other code snippets in scripts/
75+
10976
## Features
11077

111-
- **Simplicial Complex Analysis**: Create and analyze simplicial complexes from adjacency matrices
112-
- **Q-Analysis Vectors**: Compute first and second structure vectors
113-
- **Statistical Tools**: Perform statistical tests on network comparisons
114-
- **Visualization**: Plot Q-analysis vectors and other topological properties
115-
- **Connected Components**: Analyze connected components in networks
116-
- **Transformers**: Scikit-learn compatible interfaces for network transformations
78+
- **Simplicial Complex Analysis**: Create simplicial complexes from adjacency matrices by finding maximal cliques.
79+
- **Q-Analysis Metrics**: Compute various graded parameters including:
80+
- First, Second, and Third Structure Vectors (FSV, SSV, TSV)
81+
- Topological Entropy
82+
- Simplex Counts
83+
- Shared Faces Counts
84+
- **Statistical Tools**: Includes utilities for network comparison and statistical analysis.
85+
- **Visualization**: Plot Q-analysis vectors and other topological properties.
86+
- **Scikit-learn Compatibility**: Provides transformers for network transformations compatible with scikit-learn pipelines.
87+
- **Rust Backend**: Core algorithms are implemented in Rust for high performance.
11788

11889
## Contributing
11990

scripts/usage_example.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
from q_analysis.examples.scale_free_configurational import generate_networks
2+
import numpy as np
3+
import os
4+
from itertools import product
5+
from q_analysis.simplicial_complex import SimplicialComplex
6+
import pandas as pd
7+
from matplotlib import pyplot as plt
8+
from q_analysis.viz import plot_q_analysis_vectors
9+
from scipy import stats
10+
from q_analysis.stat import consensus_statistic, calculate_consensus_adjacency_matrix
11+
from q_analysis.transformers import GradedParametersTransformer
12+
from q_analysis.simplicial_complex import GradedParameters
13+
import seaborn as sns
14+
15+
os.makedirs("plots", exist_ok=True)
16+
17+
N_SAMPLES, N_NODES, M_PARAMETER = 100, 100, 8
18+
scale_free_networks, configurational_networks = generate_networks(
19+
N_NODES,
20+
M_PARAMETER,
21+
N_SAMPLES,
22+
)
23+
networks = np.concatenate([scale_free_networks, configurational_networks])
24+
25+
26+
index = product(["Scale free", "Configurational"], range(N_SAMPLES))
27+
simplicial_complex_metrics = [
28+
SimplicialComplex.from_adjacency_matrix(network)
29+
.graded_parameters()
30+
.to_dataframe()
31+
.assign(Network=net_type, Sample=sample_id)
32+
for network, (net_type, sample_id) in zip(networks, index)
33+
]
34+
35+
structure_vectors_df = pd.concat(simplicial_complex_metrics, ignore_index=True)
36+
plot_q_analysis_vectors(
37+
structure_vectors_df, hue="Network", height=3, col_wrap=2, legend_out=False
38+
)
39+
plt.savefig("plots/scale_free_configurational.pdf")
40+
plt.close()
41+
42+
consensus_scale_free_vectors, consensus_configurational_vectors = (
43+
GradedParametersTransformer().fit_transform(
44+
[
45+
calculate_consensus_adjacency_matrix(scale_free_networks),
46+
calculate_consensus_adjacency_matrix(configurational_networks),
47+
],
48+
)
49+
)
50+
max_order = len(consensus_scale_free_vectors)
51+
stats_res = stats.permutation_test(
52+
[scale_free_networks, configurational_networks],
53+
statistic=lambda a, b, axis: consensus_statistic(
54+
a, b, max_order=max_order, edge_inclusion_threshold=0.95
55+
),
56+
n_resamples=10000,
57+
vectorized=True,
58+
batch=100,
59+
axis=1,
60+
)
61+
p_value_df = GradedParameters.from_numpy(stats_res.pvalue).to_dataframe()
62+
consensus_vectors_df = pd.concat(
63+
[
64+
GradedParameters.from_numpy(consensus_vector)
65+
.to_dataframe()
66+
.assign(Network=network)
67+
for network, consensus_vector in zip(
68+
["Scale free", "Configurational"],
69+
[consensus_scale_free_vectors, consensus_configurational_vectors],
70+
)
71+
],
72+
ignore_index=True,
73+
)
74+
plot_q_analysis_vectors(
75+
consensus_vectors_df,
76+
pvalues_df=p_value_df,
77+
hue="Network",
78+
height=3,
79+
col_wrap=2,
80+
legend_out=False,
81+
)
82+
plt.savefig("plots/scale_free_configurational_consensus_vectors.pdf")
83+
plt.close()
84+
85+
simplicial_complexes_topological_dimensionality = [
86+
SimplicialComplex.from_adjacency_matrix(network)
87+
.topological_dimensionality()
88+
.to_dataframe()
89+
.assign(Network=net_type)
90+
.set_index(["Network", "Node"])
91+
for network, net_type in zip(
92+
[scale_free_networks[0], configurational_networks[0]],
93+
["Scale free", "Configurational"],
94+
)
95+
]
96+
topological_dimensionality_df = pd.concat(
97+
simplicial_complexes_topological_dimensionality,
98+
)
99+
ax = sns.barplot(
100+
data=topological_dimensionality_df,
101+
x="Node",
102+
y="Topological Dimensionality",
103+
hue="Network",
104+
)
105+
plt.xticks(plt.xticks()[0][::10])
106+
plt.savefig("plots/scale_free_configurational_topological_dimensionality.pdf")

0 commit comments

Comments
 (0)