diff --git a/src/client/containers/SemanticPortal.js b/src/client/containers/SemanticPortal.js
index 8dc6cd60bf747b75f646c1b36805a3549a193302..2f892f411e927a9866e95fcfc17584f49a9332c4 100644
--- a/src/client/containers/SemanticPortal.js
+++ b/src/client/containers/SemanticPortal.js
@@ -49,7 +49,8 @@ import {
 } from '../helpers/helpers'
 import * as apexChartsConfig from '../library_configs/ApexCharts/ApexChartsConfig'
 import * as leafletConfig from '../library_configs/Leaflet/LeafletConfig'
-import * as networkConfig from '../library_configs/Cytoscape.js/NetworkConfig'
+import * as networkToolsGeneral from '../library_configs/Cytoscape.js/NetworkToolsGeneral'
+import * as networkToolsPortalSpecific from '../library_configs/Cytoscape.js/NetworkToolsPortalSpecific'
 
 // ** Generate portal configuration based on JSON configs **
 import portalConfig from '../../configs/portalConfig.json'
@@ -69,6 +70,10 @@ const perspectiveConfigOnlyInfoPages = await createPerspectiveConfigOnlyInfoPage
   portalID,
   onlyInstancePagePerspectives: perspectives.onlyInstancePages
 })
+const networkConfig = {
+  ...networkToolsGeneral,
+  ...networkToolsPortalSpecific
+}
 // ** portal configuration end **
 
 // ** Import general components **
