Thanks for your interest in contributing! GraphVisual is a large-scale graph theory toolkit with 147 source files, 106 test classes, and 70+ documentation pages. This guide will help you navigate the codebase and contribute effectively.
- Development Setup
- Project Structure
- Module Catalog
- Building & Testing
- Code Style
- Where to Contribute
- Making Changes
- Pull Request Process
- Commit Conventions
- Issue Guidelines
- Architecture Deep Dive
- Java JDK 8 or later (JDK 11 or 17 recommended — CI tests against both)
- Git
- Maven 3.6+ (for dependency resolution via
pom.xml) - PostgreSQL (optional — only needed for the data ingestion pipeline)
IntelliJ IDEA (recommended):
- Open → select the repo root (detects
pom.xmlautomatically) - Mark
Gvisual/srcas Sources Root andGvisual/testas Test Sources Root - Add all JARs in
Gvisual/lib/as project libraries - Set Project SDK to JDK 11 or 17
Eclipse:
- Import → Existing Maven Project → select repo root
- Right-click
Gvisual/lib/*.jar→ Build Path → Add to Build Path - Ensure
Gvisual/testis on the test classpath
VS Code:
- Install the "Extension Pack for Java" extension
- Open the repo root — the Java extension will detect
pom.xml - If library resolution fails, add
Gvisual/lib/*.jarto.classpathmanually
git clone https://github.com/sauravbhattacharya001/GraphVisual.git
cd GraphVisual/Gvisual
# Compile source
mkdir -p build/classes
find src -name '*.java' > sources.txt
javac -cp "$(find lib -name '*.jar' | tr '\n' ':')" -d build/classes @sources.txt
# Compile and run tests
mkdir -p build/test/classes
find test -name '*.java' > test_sources.txt
javac -cp "build/classes:$(find lib -name '*.jar' | tr '\n' ':')" -d build/test/classes @test_sources.txt
java -cp "build/classes:build/test/classes:$(find lib -name '*.jar' | tr '\n' ':')" \
org.junit.runner.JUnitCore gvisual.EdgeTest gvisual.GraphStatsTestOnly needed for the data pipeline (app/ package):
export DB_HOST=localhost
export DB_USER=your_user
export DB_PASS=your_passThe schema expects tables: meeting, event_3, device_1, deviceID.
GraphVisual/
├── .github/
│ ├── workflows/ # CI, CodeQL, coverage, Docker, Pages, publish
│ ├── copilot-instructions.md
│ ├── copilot-setup-steps.yml
│ ├── dependabot.yml
│ └── ISSUE_TEMPLATE/ # Bug report, feature request, performance forms
├── Gvisual/
│ ├── src/
│ │ ├── gvisual/ # 140+ source files — core library
│ │ └── app/ # Data pipeline (DB → edge-list)
│ ├── test/
│ │ ├── gvisual/ # 106 test classes
│ │ └── app/ # Pipeline utility tests
│ ├── lib/ # JUNG 2.0.1, PostgreSQL JDBC, Commons IO
│ └── images/ # UI icons and legend assets
├── Vidly/ # Separate .NET project (not part of GraphVisual core)
├── docs/ # 70+ HTML documentation pages + CSS
├── pom.xml # Maven build descriptor
├── Dockerfile # Multi-stage Docker build
├── ALGORITHMS.md # Algorithm documentation
├── ARCHITECTURE.md # System architecture guide
├── TESTING.md # Testing conventions and coverage gaps
├── SECURITY.md # Security policy
└── DATABASE.md # Database schema documentation
The gvisual package contains 140+ classes organized into functional areas. Here's a map to help you find your way:
| Class | Purpose |
|---|---|
Main |
Swing GUI — graph panel, timeline controls, visualization viewer |
Edge, EdgeType, EdgeTypeRegistry |
Edge model, type definitions, type management |
GraphStats, StatsPanel, GraphStatsDashboard |
Network metrics, stats UI panel, dashboard |
ToolbarBuilder |
Toolbar construction and action wiring |
GraphRenderers |
Custom JUNG vertex/edge rendering transformers |
RandomGraphDialog, RandomGraphGenerator |
Graph generation UI and algorithms |
TemporalGraph, GrowthRateAnalyzer |
Time-series graph model, growth analysis |
QuadTree |
Spatial indexing for force-directed layout |
| Class | Purpose |
|---|---|
CommunityDetector |
Connected component analysis |
LouvainCommunityDetector |
Louvain modularity-based community detection |
CommunityEvolutionTracker |
Track community changes over time |
KCoreDecomposition |
k-core subgraph extraction |
KTrussAnalyzer |
k-truss decomposition |
ArticulationPointAnalyzer |
Cut vertices and biconnected components |
VertexConnectivityAnalyzer |
Vertex connectivity and separating sets |
StronglyConnectedComponentsAnalyzer |
Tarjan's SCC decomposition |
TreeAnalyzer, TreewidthAnalyzer |
Tree recognition, treewidth computation |
ChordalGraphAnalyzer |
Perfect elimination ordering, chordal recognition |
| Class | Purpose |
|---|---|
ShortestPathFinder |
BFS (unweighted) and Dijkstra (weighted) pathfinding |
GraphPathExplorer |
All-pairs paths, path enumeration |
NetworkFlowAnalyzer |
Max-flow / min-cut computation |
EulerianPathAnalyzer |
Euler path/circuit detection and construction |
HamiltonianAnalyzer |
Hamiltonian path/cycle analysis |
TopologicalSortAnalyzer |
DAG ordering, cycle detection |
RandomWalkAnalyzer |
Random walk simulation and hitting times |
| Class | Purpose |
|---|---|
GraphColoringAnalyzer |
Chromatic number, greedy coloring strategies |
ChromaticPolynomialCalculator |
Chromatic polynomial computation |
CliqueAnalyzer, CliqueCoverAnalyzer |
Clique enumeration, clique cover |
IndependentSetAnalyzer |
Maximum independent set |
VertexCoverAnalyzer |
Minimum vertex cover |
DominatingSetAnalyzer |
Minimum dominating set |
FeedbackVertexSetAnalyzer |
Feedback vertex set computation |
MaxCutAnalyzer |
Maximum cut approximation |
MetricDimensionAnalyzer |
Resolving sets and metric dimension |
| Class | Purpose |
|---|---|
NodeCentralityAnalyzer |
Degree, betweenness, closeness, eigenvector centrality |
PageRankAnalyzer |
PageRank computation |
EdgeBetweennessAnalyzer |
Edge betweenness centrality |
GraphCentralityCorrelator |
Cross-centrality correlation analysis |
NodeSimilarityAnalyzer |
Jaccard, cosine, structural similarity |
LinkPredictionAnalyzer |
Link prediction (common neighbors, Adamic-Adar, etc.) |
RichClubAnalyzer |
Rich-club coefficient analysis |
StructuralHoleAnalyzer |
Burt's structural holes, constraint, effective size |
| Class | Purpose |
|---|---|
SpectralAnalyzer |
Eigenvalue decomposition, spectral gap |
LaplacianBuilder |
Laplacian matrix construction |
GraphSpectrumAnalyzer |
Adjacency spectrum analysis |
GraphEntropyAnalyzer |
Graph entropy measures |
WienerIndexCalculator |
Wiener index (sum of all shortest paths) |
BandwidthMinimizer |
Graph bandwidth optimization |
| Class | Purpose |
|---|---|
BipartiteAnalyzer |
Bipartiteness testing, matching |
PlanarGraphAnalyzer |
Planarity testing, face enumeration |
PerfectGraphAnalyzer |
Perfect graph recognition |
TournamentAnalyzer |
Tournament properties, Hamiltonian ordering |
SignedGraphAnalyzer |
Signed graph balance, frustration index |
GraphMinorAnalyzer |
Minor testing and contraction |
LineGraphAnalyzer |
Line graph construction and analysis |
| Class | Purpose |
|---|---|
GraphNetworkProfiler |
Comprehensive structural profiling |
NetworkRoleClassifier |
Structural role classification |
SmallWorldAnalyzer |
Small-world coefficient, clustering |
GraphResilienceAnalyzer |
Attack/failure resilience simulation |
GraphAnomalyDetector |
Anomalous node/edge detection |
InfluenceSpreadSimulator |
Influence cascade simulation (IC, LT models) |
GraphClusterQualityAnalyzer |
Modularity, silhouette, NMI |
DegreeDistributionAnalyzer |
Degree distribution, power-law fitting |
GraphHealthChecker |
Graph quality diagnostics |
| Class | Purpose |
|---|---|
GraphGenerator |
Programmatic graph generation (Erdős–Rényi, BA, etc.) |
FamousGraphLibrary |
Named graph catalog (Petersen, K₅, etc.) |
GraphMerger |
Graph union/intersection/difference |
GraphCompressor |
Graph compression strategies |
GraphComplementAnalyzer |
Complement graph construction |
GraphProductCalculator |
Cartesian, tensor, strong, lexicographic products |
GraphPowerCalculator |
k-th power graph construction |
GraphDegreeSequenceRandomizer |
Degree-preserving rewiring |
SubgraphExtractor |
Induced/edge subgraph extraction |
SubgraphPatternMatcher |
Subgraph isomorphism matching |
GraphIsomorphismChecker, GraphIsomorphismAnalyzer |
Graph isomorphism testing |
GraphSampler |
Graph sampling strategies |
GraphSparsificationAnalyzer |
Edge sparsification |
GraphPartitioner |
Graph partitioning (Kernighan-Lin, spectral) |
GraphVoronoiPartitioner |
Voronoi-based partitioning |
GraphSimilarityAnalyzer |
Graph-level similarity metrics |
GraphDiffAnalyzer |
Structural diff between two graphs |
MotifAnalyzer, GraphMotifFinder |
Network motif detection |
| Class | Purpose |
|---|---|
ForceDirectedLayout |
Force-directed (Fruchterman-Reingold) |
HierarchicalLayout |
Sugiyama-style hierarchical layout |
CircularLayout |
Circular/radial layout |
SpectralLayout |
Spectral embedding layout |
GraphLayoutComparer |
Layout quality comparison |
GraphDrawingQualityAnalyzer |
Crossing number, angular resolution |
| Class | Purpose |
|---|---|
GraphMLExporter, GexfExporter, JsonGraphExporter |
Standard graph formats |
DotExporter, DimacsExporter |
DOT (Graphviz), DIMACS formats |
SvgExporter, TikzExporter |
SVG, LaTeX TikZ export |
InteractiveHtmlExporter, GraphDiffHtmlExporter |
Interactive HTML visualizations |
CsvReportExporter, NetworkFlowExporter |
Tabular data export |
AdjacencyListExporter, AdjacencyMatrixHeatmap |
Adjacency representations |
CentralityRadarExporter |
Radar chart export |
GraphStorytellerExporter |
Natural-language graph narratives |
GraphTimelineExporter |
Temporal evolution export |
GraphAsciiRenderer |
Terminal-friendly graph rendering |
NetworkReportGenerator |
Comprehensive HTML reports |
GraphSummarizer |
Graph summary generation |
| Class | Purpose |
|---|---|
AnalysisTask, AnalysisResult |
Async analysis task framework |
GraphAlgorithmAnimator |
Step-by-step algorithm animation |
GraphAnnotationManager |
Vertex/edge annotation management |
GraphBenchmarkSuite |
Performance benchmarking |
GraphQueryEngine |
Graph query language (GQL-lite) |
GraphIntelligenceAdvisor |
AI-driven analysis recommendations |
GraphUtils |
Shared graph utilities |
ExportActions, ExportUtils |
Export action registry, shared helpers |
MinimumSpanningTree, SteinerTreeAnalyzer |
MST and Steiner tree |
EdgePersistenceAnalyzer |
Edge stability over time |
TimelineMetricsRecorder |
Temporal metric recording |
GraphDistanceDistribution |
Distance histogram analysis |
GraphLabelingAnalyzer |
Graph labeling (graceful, harmonious) |
GraphRegularityAnalyzer |
Regularity testing |
GraphSymmetryAnalyzer |
Automorphism group, orbit analysis |
| Class | Purpose |
|---|---|
CentralityPanelController |
Centrality analysis panel |
CommunityPanelController |
Community detection panel |
ArticulationPanelController |
Bridges/cut-vertices panel |
MSTPanelController |
MST analysis panel |
PathPanelController |
Pathfinding panel |
EgoPanelController |
Ego network panel |
ResiliencePanelController |
Resilience analysis panel |
| Class | Purpose |
|---|---|
Network |
Edge-list generation from database |
Util |
Database connection factory |
findMeetings |
Bluetooth event → meeting extraction |
addLocation |
Meeting location classification |
matchImei |
Device ↔ IMEI matching |
cd Gvisual
mkdir -p build/classes
find src -name '*.java' > sources.txt
javac -cp "$(find lib -name '*.jar' | tr '\n' ':')" -d build/classes @sources.txtmkdir -p build/test/classes
find test -name '*.java' > test_sources.txt
javac -cp "build/classes:$(find lib -name '*.jar' | tr '\n' ':')" -d build/test/classes @test_sources.txt
# Run specific test classes
java -cp "build/classes:build/test/classes:$(find lib -name '*.jar' | tr '\n' ':')" \
org.junit.runner.JUnitCore gvisual.EdgeTest gvisual.GraphStatsTest
# Run all tests (use a test runner or list all test classes)The test suite has 106 test classes covering most analyzers and exporters. CI runs a subset against JDK 11 and 17 — see .github/workflows/ci.yml for the canonical list.
docker build -t graphvisual .
docker run graphvisualThe Docker build compiles all source, runs the full test suite, and produces a fat JAR.
Coverage is tracked via .github/workflows/coverage.yml. When adding new analyzers, add corresponding test classes to maintain coverage.
- Classes:
PascalCase(e.g.,GraphStats,ShortestPathFinder) - Methods/variables:
camelCase(e.g.,calculateDensity,edgeWeight) - Constants:
UPPER_SNAKE_CASE - Packages: lowercase (
gvisual,app) - Test classes:
<ClassName>Test(e.g.,EdgeTest,GraphStatsTest)
Note: Some legacy classes use lowercase names (e.g.,
findMeetings.java). UsePascalCasefor all new classes.
- Keep methods focused — one responsibility per method
- Add Javadoc to all public methods and classes
- No hardcoded credentials — use environment variables (see
Util.java) - Prefer
finalfor parameters and locals that don't change - Use generics properly with JUNG graph types (
Graph<String, Edge>) - Handle
nulland edge cases defensively, especially in graph algorithms - Use
GraphUtilsfor shared operations — check there before writing utility code
- All Swing operations must happen on the Event Dispatch Thread (EDT)
- Use
SwingUtilities.invokeLater()for cross-thread UI updates - Keep visualization logic in
Main.java; extract algorithms to separate classes - Panel controllers wire analysis panels to the GUI — follow the existing pattern
- Use JUnit 4 (
@Test,@Before,@After) - Test normal cases, edge cases (empty graphs, disconnected components, single nodes), and boundary conditions
- Tests must work without a database connection
- Use descriptive names:
testMethodName_scenario_expectedResult - See TESTING.md for coverage gaps and testing conventions
-
Test coverage expansion — See TESTING.md for the full inventory of untested classes. Many analyzers added recently have test classes, but some older modules or newer panel controllers may lack coverage.
-
Algorithm improvements — The analyzers use heuristic approximations for NP-hard problems (coloring, independent set, vertex cover, etc.). Better heuristics or tighter bounds are always welcome.
-
Performance — Several analyzers operate on adjacency scans that could benefit from precomputed data structures. Profile before optimizing —
GraphBenchmarkSuitecan help. -
New export formats — Formats like Graph6, Sparse6, or Pajek (.net) would be useful additions.
-
Documentation pages — The
docs/folder has 70+ interactive HTML pages. If you add a new analyzer, consider adding a corresponding documentation page. -
GUI panels — Many analyzers run from the toolbar or menu but don't have dedicated panel controllers for interactive use.
Look for issues labeled good first issue. If none exist, adding tests for untested classes or improving Javadoc on public APIs are great starting points.
- Check open issues for existing discussions
- For significant changes, open an issue first to discuss the approach
- Fork the repository and create a feature branch
feature/<description>— new features or analyzersfix/<description>— bug fixesrefactor/<description>— code improvementsdocs/<description>— documentation changestest/<description>— test additions or fixesperf/<description>— performance improvements
- All existing tests must pass before pushing
- Add tests for new classes — every new analyzer should have a corresponding
*Test.java - GUI changes — test manually by running
Main.java - Data pipeline changes — require a PostgreSQL instance with test data
- Verify compilation against JDK 8 compatibility (
-source 8 -target 8in CI)
- Create a focused PR — one logical change per PR
- Write a clear description — what changed, why, and how to test it
- All CI checks must pass — build (JDK 11 + 17), tests, CodeQL security scan
- Keep the PR small — large PRs are harder to review; split if possible
- Update documentation — if your change affects the README or architecture
- Code compiles without warnings on JDK 11 and 17
- All existing tests pass
- New tests added for new functionality
- No hardcoded credentials or secrets
- Javadoc added to public methods
- Documentation updated if applicable (README, docs/, ALGORITHMS.md)
- Commit messages follow conventions
Use Conventional Commits format:
<type>: <short description>
<optional body>
| Type | Description |
|---|---|
feat |
New feature or analyzer |
fix |
Bug fix |
refactor |
Code restructuring (no behavior change) |
test |
Adding or fixing tests |
docs |
Documentation only |
perf |
Performance improvement |
ci |
CI/CD configuration |
chore |
Build process or tooling changes |
feat: add Steiner tree analyzer with terminal-set heuristics
fix: prevent NPE in GraphColoringAnalyzer on disconnected graphs
perf: O(1) adjacency lookups via HashSet in GraphColoringAnalyzer
test: add 25 tests for BipartiteAnalyzer covering König's theorem
docs: add interactive planarity testing documentation page
Main.java orchestrates the Swing GUI:
- Reads an edge-list file (generated by the data pipeline or loaded from file)
- Creates a JUNG
SparseMultigraph<String, Edge>from the data - Applies layout algorithms (static grid, force-directed, hierarchical, circular, spectral)
- Renders via
VisualizationViewerwith custom vertex/edge transformers - Timeline controls iterate over a date range, rebuilding the graph per timestamp
- Panel controllers wire analysis tools into the sidebar
Most analyzers follow this pattern:
- Accept a
Graph<String, Edge>(JUNG graph) - Compute results using graph traversals, matrix operations, or heuristics
- Return structured results that can be displayed in panels or exported
- Optionally generate HTML reports via the
docs/templates
Bluetooth events → findMeetings → matchImei → addLocation → Network → edge-list → Main (GUI)
Each pipeline stage reads from and writes to PostgreSQL. The edge-list file bridges the pipeline to the visualizer.
- JUNG 2.0.1 — Graph data structures and basic algorithms
- PostgreSQL JDBC — Database connectivity for the data pipeline
- Commons IO — File and stream utilities
- JUnit 4 — Testing framework
Include:
- Steps to reproduce
- Expected vs actual behavior
- Java version and OS
- Stack trace if applicable
- Sample graph data if relevant (edge-list or GraphML)
Include:
- Problem or use case description
- Proposed approach (algorithm, data structure)
- Impact on existing functionality
- References (papers, existing implementations) if applicable
Before pushing, replicate exactly what CI does:
cd Gvisual
# JDK 11 build (CI primary)
mkdir -p build/classes build/test/classes
find src -name '*.java' > sources.txt
javac -source 8 -target 8 \
-cp "$(find lib -name '*.jar' | tr '\n' ':')" \
-d build/classes @sources.txt
# Compile tests
find test -name '*.java' > test_sources.txt
javac -cp "build/classes:$(find lib -name '*.jar' | tr '\n' ':')" \
-d build/test/classes @test_sources.txt
# Run all tests
java -cp "build/classes:build/test/classes:$(find lib -name '*.jar' | tr '\n' ':')" \
org.junit.runner.JUnitCore $(find build/test/classes -name '*Test.class' \
| sed 's|build/test/classes/||;s|/|.|g;s|\.class||')mvn clean compile # Build only
mvn clean test # Build + run tests
mvn clean verify # Full verificationReproduces the full CI environment:
docker build -t graphvisual:local .
# Runs tests as part of the multi-stage buildCI tests on both JDK 11 and JDK 17. If you have both installed:
JAVA_HOME=/path/to/jdk11 mvn test
JAVA_HOME=/path/to/jdk17 mvn testInstall the CodeQL CLI and run:
codeql database create graphvisual-db --language=java --source-root=.
codeql database analyze graphvisual-db codeql/java-queries:codeql-suites/java-security-extended.qls --format=sarif-latest --output=results.sarifGraphVisual includes GraphBenchmarkSuite — a collection of classic network science benchmark graphs for testing algorithm performance.
import gvisual.GraphBenchmarkSuite;
// Generate all benchmark graphs
List<GraphBenchmarkSuite.BenchmarkGraph> benchmarks = GraphBenchmarkSuite.getAllBenchmarks();
// Time your analyzer against increasing graph sizes
for (BenchmarkGraph bg : benchmarks) {
long start = System.nanoTime();
YourAnalyzer analyzer = new YourAnalyzer(bg.getGraph());
analyzer.analyze();
long elapsed = System.nanoTime() - start;
System.out.printf("%s (%d nodes): %.2f ms%n",
bg.getName(), bg.getGraph().getVertexCount(), elapsed / 1e6);
}| Graph Size | Acceptable Response Time |
|---|---|
| < 100 nodes | < 10 ms |
| 100–1,000 nodes | < 100 ms |
| 1,000–10,000 nodes | < 1 second |
| > 10,000 nodes | Document complexity |
- Use
GraphBenchmarkSuite— don't invent random graph generators for every test - Measure wall-clock time for user-facing operations
- Profile before optimizing — use VisualVM or async-profiler
- Document complexity — add
@implNoteJavadoc with big-O for non-trivial algorithms - Avoid premature allocation — reuse collections across iterations when safe
- Precompute adjacency sets or degree caches if your analyzer does repeated neighbor lookups
When submitting a performance PR:
- Show before/after timings on at least 2 benchmark graphs
- Include the graph size and your hardware specs
- Verify correctness hasn't regressed (same outputs on same inputs)
GraphVisual uses a hybrid approach:
- Maven (
pom.xml) — for CI, CodeQL, and IDE integration - Local JARs (
Gvisual/lib/) — for compilation without Maven (legacy support)
- Add to
pom.xmlwith appropriate<scope>(compile, test, provided) - Place the JAR in
Gvisual/lib/for non-Maven builds - Update
.github/copilot-setup-steps.ymlif the dep affects build steps - Document why it's needed in the PR description
| Dependency | Version | Purpose |
|---|---|---|
| JUNG | 2.0.1 | Graph data structures & basic algorithms |
| PostgreSQL JDBC | 42.7.x | Data pipeline database connectivity |
| Commons IO | 2.x | File/stream utilities |
| JUnit 4 | 4.13.x | Test framework |
Dependabot manages automated updates. To manually update:
mvn versions:display-dependency-updates
mvn versions:use-latest-releases -DallowMajorUpdates=falseAlways run the full test suite after a dependency update.
By contributing, you agree that your contributions will be licensed under the MIT License.
We follow the Contributor Covenant v2.1. Be respectful, give constructive feedback, focus on what's best for the community, and show empathy toward other contributors.