Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
neesjanvaneck committed Aug 29, 2022
0 parents commit 565bb21
Show file tree
Hide file tree
Showing 58 changed files with 23,344 additions and 0 deletions.
70 changes: 70 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:import/typescript",
"standard"
],
"env": {
"es6": true,
"browser": true
},
"plugins": [
"svelte3"
],
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"overrides": [
{
"files": ["*.svelte"],
"processor": "svelte3/svelte3",
"rules": {
"import/first": "off",
"import/no-duplicates": "off",
"import/no-mutable-exports": "off",
"import/no-unresolved": "off"
}
}
],
"rules": {
"object-curly-spacing": ["error", "always"],
"prefer-template": "error",
"no-useless-constructor": "off",
"import/extensions": 0,
"import/no-extraneous-dependencies": 0,
"import/prefer-default-export": 0,
"import/first": ["error", "absolute-first"],
"comma-dangle": ["error", {
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "never"
}],
"indent": ["error", 2],
"no-console": ["warn", { "allow": ["warn", "error"] }],
"no-undef": 0,
"no-unused-vars": 0,
"no-unused-expressions": "off",
"no-multiple-empty-lines": ["error", { "max": 1, "maxBOF": 2, "maxEOF": 0 }],
"@typescript-eslint/member-ordering": "error",
"@typescript-eslint/explicit-member-accessibility": "error",
"@typescript-eslint/explicit-function-return-type": "error",
"consistent-return": "error",
"@typescript-eslint/no-explicit-any": ["error"],
"@typescript-eslint/no-unused-expressions": ["error"],
"@typescript-eslint/indent": "off",
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "enum",
"format": ["PascalCase"]
},
{
"selector": "enumMember",
"format": ["PascalCase"]
}
]
}
}
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.DS_Store
node_modules
dist
lib
.idea
yarn.lock
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 Centre for Science and Technology Studies (CWTS), Leiden University

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
199 changes: 199 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# networkanalysis-ts