diff --git a/src/client/library_configs/Cytoscape.js/NetworkConfig.js b/src/client/library_configs/Cytoscape.js/NetworkConfig.js
deleted file mode 100644
index 1223a95b788ed50e8e5e7c2ddec5949d6b3e7b4a..0000000000000000000000000000000000000000
--- a/src/client/library_configs/Cytoscape.js/NetworkConfig.js
+++ /dev/null
@@ -1,251 +0,0 @@
-import { has } from 'lodash'
-import { constrainValue, ValueScaler, ColorScaler } from './NetworkTools'
-
-//  preprocess by pagerank
-export const preprocessPagerank = elements => {
-  const maxEdgeWidth = 8
-
-  //  edges
-  let arr = elements.edges.map(ele => ele.data.weight)
-
-  //  edge width
-  let res = (new ValueScaler(1.0, maxEdgeWidth)).fitTransform(arr)
-  elements.edges.forEach((ele, i) => { ele.data.weight = res[i] })
-
-  // nodes
-  arr = elements.nodes.map(ele => ele.data.pagerank)
-
-  // node size
-  res = (new ColorScaler('6px', '24px')).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.size = res[i] })
-
-  // node label font size
-  res = (new ValueScaler(8, 12)).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.font_size = res[i] })
-
-  elements.nodes.forEach(ele => {
-    if (ele.data.distance === 0) {
-      ele.data.size = '16px'
-      ele.data.color = 'black'
-      ele.data.font_size = 12.0
-      // console.log('Found')
-    }
-  })
-}
-
-export const preprocessLetterSampo = elements => {
-  const maxEdgeWidth = 8
-
-  /**
-  const rankSort = arr => {
-   const arr2 = arr.map(function (o, i) { return { idx: i, obj: o } }).sort((a, b) => a.obj - b.obj)
-   return arr2.map(function (o, i) { o.ord = i; return o }).sort((a, b) => a.idx - b.idx).map(o => o.ord)
-  }
-  */
-
-  //  edges
-  let arr = elements.edges.map(ele => ele.data.weight || 1)
-
-  //  edge width
-  let res = (new ValueScaler(1.0, maxEdgeWidth)).fitTransform(arr)
-  elements.edges.forEach((ele, i) => { ele.data.weight = res[i] })
-
-  //  edge color
-  // https://www.w3schools.com/colors/colors_hsl.asp
-  res = (new ColorScaler('hsl(30, 64%, 85%)', 'hsl(30, 64%, 35%)')).fitTransform(arr)
-  elements.edges.forEach((ele, i) => { ele.data.color = res[i] })
-
-  // nodes
-  arr = elements.nodes.map(ele => Math.sqrt(ele.data.numLetters || 0))
-
-  // TODO: adjust node sizes e.g. https://stackoverflow.com/questions/30167117/get-the-current-index-in-sort-function
-  // node size
-  res = (new ColorScaler('8px', '40px')).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.size = res[i] })
-
-  // node color
-  res = (new ColorScaler('rgb(0,0,0)', 'rgb(255,0,0)')).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.color = res[i] })
-}
-
-export const preprocessEgo = elements => {
-  const maxEdgeWidth = 8
-  //  edges
-  let arr = elements.edges.map(ele => ele.data.weight || 1)
-
-  //  edge width
-  let res = (new ValueScaler(1.0, maxEdgeWidth)).fitTransform(arr)
-  elements.edges.forEach((ele, i) => { ele.data.weight = res[i] })
-
-  //  edge color
-  // https://www.w3schools.com/colors/colors_hsl.asp
-  res = (new ColorScaler('hsl(30, 64%, 85%)', 'hsl(30, 64%, 35%)')).fitTransform(arr)
-  elements.edges.forEach((ele, i) => { ele.data.color = res[i] })
-
-  // nodes
-  arr = elements.nodes.map(ele => has(ele.data, 'distance') ? ele.data.distance : 3)
-  // node size
-  res = (new ColorScaler('20px', '8px')).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.size = res[i] })
-
-  // node color
-  res = (new ColorScaler('rgb(255,0,0)', 'rgb(0,0,0)')).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.color = res[i] })
-}
-
-export const preprocessTie = elements => {
-  const maxEdgeWidth = 8
-  //  edges
-  let arr = elements.edges.map(ele => ele.data.weight)
-
-  //  edge width
-  let res = (new ValueScaler(1.0, maxEdgeWidth)).fitTransform(arr)
-  elements.edges.forEach((ele, i) => { ele.data.weight = res[i] })
-
-  //  edge color
-  res = (new ColorScaler('hsl(30, 64%, 85%)', 'hsl(30, 64%, 35%)')).fitTransform(arr)
-  elements.edges.forEach((ele, i) => { ele.data.color = res[i] })
-
-  // nodes
-  arr = elements.nodes.map(ele => ele.data.pagerank)
-
-  // node size
-  res = (new ColorScaler('8px', '20px')).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.size = res[i] })
-
-  // node color
-  res = (new ColorScaler('rgb(0,0,0)', 'rgb(255,0,0)')).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.color = res[i] })
-}
-
-export const preprocessRelationNetwork = elements => {
-  preprocessPagerank(elements)
-
-  // nodes
-  const arr = elements.nodes.map(ele => ele.data.distance)
-
-  // node size
-  let res = (new ColorScaler('24px', '6px')).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.size = res[i] })
-
-  // node label font size
-  res = (new ValueScaler(12, 8)).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.font_size = res[i] })
-}
-
-//  preprocess for person/connections
-export const preprocessConnections = elements => {
-  //  edges
-  let arr = elements.edges.map(ele => ele.data.weight)
-
-  //  edge width
-  let res = (new ValueScaler(1.0, 4.0)).fitTransform(arr)
-  elements.edges.forEach((ele, i) => { ele.data.weight = res[i] })
-
-  const maxlength = 60
-  elements.edges.forEach(ele => {
-    const st = ele.data.prefLabel
-    ele.data.prefLabel = st.length > maxlength ? st.substring(0, maxlength - 3) + '...' : st
-  })
-  // nodes by distance to ego
-  arr = elements.nodes.map(ele => ele.data.distance)
-
-  // node size
-  res = (new ColorScaler('24px', '6px')).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.size = res[i] })
-
-  // node label font size
-  res = (new ValueScaler(12, 8)).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.font_size = res[i] })
-
-  elements.nodes.forEach(ele => { ele.data.color = (ele.data.distance < 1) ? 'red' : 'blue' })
-
-  elements.nodes.forEach(ele => {
-    if (ele.data.distance === 0) {
-      ele.data.size = '16px'
-      ele.data.color = 'black'
-      ele.data.font_size = 12.0
-      // console.log('Found')
-    }
-  })
-}
-
-//  preprocess by ego node distance
-export const preprocessDistance = elements => {
-  const maxEdgeWidth = 8
-
-  //  edges
-  let arr = elements.edges.map(ele => ele.data.weight)
-
-  //  edge width
-  let res = (new ValueScaler(1.0, maxEdgeWidth)).fitTransform(arr)
-  elements.edges.forEach((ele, i) => { ele.data.weight = res[i] })
-
-  // console.log(elements.nodes)
-  // nodes
-  arr = elements.nodes.map(ele => ele.data.distance)
-
-  // node size
-  res = (new ColorScaler('24px', '6px')).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.size = res[i] })
-
-  //  label size
-  res = (new ValueScaler(16, 8)).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.font_size = res[i] })
-}
-
-export const preprocessPointCloud = elements => {
-  const nodes = elements.nodes.map(ob => {
-    return {
-      data: ob.data,
-      position: {
-        x: 360 * parseFloat(ob.data.x),
-        y: 360 * parseFloat(ob.data.y)
-      }
-    }
-  })
-  elements.nodes = nodes
-  elements.edges = []
-}
-
-export const preprocessFamilytree = elements => {
-  const maxEdgeWidth = 8
-
-  const nodes = elements.nodes.map(ob => {
-    if (ob.data.distance === 0) {
-      ob.data.size = '24px'
-      ob.data.color = 'black'
-      // console.log('Found')
-    }
-    return {
-      data: ob.data,
-      position: {
-        x: 800 * parseFloat(ob.data.x),
-        y: 600 * parseFloat(ob.data.y)
-      }
-    }
-  })
-  elements.nodes = nodes
-  elements.edges.forEach(edge => {
-    edge.data.weight = constrainValue({ value: edge.data.weight, maxValue: maxEdgeWidth })
-  })
-}
-
-export const preprocessParliamentSampoPeopleNetwork = elements => {
-  preprocessPagerank(elements)
-
-  // nodes
-  const arr = elements.nodes.map(ele => ele.data.distance)
-
-  // node size
-  let res = (new ColorScaler('26px', '12px')).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.size = res[i] })
-
-  //  label size
-  res = (new ValueScaler(12, 8)).fitTransform(arr)
-  elements.nodes.forEach((ele, i) => { ele.data.font_size = res[i] })
-
-  // node color
-  // res = (new ColorScaler('rgb(255, 0, 0)', 'rgb(0, 0, 255)')).fitTransform(arr)
-  // elements.nodes.forEach((ele, i) => { ele.data.color = res[i] })
-}
diff --git a/src/client/library_configs/Cytoscape.js/NetworkTools.js b/src/client/library_configs/Cytoscape.js/NetworkTools.js
deleted file mode 100644
index ceba0d428936a5eb1591cdeb8b2a87724b7e44d5..0000000000000000000000000000000000000000
--- a/src/client/library_configs/Cytoscape.js/NetworkTools.js
+++ /dev/null
@@ -1,59 +0,0 @@
-export const constrainValue = ({ value, maxValue, defaultValue = 1 }) => {
-  return (value ? (value < maxValue ? value : maxValue) : defaultValue)
-}
-
-export class ValueScaler {
-    a;
-    b;
-    constructor (low, high) {
-      this.low = low
-      this.high = high
-    }
-
-    fit (vals) {
-      const valmin = Math.min(...vals)
-      const valmax = Math.max(...vals)
-      if (valmax === valmin) {
-        this.a = 0.0
-      } else {
-        this.a = (this.high - this.low) / (valmax - valmin)
-      }
-      this.b = this.low - valmin * this.a
-    }
-
-    transform (vals) {
-      return vals.map(x => { return x * this.a + this.b })
-    }
-
-    fitTransform (vals) {
-      this.fit(vals)
-      return this.transform(vals)
-    }
-}
-
-export class ColorScaler extends ValueScaler {
-    col1;
-    col2;
-    constructor (low, high) {
-      super(0.0, 1.0)
-      this.col1 = low
-      this.col2 = high
-    }
-
-    // super.fit(vals)
-
-    _process (s0, s1, r) {
-      const x0 = parseInt(s0)
-      const x1 = parseInt(s1)
-      if (isNaN(x0) || isNaN(x1)) return s0
-      return Math.floor(x0 + (x1 - x0) * r)
-    }
-
-    transform (vals) {
-      const s1 = this.col1.split(/(\d+)/)
-      const s2 = this.col2.split(/(\d+)/)
-      const _vals01 = vals.map(x => { return x * this.a + this.b })
-
-      return _vals01.map(v => s1.map((s, i) => this._process(s, s2[i], v)).join(''))
-    }
-}
diff --git a/src/client/library_configs/Cytoscape.js/NetworkToolsGeneral.js b/src/client/library_configs/Cytoscape.js/NetworkToolsGeneral.js
new file mode 100644
index 0000000000000000000000000000000000000000..52d7e3771a3f12e3ac33c5c5c0a52b3941dabcae
--- /dev/null
+++ b/src/client/library_configs/Cytoscape.js/NetworkToolsGeneral.js
@@ -0,0 +1,143 @@
+import { has } from 'lodash'
+
+export const constrainValue = ({ value, maxValue, defaultValue = 1 }) => {
+  return (value ? (value < maxValue ? value : maxValue) : defaultValue)
+}
+
+export class ValueScaler {
+    a;
+    b;
+    constructor (low, high) {
+      this.low = low
+      this.high = high
+    }
+
+    fit (vals) {
+      const valmin = Math.min(...vals)
+      const valmax = Math.max(...vals)
+      if (valmax === valmin) {
+        this.a = 0.0
+      } else {
+        this.a = (this.high - this.low) / (valmax - valmin)
+      }
+      this.b = this.low - valmin * this.a
+    }
+
+    transform (vals) {
+      return vals.map(x => { return x * this.a + this.b })
+    }
+
+    fitTransform (vals) {
+      this.fit(vals)
+      return this.transform(vals)
+    }
+}
+
+export class ColorScaler extends ValueScaler {
+    col1;
+    col2;
+    constructor (low, high) {
+      super(0.0, 1.0)
+      this.col1 = low
+      this.col2 = high
+    }
+
+    // super.fit(vals)
+
+    _process (s0, s1, r) {
+      const x0 = parseInt(s0)
+      const x1 = parseInt(s1)
+      if (isNaN(x0) || isNaN(x1)) return s0
+      return Math.floor(x0 + (x1 - x0) * r)
+    }
+
+    transform (vals) {
+      const s1 = this.col1.split(/(\d+)/)
+      const s2 = this.col2.split(/(\d+)/)
+      const _vals01 = vals.map(x => { return x * this.a + this.b })
+
+      return _vals01.map(v => s1.map((s, i) => this._process(s, s2[i], v)).join(''))
+    }
+}
+
+//  preprocess by pagerank
+export const preprocessPagerank = elements => {
+  const maxEdgeWidth = 8
+
+  //  edges
+  let arr = elements.edges.map(ele => ele.data.weight)
+
+  //  edge width
+  let res = (new ValueScaler(1.0, maxEdgeWidth)).fitTransform(arr)
+  elements.edges.forEach((ele, i) => { ele.data.weight = res[i] })
+
+  // nodes
+  arr = elements.nodes.map(ele => ele.data.pagerank)
+
+  // node size
+  res = (new ColorScaler('6px', '24px')).fitTransform(arr)
+  elements.nodes.forEach((ele, i) => { ele.data.size = res[i] })
+
+  // node label font size
+  res = (new ValueScaler(8, 12)).fitTransform(arr)
+  elements.nodes.forEach((ele, i) => { ele.data.font_size = res[i] })
+
+  // highlight main node
+  elements.nodes.forEach(ele => {
+    if (ele.data.distance === 0) {
+      ele.data.size = '16px'
+      ele.data.color = 'black'
+      ele.data.font_size = 12.0
+    }
+  })
+}
+
+export const preprocessEgo = elements => {
+  const maxEdgeWidth = 8
+
+  //  edges
+  let arr = elements.edges.map(ele => ele.data.weight || 1)
+
+  //  edge width
+  let res = (new ValueScaler(1.0, maxEdgeWidth)).fitTransform(arr)
+  elements.edges.forEach((ele, i) => { ele.data.weight = res[i] })
+
+  //  edge color
+  // https://www.w3schools.com/colors/colors_hsl.asp
+  res = (new ColorScaler('hsl(30, 64%, 85%)', 'hsl(30, 64%, 35%)')).fitTransform(arr)
+  elements.edges.forEach((ele, i) => { ele.data.color = res[i] })
+
+  // nodes
+  arr = elements.nodes.map(ele => has(ele.data, 'distance') ? ele.data.distance : 3)
+
+  // node size
+  res = (new ColorScaler('20px', '8px')).fitTransform(arr)
+  elements.nodes.forEach((ele, i) => { ele.data.size = res[i] })
+
+  // node color
+  res = (new ColorScaler('rgb(255,0,0)', 'rgb(0,0,0)')).fitTransform(arr)
+  elements.nodes.forEach((ele, i) => { ele.data.color = res[i] })
+}
+
+//  preprocess by ego node distance
+export const preprocessDistance = elements => {
+  const maxEdgeWidth = 8
+
+  //  edges
+  let arr = elements.edges.map(ele => ele.data.weight)
+
+  //  edge width
+  let res = (new ValueScaler(1.0, maxEdgeWidth)).fitTransform(arr)
+  elements.edges.forEach((ele, i) => { ele.data.weight = res[i] })
+
+  // nodes
+  arr = elements.nodes.map(ele => ele.data.distance)
+
+  // node size
+  res = (new ColorScaler('24px', '6px')).fitTransform(arr)
+  elements.nodes.forEach((ele, i) => { ele.data.size = res[i] })
+
+  //  label size
+  res = (new ValueScaler(16, 8)).fitTransform(arr)
+  elements.nodes.forEach((ele, i) => { ele.data.font_size = res[i] })
+}
diff --git a/src/client/library_configs/Cytoscape.js/NetworkToolsPortalSpecific.js b/src/client/library_configs/Cytoscape.js/NetworkToolsPortalSpecific.js
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391