This package is a TypeScript port of the [networkanalysis](https://github.com/CWTSLeiden/networkanalysis) package written in Java. The package provides algorithms and data structures for network analysis. Currently, the package focuses on clustering (or community detection) and layout (or mapping) of networks. In particular, the package contains an implementation of the [Leiden algorithm](https://doi.org/10.1038/s41598-019-41695-z) and the [Louvain algorithm](https://doi.org/10.1088/1742-5468/2008/10/P10008) for network clustering and the [VOS technique](https://doi.org/10.1002/asi.21421) for network layout. Only undirected networks are supported.

The networkanalysis-ts package was developed by [Nees Jan van Eck](https://orcid.org/0000-0001-8448-4521) at the [Centre for Science and Technology Studies (CWTS)](https://www.cwts.nl) at [Leiden University](https://www.universiteitleiden.nl/en) and benefited from contributions by [Olya Stukova](https://github.com/Stukova) and [Nikita Rokotyan](https://github.com/Rokotyan) from [Interacta](https://interacta.io). The networkanalysis package written in Java on which networkanalysis-ts is based was developed by [Vincent Traag](https://orcid.org/0000-0003-3170-3879), [Nees Jan van Eck](https://orcid.org/0000-0001-8448-4521), and [Ludo Waltman](https://orcid.org/0000-0001-8249-1752).

## Documentation

Documentation of the source code of networkanalysis-ts is provided in the code in `TSDoc` format. The documentation is also available in a [compiled format](https://neesjanvaneck.github.io/networkanalysis-ts).

## Installation

```sh
npm install networkanalysis-ts
```

## Usage

The following code snippet demonstrates how the core classes in networkanalysis-ts can be used to create a network and to perform network normalization, clustering, and layout:

```typescript
import { Clustering, GradientDescentVOSLayoutAlgorithm, Layout, LeidenAlgorithm, Network } from 'networkanalysis-ts'

const nRandomStarts = 10

// Construct network.
const nNodes = 6
const edges = [[0, 1, 2, 2, 3, 5, 4], [1, 2, 0, 3, 5, 4, 3]]
const network = new Network({
nNodes: nNodes,
setNodeWeightsToTotalEdgeWeights: true,
edges: edges,
sortedEdges: false,
checkIntegrity: true,
})

// Perform network normalization.
const normalizedNetwork = network.createNormalizedNetworkUsingAssociationStrength()

// Perform clustering.
let bestClustering: Clustering | undefined
let maxQuality = Number.NEGATIVE_INFINITY
const clusteringAlgorithm = new LeidenAlgorithm()
clusteringAlgorithm.setResolution(0.2)
clusteringAlgorithm.setNIterations(50)
for (let i = 0; i < nRandomStarts; i++) {
const clustering = new Clustering({ nNodes: normalizedNetwork.getNNodes() })
clusteringAlgorithm.improveClustering(normalizedNetwork, clustering)
const quality = clusteringAlgorithm.calcQuality(normalizedNetwork, clustering)
if (quality > maxQuality) {
bestClustering = clustering
maxQuality = quality
}
}
bestClustering?.orderClustersByNNodes()

// Perform layout.
let bestLayout: Layout | undefined
let minQuality = Number.POSITIVE_INFINITY
const layoutAlgorithm = new GradientDescentVOSLayoutAlgorithm();
layoutAlgorithm.setAttraction(2)
layoutAlgorithm.setRepulsion(1)
for (let i = 0; i < nRandomStarts; i++) {
const layout = new Layout({ nNodes: normalizedNetwork.getNNodes() })
layoutAlgorithm.improveLayout(normalizedNetwork, layout)
const quality = layoutAlgorithm.calcQuality(normalizedNetwork, layout)
if (quality < minQuality) {
bestLayout = layout
minQuality = quality
}
}
bestLayout?.standardize(true)
```

The package also includes a `run` module that provides helper classes for running the network analysis algorithms in an easier way. The following code snippet demonstrates the use of the helper classes for constructing a network and for performing network clustering and layout:

```typescript
import { Node, Link, NetworkClustering, NetworkLayout } from 'networkanalysis-ts/run'

// Construct network.
const nodes: Node[] = [
{ id: 'James' },
{ id: 'Mary' },
{ id: 'John' },
{ id: 'Linda' },
{ id: 'David' },
{ id: 'Karen' },
]
const links: Link[] = [
{ node1: nodes[0], node2: nodes[1] },
{ node1: nodes[1], node2: nodes[2] },
{ node1: nodes[2], node2: nodes[0] },
{ node1: nodes[2], node2: nodes[3] },
{ node1: nodes[3], node2: nodes[5] },
{ node1: nodes[5], node2: nodes[4] },
{ node1: nodes[4], node2: nodes[3] },
]

// Perform clustering.
new NetworkClustering()
.data(nodes, links)
.qualityFunction('CPM')
.normalization('AssociationStrength')
.resolution(0.2)
.minClusterSize(1)
.algorithm('Leiden')
.randomStarts(10)
.iterations(50)
.randomness(0.01)
.seed(0)
.run()

// Perform layout.
new NetworkLayout()
.data(nodes, links)
.qualityFunction('VOS')
.normalization('AssociationStrength')
.attraction(2)
.repulsion(1)
.randomStarts(10)
.seed(0)
.run()
```

## Demo app

The GitHub repository of networkanalys-ts also provides a [Svelt](https://svelte.dev) demo app that uses the helper classes discussed above. The source code of the demo app is available in the `app/` folder. The following screenshot shows the output of the demo app when applying it to a journal co-citation network:

<img src="https://github.com/neesjanvaneck/networkanalysis-ts/blob/main/app/assets/images/networkanalysis-ts-demo-app.png?raw=true" alt="networkanalysis-ts demo app" style="width: 100%; max-width: 800px; height: auto;">

## License

The networkanalysis-ts package is distributed under the [MIT license](LICENSE).

## Issues

If you encounter any issues, please report them using the [issue tracker](https://github.com/neesjanvaneck/networkanalysis-ts/issues) on GitHub.

## Contribution

You are welcome to contribute to the development of networkanalysis-ts. Please follow the typical GitHub workflow: Fork from this repository and make a pull request to submit your changes. Make sure that your pull request has a clear description and that the code has been properly tested.

## Development and deployment

The latest stable version of the code is available from the [`main`](https://github.com/neesjanvaneck/networkanalysis-ts/tree/main) branch on GitHub. The most recent code, which may be under development, is available from the [`develop`](https://github.com/neesjanvaneck/networkanalysis-ts/tree/develop) branch.

### Requirements

To run networkanalysis-ts locally and to build production-ready bundles, [Node.js](https://nodejs.org) and [npm](https://www.npmjs.com) need to be installed on your system.

### Setup

Run
```sh
npm install
```
to install all required Node.js packages.

### Development

Run
```sh
npm run dev
```
to build a development version of the demo app and serve it with hot reload at [http://localhost:6800](http://localhost:6800).

### Deployment

Run
```sh
npm run build:lib
```
to build a deployment version of the package. The output is stored in the `lib/` folder.

Run
```sh
npm run build:app
```
to build a deployment version of the demo app. The output is stored in the `dist/` folder.

Run
```sh
npm run build
```
to build a deployment version of both the package and the demo app.

### References

> Traag, V.A., Waltman, L., & Van Eck, N.J. (2019). From Louvain to Leiden: Guaranteeing well-connected communities. *Scientific Reports*, 9, 5233. https://doi.org/10.1038/s41598-019-41695-z
> Van Eck, N.J., Waltman, L., Dekker, R., & Van den Berg, J. (2010). A comparison of two techniques for bibliometric mapping: Multidimensional scaling and VOS. *Journal of the American Society for Information Science and Technology*, 61(12), 2405-2416. https://doi.org/10.1002/asi.21421
> Waltman, L., Van Eck, N.J., & Noyons, E.C.M. (2010). A unified approach to mapping and clustering of bibliometric networks. *Journal of Informetrics*, 4(4), 629-635. https://doi.org/10.1016/j.joi.2010.07.002
> Van Eck, N.J., & Waltman, L. (2009). How to normalize co-occurrence data? An analysis of some well-known similarity measures. *Journal of the American Society for Information Science and Technology*, 60(8), 1635-1651. https://doi.org/10.1002/asi.21075
> Blondel, V.D., Guillaume, J.-L., Lambiotte, R., & Lefebvre, E. (2008). Fast unfolding of communities in large networks. *Journal of Statistical Mechanics: Theory and Experiment*, 10, P10008. https://doi.org/10.1088/1742-5468/2008/10/P10008
> Newman, M.E.J. & Girvan, M. (2004). Finding and evaluating community structure in networks. *Physical Review E*, 69(2), 026113, https://doi.org/10.1103/PhysRevE.69.026113.
40 changes: 40 additions & 0 deletions app/App.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<script>
import { onMount } from 'svelte'
import { parseData } from './parseData'
import { processData } from './processData'
import { runNetworkLayout, runNetworkClustering } from './runAlgorithms'
import { updateScales, renderLinks, renderNodes } from './renderNetwork'
let svgElement
onMount(() => {
parseData(parseResult => {
try {
const { nodes, links } = processData(parseResult.data)
runNetworkClustering(nodes, links)
runNetworkLayout(nodes, links)
updateScales(svgElement.clientWidth, svgElement.clientHeight, nodes)
renderLinks(svgElement, links)
renderNodes(svgElement, nodes)
} catch (error) {
console.error(error.message)
}
})
})
</script>
<style>
:global(body) {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}
svg {
position: absolute;
width: 100%;
height: 100%;
}
</style>
<div class="App">
<svg bind:this={svgElement}>
</svg>
</div>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 565bb21

Please sign in to comment.