From 5ed12043991f693460773558f5a15062c8e3af4c Mon Sep 17 00:00:00 2001
From: "Hartung, Michael" <michael.hartung@uni-hamburg.de>
Date: Mon, 11 Jul 2022 16:10:49 +0200
Subject: [PATCH] fix node duplication bug when node group has "id" and make
 enrichment analysis button small style

---
 .../analysis-panel.component.ts               | 40 +++++++++----------
 .../info-tile/info-tile.component.html        |  2 +-
 .../network-menu-left.component.html          |  4 +-
 .../network-menu/network-menu.component.html  |  4 +-
 .../components/network/network.component.ts   | 20 +++++-----
 .../add-expressed-proteins.component.ts       |  4 +-
 .../launch-analysis.component.ts              |  4 +-
 src/app/interfaces.ts                         | 21 +++++-----
 src/app/network-settings.ts                   |  1 +
 .../explorer-page.component.html              |  4 +-
 .../explorer-page/explorer-page.component.ts  | 27 ++++++++-----
 .../netex-controller.service.ts               | 10 ++---
 src/index.html                                | 29 ++++++++++++--
 13 files changed, 100 insertions(+), 70 deletions(-)

diff --git a/src/app/components/analysis-panel/analysis-panel.component.ts b/src/app/components/analysis-panel/analysis-panel.component.ts
index 59584070..3b5c1419 100644
--- a/src/app/components/analysis-panel/analysis-panel.component.ts
+++ b/src/app/components/analysis-panel/analysis-panel.component.ts
@@ -197,12 +197,12 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
 
         this.networkHandler.activeNetwork.networkInternal = new vis.Network(container, this.nodeData, options);
 
-        this.tableDrugs = nodes.filter( e => e.drugstoneId && e.drugstoneId.startsWith('d'));
+        this.tableDrugs = nodes.filter( e => e.netexId && e.netexId.startsWith('d'));
         this.tableDrugs.forEach((r) => {
           r.rawScore = r.score;
         });
 
-        this.tableProteins = nodes.filter( e => e.drugstoneId && e.drugstoneId.startsWith('p'));
+        this.tableProteins = nodes.filter( e => e.netexId && e.netexId.startsWith('p'));
         this.tableSelectedProteins = [];
         this.tableProteins.forEach((r) => {
           r.rawScore = r.score;
@@ -233,7 +233,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
           if (nodeIds.length > 0) {
             const nodeId = nodeIds[0];
             const node = this.nodeData.nodes.get(nodeId);
-            if (node.nodeType === 'drug' || node.drugstoneId === undefined || !node.drugstoneId.startsWith('p')) {
+            if (node.nodeType === 'drug' || node.netexId === undefined || !node.netexId.startsWith('p')) {
               return;
             }
             const wrapper = getWrapperFromNode(node);
@@ -306,7 +306,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
             this.nodeData.nodes.forEach((node) => {
               // let drugType;
               // let drugInTrial;
-              // if (node.drugstoneId && node.drugstoneId.startsWith('d')) {
+              // if (node.netexId && node.netexId.startsWith('d')) {
               //   drugType = node.status;
               //   drugInTrial = node.inTrial;
               // }
@@ -428,7 +428,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
   //       }
   //       for (const disorder of response.disorders) {
   //         disorder.group = 'defaultDisorder';
-  //         disorder.id = disorder.drugstoneId;
+  //         disorder.id = disorder.netexId;
   //         this.adjacentProteinDisorderList.push(mapCustomNode(disorder, this.myConfig))
   //       }
   //       this.saveAddNodes(this.adjacentProteinDisorderList);
@@ -456,7 +456,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
   //       }
   //       for (const disorder of response.disorders) {
   //         disorder.group = 'defaultDisorder';
-  //         disorder.id = disorder.drugstoneId;
+  //         disorder.id = disorder.netexId;
   //         this.adjacentDrugDisorderList.push(mapCustomNode(disorder, this.myConfig));
   //       }
   //       this.saveAddNodes(this.adjacentDrugDisorderList);
@@ -495,9 +495,9 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
   public inferNodeGroup(wrapper: Wrapper): string {
     if (wrapper.data.group !== undefined) {
       return wrapper.data.group;
-    } else if (wrapper.data.drugstoneId !== undefined && wrapper.data.drugstoneId.startsWith('d')) {
+    } else if (wrapper.data.netexId !== undefined && wrapper.data.netexId.startsWith('d')) {
       return 'drug';
-    } else if (wrapper.data.drugstoneId !== undefined && wrapper.data.drugstoneId.startsWith('p')) {
+    } else if (wrapper.data.netexId !== undefined && wrapper.data.netexId.startsWith('p')) {
       return 'protein';
     }
   }
@@ -531,7 +531,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
   public createNetwork(result: any): { edges: any[], nodes: any[] } {
     const config = result.parameters.config;
     this.myConfig = config;
-
+    
     const identifier = this.myConfig.identifier;
 
     // add drugGroup and foundNodesGroup for added nodes
@@ -554,14 +554,14 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
       // convert id to netex Id if exists
       const nodeDetails = details[node];
 
-      nodeDetails.id = nodeDetails.id ? nodeDetails.id : nodeDetails.drugstoneId;
-      if (nodeDetails.drugstoneId && nodeDetails.drugstoneId.startsWith('p')) {
+      nodeDetails.id = nodeDetails.id ? nodeDetails.id : nodeDetails.netexId;
+      if (nodeDetails.netexId && nodeDetails.netexId.startsWith('p')) {
         // node is protein from database, has been mapped on init to backend protein from backend
         // or was found during analysis
         nodeDetails.group = nodeDetails.group ? nodeDetails.group : 'foundNode';
         nodeDetails.label = nodeDetails.label ? nodeDetails.label : nodeDetails[identifier];
         this.proteins.push(nodeDetails);
-      } else if (nodeDetails.drugstoneId && nodeDetails.drugstoneId.startsWith('d')) {
+      } else if (nodeDetails.netexId && nodeDetails.netexId.startsWith('d')) {
         // node is drug, was found during analysis
         nodeDetails.type = 'Drug';
         nodeDetails.group = 'foundDrug';
@@ -586,7 +586,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
   // hasDrugsLoaded(): boolean {
   //   if (this.nodeData == null || this.nodeData.nodes == null)
   //     return false;
-  //   return this.nodeData.nodes.get().filter((node: Node) => node.drugId && node.drugstoneId.startsWith('dr')).length > 0;
+  //   return this.nodeData.nodes.get().filter((node: Node) => node.drugId && node.netexId.startsWith('dr')).length > 0;
   // }
 
   // public updateAdjacentDrugs(bool: boolean) {
@@ -684,7 +684,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
   //     this.selectedTissue = null;
   //     const updatedNodes = [];
   //     for (const item of this.proteins) {
-  //       if (item.drugstoneId === undefined) {
+  //       if (item.netexId === undefined) {
   //         // nodes that are not mapped to backend remain untouched
   //         continue;
   //       }
@@ -718,7 +718,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
   //     // filter out non-proteins, e.g. drugs
   //     const proteinNodes = [];
   //     this.nodeData.nodes.forEach(element => {
-  //       if (element.id.startsWith('p') && element.drugstoneId !== undefined) {
+  //       if (element.id.startsWith('p') && element.netexId !== undefined) {
   //         proteinNodes.push(element);
   //       }
   //     });
@@ -728,17 +728,17 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
   //       // mapping from netex IDs to network IDs, TODO check if this step is necessary
   //       const networkIdMappping = {}
   //       this.nodeData.nodes.forEach(element => {
-  //         networkIdMappping[element.drugstoneId] = element.id
+  //         networkIdMappping[element.netexId] = element.id
   //       });
   //       const maxExpr = Math.max(...Object.values(this.expressionMap));
-  //       for (const [drugstoneId, expressionlvl] of Object.entries(this.expressionMap)) {
-  //         const networkId = networkIdMappping[drugstoneId]
+  //       for (const [netexId, expressionlvl] of Object.entries(this.expressionMap)) {
+  //         const networkId = networkIdMappping[netexId]
   //         const node = this.nodeData.nodes.get(networkId);
   //         if (node === null) {
   //           continue;
   //         }
   //         const wrapper = getWrapperFromNode(node)
-  //         this.gradientMap[drugstoneId] = expressionlvl !== null ? (Math.pow(expressionlvl / maxExpr, 1 / 3) * (1 - minExp) + minExp) : -1;
+  //         this.gradientMap[netexId] = expressionlvl !== null ? (Math.pow(expressionlvl / maxExpr, 1 / 3) * (1 - minExp) + minExp) : -1;
   //         const pos = this.networkHandler.activeNetwork.networkInternal.getPositions([networkId]);
   //         node.x = pos[networkId].x;
   //         node.y = pos[networkId].y;
@@ -749,7 +749,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges, AfterViewInit
   //             this.myConfig,
   //             isSeed,
   //             this.analysis.inSelection(wrapper),
-  //             this.gradientMap[drugstoneId]));
+  //             this.gradientMap[netexId]));
   //         node.shape = 'custom';
   //         node.ctxRenderer = pieChartContextRenderer;
   //         updatedNodes.push(node);
diff --git a/src/app/components/info-tile/info-tile.component.html b/src/app/components/info-tile/info-tile.component.html
index dc8f22f3..744580ef 100644
--- a/src/app/components/info-tile/info-tile.component.html
+++ b/src/app/components/info-tile/info-tile.component.html
@@ -101,7 +101,7 @@
   </div>
 
   <app-toggle
-    *ngIf="wrapper.data.drugstoneId && wrapper.data.drugstoneId.startsWith('p')"
+    *ngIf="wrapper.data.netexId && wrapper.data.netexId.startsWith('p')"
     [value]="analysis.inSelection(wrapper)"
     (valueChange)="
       $event ? analysis.addItems([wrapper]) : analysis.removeItems([wrapper])
diff --git a/src/app/components/network/network-menu-left/network-menu-left.component.html b/src/app/components/network/network-menu-left/network-menu-left.component.html
index 16d61492..c251083c 100644
--- a/src/app/components/network/network-menu-left/network-menu-left.component.html
+++ b/src/app/components/network/network-menu-left/network-menu-left.component.html
@@ -151,8 +151,8 @@
                   (click)="networkHandler.activeNetwork.selectTissue(tissue)"
                   [class.is-active]="
                     networkHandler.activeNetwork.selectedTissue &&
-                    tissue.drugstoneId ===
-                      networkHandler.activeNetwork.selectedTissue.drugstoneId
+                    tissue.netexId ===
+                      networkHandler.activeNetwork.selectedTissue.netexId
                   "
                   class="dropdown-item"
                 >
diff --git a/src/app/components/network/network-menu/network-menu.component.html b/src/app/components/network/network-menu/network-menu.component.html
index 4a80fc1d..f529997a 100644
--- a/src/app/components/network/network-menu/network-menu.component.html
+++ b/src/app/components/network/network-menu/network-menu.component.html
@@ -151,8 +151,8 @@
                   (click)="networkHandler.activeNetwork.selectTissue(tissue)"
                   [class.is-active]="
                     networkHandler.activeNetwork.selectedTissue &&
-                    tissue.drugstoneId ===
-                      networkHandler.activeNetwork.selectedTissue.drugstoneId
+                    tissue.netexId ===
+                      networkHandler.activeNetwork.selectedTissue.netexId
                   "
                   class="dropdown-item"
                 >
diff --git a/src/app/components/network/network.component.ts b/src/app/components/network/network.component.ts
index 529f5fcc..9410c3d9 100644
--- a/src/app/components/network/network.component.ts
+++ b/src/app/components/network/network.component.ts
@@ -73,7 +73,7 @@ export class NetworkComponent implements OnInit {
   public highlightSeeds = false;
   public seedMap: NodeAttributeMap = {};
 
-  // keys are node drugstoneIds
+  // keys are node netexIds
   public expressionMap: NodeAttributeMap = {};
   public gradientMap: NodeAttributeMap = {};
 
@@ -119,7 +119,7 @@ export class NetworkComponent implements OnInit {
         }
         for (const disorder of response.disorders) {
           disorder.group = 'defaultDisorder';
-          disorder.id = disorder.drugstoneId;
+          disorder.id = disorder.netexId;
           this.adjacentProteinDisorderList.push(mapCustomNode(disorder, this.drugstoneConfig.config))
         }
         this.saveAddNodes(this.adjacentProteinDisorderList);
@@ -147,7 +147,7 @@ export class NetworkComponent implements OnInit {
         }
         for (const disorder of response.disorders) {
           disorder.group = 'defaultDisorder';
-          disorder.id = disorder.drugstoneId;
+          disorder.id = disorder.netexId;
           this.adjacentDrugDisorderList.push(mapCustomNode(disorder, this.drugstoneConfig.config));
         }
         this.saveAddNodes(this.adjacentDrugDisorderList);
@@ -271,7 +271,7 @@ export class NetworkComponent implements OnInit {
       const updatedNodes = [];
       // for (const item of this.proteins) {
       for (const item of this.currentViewProteins) {
-        if (item.drugstoneId === undefined) {
+        if (item.netexId === undefined) {
           // nodes that are not mapped to backend remain untouched
           continue;
         }
@@ -303,7 +303,7 @@ export class NetworkComponent implements OnInit {
       // filter out non-proteins, e.g. drugs
       const proteinNodes = [];
       this.nodeData.nodes.forEach(element => {
-        if (element.id.startsWith('p') && element.drugstoneId !== undefined) {
+        if (element.id.startsWith('p') && element.netexId !== undefined) {
           proteinNodes.push(element);
         }
       });
@@ -313,11 +313,11 @@ export class NetworkComponent implements OnInit {
         // mapping from netex IDs to network IDs, TODO check if this step is necessary
         const networkIdMappping = {}
         this.nodeData.nodes.forEach(element => {
-          networkIdMappping[element.drugstoneId] = element.id
+          networkIdMappping[element.netexId] = element.id
         });
         const maxExpr = Math.max(...Object.values(this.expressionMap));
-        for (const [drugstoneId, expressionlvl] of Object.entries(this.expressionMap)) {
-          const networkId = networkIdMappping[drugstoneId]
+        for (const [netexId, expressionlvl] of Object.entries(this.expressionMap)) {
+          const networkId = networkIdMappping[netexId]
           const node = this.nodeData.nodes.get(networkId);
           if (node === null) {
             continue;
@@ -349,7 +349,7 @@ export class NetworkComponent implements OnInit {
   public hasDrugsLoaded(): boolean {
     if (this.nodeData == null || this.nodeData.nodes == null)
       return false;
-    return this.nodeData.nodes.get().filter((node: Node) => node.drugId && node.drugstoneId.startsWith('dr')).length > 0;
+    return this.nodeData.nodes.get().filter((node: Node) => node.drugId && node.netexId.startsWith('dr')).length > 0;
   }
 
   public setLegendContext() {
@@ -376,7 +376,7 @@ export class NetworkComponent implements OnInit {
     this.highlightSeeds = bool;
     const updatedNodes = [];
     for (const item of this.currentViewProteins) {
-      if (item.drugstoneId === undefined) {
+      if (item.netexId === undefined) {
         // nodes that are not mapped to backend remain untouched
         continue;
       }
diff --git a/src/app/dialogs/add-expressed-proteins/add-expressed-proteins.component.ts b/src/app/dialogs/add-expressed-proteins/add-expressed-proteins.component.ts
index c1e8a59c..634873da 100644
--- a/src/app/dialogs/add-expressed-proteins/add-expressed-proteins.component.ts
+++ b/src/app/dialogs/add-expressed-proteins/add-expressed-proteins.component.ts
@@ -39,7 +39,7 @@ export class AddExpressedProteinsComponent implements OnChanges {
   public async addProteins() {
     this.loading = true;
     const result = await this.http.post<any>(`${environment.backend}query_tissue_proteins/`,
-      {tissueId: this.selectedTissue.drugstoneId, threshold: this.threshold}).toPromise();
+      {tissueId: this.selectedTissue.netexId, threshold: this.threshold}).toPromise();
     const items = [];
     for (const detail of result) {
       items.push(getWrapperFromNode(detail));
@@ -59,7 +59,7 @@ export class AddExpressedProteinsComponent implements OnChanges {
     if (!this.currentViewProteins || this.expressionMap === undefined) {
       return;
     }
-    this.proteins = this.currentViewProteins.filter(p => this.expressionMap[p.drugstoneId] >= threshold);
+    this.proteins = this.currentViewProteins.filter(p => this.expressionMap[p.netexId] >= threshold);
   }
 
   public close() {
diff --git a/src/app/dialogs/launch-analysis/launch-analysis.component.ts b/src/app/dialogs/launch-analysis/launch-analysis.component.ts
index bf4637eb..38ef3ecd 100644
--- a/src/app/dialogs/launch-analysis/launch-analysis.component.ts
+++ b/src/app/dialogs/launch-analysis/launch-analysis.component.ts
@@ -104,8 +104,8 @@ export class LaunchAnalysisComponent implements OnInit, OnChanges {
   }
 
   public async startTask() {
-    // all nodes in selection have drugstoneId, hence exist in the backend
-    const seeds = this.analysis.getSelection().map((item) => item.data.drugstoneId)
+    // all nodes in selection have netexId, hence exist in the backend
+    const seeds = this.analysis.getSelection().map((item) => item.data.netexId)
     const seedsFiltered = seeds.filter(function (el) {
       return el != null;
     });
diff --git a/src/app/interfaces.ts b/src/app/interfaces.ts
index 59daa8bf..e479edf3 100644
--- a/src/app/interfaces.ts
+++ b/src/app/interfaces.ts
@@ -5,7 +5,7 @@ export interface Node {
   symbol: string;
   id: string;
   type: string;
-  drugstoneId?: string;
+  netexId?: string;
   drugId?:string;
   uniprotAc?: string;
   ensg?: Array<string>;
@@ -28,7 +28,7 @@ export interface Node {
 }
 
 export interface Tissue {
-  drugstoneId: number;
+  netexId: number;
   name: string;
 }
 
@@ -42,7 +42,7 @@ export type NetworkType = 'explorer' | 'analysis'
 export type LegendContext = 'explorer' | 'adjacentDrugs' | 'drug' | 'drugTarget' |
 'drugTargetAndSeeds' | 'drugAndSeeds' | 'adjacentDisorders' | 'adjacentDrugsAndDisorders';
 
-/// drugstoneId to expressionlvl
+/// netexId to expressionlvl
 export type NodeAttributeMap = { string: number } | {};
 
 export interface NetexInteraction {
@@ -125,21 +125,21 @@ export function getDrugNodeId(drug: Drug) {
   /**
    * Returns backend_id of Drug object
    */
-  return drug.drugstoneId
+  return drug.netexId
 }
 
 // export function getDisorderNodeId(disorder: Disorder) {
 //   /**
 //    * Returns backend_id of Drug object
 //    */
-//   return disorder.drugstoneId
+//   return disorder.netexId
 
 export function getNodeId(node: Node) {
   /**
    * Returns backend_id of Gene object
    */
-  //  if ('drugstoneId' in node) {
-  //    return node['drugstoneId']
+  //  if ('netexId' in node) {
+  //    return node['netexId']
   //  } else {
   //    return node.id
   //  }
@@ -150,7 +150,7 @@ export function getNetworkId(node: Node) {
   /**
    * Returns ID of a network node
    */
-  return node.drugstoneId
+  return node.netexId
 }
 
 export function getId(gene: Node) {
@@ -165,6 +165,7 @@ export function getWrapperFromNode(node: Node): Wrapper {
    * Constructs wrapper interface for gene
    */
   // if node does not have property group, it was custom node from user
+  console.log(node.groupName)
   node.group = node.group ? node.group : 'default';
   node.label = node.label ? node.label : node.id
   return {
@@ -182,7 +183,7 @@ export interface Wrapper {
     label: string;
     type?: string;
     symbol?: string;
-    drugstoneId?: string;
+    netexId?: string;
     ensg?: Array<string>;
     shape?: string;
     color?: string;
@@ -215,7 +216,7 @@ export interface Drug {
   inTrial: boolean;
   inLiterature: boolean;
   trialLinks: string[];
-  drugstoneId: string;
+  netexId: string;
   group: string;
 }
 
diff --git a/src/app/network-settings.ts b/src/app/network-settings.ts
index ddd420a3..b8e1ae85 100644
--- a/src/app/network-settings.ts
+++ b/src/app/network-settings.ts
@@ -133,6 +133,7 @@ export class NetworkSettings {
     } else {
       node = merge(node, config.nodeGroups[node.group]);
     }
+
     // note that seed and selected node style are applied after the node style is fetched.
     // this allows to overwrite only attributes of interest, therefor in e.g. seedNode group
     // certain attributes like shape can remain undefined
diff --git a/src/app/pages/explorer-page/explorer-page.component.html b/src/app/pages/explorer-page/explorer-page.component.html
index c6df3dde..c49b9079 100644
--- a/src/app/pages/explorer-page/explorer-page.component.html
+++ b/src/app/pages/explorer-page/explorer-page.component.html
@@ -465,7 +465,7 @@
                     *ngIf="analysis.getCount() > 0"
                     [href]="gProfilerLink()"
                     target="_blank"
-                    class="button is-primary is-fullwidth is-rounded has-tooltip"
+                    class="button is-primary is-fullwidth is-rounded has-tooltip is-small"
                     pTooltip="Use enrichment analysis via g:Profiler (external)."
                     [tooltipStyleClass]="
                       'drgstn drgstn-tooltip drgstn-tooltip-top'
@@ -484,7 +484,7 @@
                   <a
                     *ngIf="analysis.getCount() === 0"
                     disabled
-                    class="button is-primary is-fullwidth is-rounded has-tooltip"
+                    class="button is-primary is-fullwidth is-rounded has-tooltip is-small"
                     pTooltip="Use enrichment analysis via g:Profiler (external)."
                     [tooltipStyleClass]="
                       'drgstn drgstn-tooltip drgstn-tooltip-top'
diff --git a/src/app/pages/explorer-page/explorer-page.component.ts b/src/app/pages/explorer-page/explorer-page.component.ts
index cf615e66..dae1f7df 100644
--- a/src/app/pages/explorer-page/explorer-page.component.ts
+++ b/src/app/pages/explorer-page/explorer-page.component.ts
@@ -40,7 +40,7 @@ declare var vis: any;
 
 export class ExplorerPageComponent implements OnInit, AfterViewInit {
 
-  private networkJSON = '{"nodes": [], "edges": []}';
+  private networkJSON = undefined;  //'{"nodes": [], "edges": []}'
   public _config: string;
 
   @Input()
@@ -65,7 +65,11 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
     if (network == null) {
       return;
     }
-    this.networkJSON = JSON.stringify(typeof network === 'string' ? JSON5.parse(network) : network);
+    try {
+      this.networkJSON = JSON.stringify(typeof network === 'string' ? JSON5.parse(network) : network);
+    } catch {
+      console.log('ERROR: Failed parsing input network')
+    }
     this.activateConfig();
   }
 
@@ -122,7 +126,6 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
     public networkHandler: NetworkHandlerService) {
     this.showDetails = false;
     this.analysis.subscribeList(async (items, selected) => {
-
       // return if analysis panel is open or no nodes are loaded
       if (this.selectedAnalysisToken || !this.nodeData.nodes) {
         return;
@@ -275,7 +278,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
       if (nodeIds != null && nodeIds.length > 0) {
         const nodeId = nodeIds[0];
         const node = this.nodeData.nodes.get(nodeId);
-        if (node.drugstoneId === undefined || !node.drugstoneId.startsWith('p')) {
+        if (node.netexId === undefined || !node.netexId.startsWith('p')) {
           // skip if node is not a protein mapped to backend
           return;
         }
@@ -345,17 +348,16 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
 
     if (this.drugstoneConfig.config.identifier === 'ensg') {
       // remove possible duplicate IDs
-      network.nodes = removeDuplicateObjectsFromList(network.nodes, 'drugstoneId');
+      network.nodes = removeDuplicateObjectsFromList(network.nodes, 'netexId');
     }
 
     // at this point, we have nodes synched with the backend
-    // use drugstoneIds where posssible, but use original id as node name if no label given
+    // use netexIds where posssible, but use original id as node name if no label given
     const nodeIdMap = {};
     network.nodes.forEach((node) => {
       // set node label to original id before node id will be set to netex id
       node.label = node.label ? node.label : node.id;
-
-      nodeIdMap[node.id] = node.drugstoneId ? node.drugstoneId : node.id;
+      nodeIdMap[node.id] = node.netexId ? node.netexId : node.id;
       node.id = nodeIdMap[node.id];
     });
 
@@ -461,6 +463,11 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
       }
       // implement nodeShadow option, it needs to be set for all nodes or none
       group.shadow = this.drugstoneConfig.config.nodeShadow;
+
+      // group must not have id, otherwise node id's would be overwritten which causes duplciates
+      if (group.hasOwnProperty('id')) {
+        delete group['id'];
+      }
     });
 
     this.drugstoneConfig.config[key] = nodeGroups;
@@ -494,9 +501,9 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
   }
 
   gProfilerLink(): string {
-    // nodes in selection have drugstoneId
+    // nodes in selection have netexId
     const queryString = this.analysis.getSelection()
-      .filter(wrapper => wrapper.data.drugstoneId.startsWith('p'))
+      .filter(wrapper => wrapper.data.netexId.startsWith('p'))
       .map(wrapper => wrapper.data.uniprotAc)
       .join('%0A');
     return 'http://biit.cs.ut.ee/gprofiler/gost?' +
diff --git a/src/app/services/netex-controller/netex-controller.service.ts b/src/app/services/netex-controller/netex-controller.service.ts
index bce39cb1..baa8a588 100644
--- a/src/app/services/netex-controller/netex-controller.service.ts
+++ b/src/app/services/netex-controller/netex-controller.service.ts
@@ -89,9 +89,9 @@ export class NetexControllerService {
      * Returns the expression in the given tissue for given nodes and cancerNodes
      */
       // slice prefix of netex id away for direct lookup in db, if node not mapped to db, replace by undefined
-    const genesBackendIds = nodes.map((node: Node) => node.drugstoneId ? node.drugstoneId.slice(1) : undefined);
+    const genesBackendIds = nodes.map((node: Node) => node.netexId ? node.netexId.slice(1) : undefined);
     const params = new HttpParams()
-      .set('tissue', tissue.drugstoneId)
+      .set('tissue', tissue.netexId)
       .set('proteins', JSON.stringify(genesBackendIds));
     return this.http.get(`${environment.backend}tissue_expression/`, {params});
   }
@@ -101,10 +101,10 @@ export class NetexControllerService {
     const params = {};
     if (nodeType === 'proteins') {
       // @ts-ignore
-      params.proteins = nodes.map((node: Node) => node.drugstoneId && node.drugstoneId.startsWith('p') ? node.drugstoneId.slice(1) : undefined).filter(id => id != null);
+      params.proteins = nodes.map((node: Node) => node.netexId && node.netexId.startsWith('p') ? node.netexId.slice(1) : undefined).filter(id => id != null);
     } else if (nodeType === 'drugs') {
       // @ts-ignore
-      params.drugs = nodes.map((node: Node) => node.drugId && node.drugstoneId.startsWith('dr') ? node.drugstoneId.slice(2) : undefined).filter(id => id != null);
+      params.drugs = nodes.map((node: Node) => node.drugId && node.netexId.startsWith('dr') ? node.netexId.slice(2) : undefined).filter(id => id != null);
     }
     return this.http.post<any>(`${environment.backend}adjacent_disorders/`, params);
   }
@@ -114,7 +114,7 @@ export class NetexControllerService {
      * Returns the expression in the given tissue for given nodes and cancerNodes
      */
       // slice prefix of netex id away for direct lookup in db, if node not mapped to db, replace by undefined
-    const genesBackendIds = nodes.map((node: Node) => node.drugstoneId && node.drugstoneId.startsWith('p') ? node.drugstoneId.slice(1) : undefined).filter(id => id != null);
+    const genesBackendIds = nodes.map((node: Node) => node.netexId && node.netexId.startsWith('p') ? node.netexId.slice(1) : undefined).filter(id => id != null);
     const params = {
       pdi_dataset: pdiDataset,
       proteins: genesBackendIds
diff --git a/src/index.html b/src/index.html
index 3614e49c..7094e66b 100644
--- a/src/index.html
+++ b/src/index.html
@@ -48,10 +48,31 @@
 <div style="max-width: 80vw">
 
   <drugst-one id="netexp1"
-                    pluginId="2"
-                    config='{"interactionDrugProtein":"NeDRex", "physicsOn":true, "showLeftSidebar": true, "showSimpleAnalysis":true, "nodeGroups":{"patient":{"type":"patient","color":"black","font":{"color":"#ffffff"},"groupName":"Patient","shape":"image","image":"https://static.thenounproject.com/png/22780-200.png"},"condition":{"type":"condition","color":"black","font":{"color":"black"},"groupName":"Condition","shape":"text"},"important":{"type":"gene","color":"#ff881f","font":{"color":"#000000"},"groupName":"Important Gene","shape":"star"},"gene":{"type":"gene","color":"#4da300","font":{"color":"#ffffff"},"groupName":"Gene","shape":"circle"},"foundDrug":{"type":"drug","color":{"border":"#F12590","background":"#F12590"},"font":{"color":"#f0f0f0"},"groupName":"Drug","shape":"diamond"}},"edgeGroups":{"genotype":{"color":"black","groupName":"Relevant Gene"},"has-condition":{"color":"#000000","groupName":"Has Condition","dashes":[2,2]},"default":{"color":"#000000","groupName":"default edge"},"ggi":{"color":"#000000","groupName":"Interaction","dashes":[3,2]}},"identifier":"symbol","title":"Breast cancer example network","nodeShadow":true,"edgeShadow":false,"autofillEdges":false,"showLegend":true}'
-                    network='{"nodes":[{"id":"patient-1","group":"patient","x":592,"y":446},{"id":"patient-2","group":"patient","x":235,"y":87},{"id":"patient-3","group":"patient","x":105,"y":369},{"id":"ATM","label":"ATM","group":"gene","x":289,"y":242},{"id":"BARD1","label":"BARD1","group":"gene","x":44,"y":250},{"id":"BRCA1","label":"BRCA1","group":"gene","x":466,"y":576},{"id":"BRCA2","label":"BRCA2","group":"gene","x":507,"y":285},{"id":"BRIP1","label":"BRIP1","group":"gene","x":54,"y":474},{"id":"CHEK2","label":"CHEK2","group":"gene","x":216,"y":590},{"id":"CDH1","label":"CDH1","group":"gene","x":320,"y":-57},{"id":"NF1","label":"NF1","group":"gene","x":481,"y":111},{"id":"NBN","label":"NBN","group":"gene","x":-57,"y":314},{"id":"PALB2","label":"PALB2","group":"gene","x":450,"y":190},{"id":"PTEN","label":"PTEN","group":"important","x":305,"y":494},{"id":"RAD51C","label":"RAD51C","group":"gene","x":182,"y":-90},{"id":"RAD51D","label":"RAD51D","group":"gene","x":368,"y":73},{"id":"STK11","label":"STK11","group":"gene","x":686,"y":330},{"id":"TP53","label":"TP53","group":"important","x":333,"y":316},{"id":"subtype-1","label":"Subtype 1","group":"condition","x":556,"y":171},{"id":"subtype-2","label":"Subtype 2","group":"condition","x":-87,"y":221}],"edges":[{"from":"BRCA1","to":"BRCA2","group":"ggi"},{"from":"ATM","to":"BARD1","group":"ggi"},{"from":"BRCA1","to":"CHEK2","group":"ggi"},{"from":"RAD51C","to":"RAD51D","group":"ggi"},{"from":"STK11","to":"TP53","group":"ggi"},{"from":"TP53","to":"PALB2","group":"ggi"},{"from":"TP53","to":"RAD51D","group":"ggi"},{"from":"TP53","to":"NF1","group":"ggi"},{"from":"TP53","to":"BRCA1","group":"ggi"},{"from":"TP53","to":"BRCA2","group":"ggi"},{"from":"PTEN","to":"BRCA1","group":"ggi"},{"from":"PTEN","to":"BRCA2","group":"ggi"},{"from":"TP53","to":"PTEN","group":"ggi"},{"from":"ATM","to":"PTEN","group":"ggi"},{"from":"CDH1","to":"RAD51D","group":"ggi"},{"from":"CDH1","to":"PALB2","group":"ggi"},{"from":"NBN","to":"BRIP1","group":"ggi"},{"from":"BRIP1","to":"PTEN","group":"ggi"},{"from":"patient-1","to":"BRCA1","group":"genotype"},{"from":"patient-1","to":"TP53","group":"genotype"},{"from":"patient-1","to":"BRCA2","group":"genotype"},{"from":"patient-1","to":"PTEN","group":"genotype"},{"from":"patient-2","to":"TP53","group":"genotype"},{"from":"patient-2","to":"NF1","group":"genotype"},{"from":"patient-2","to":"BARD1","group":"genotype"},{"from":"patient-3","to":"TP53","group":"genotype"},{"from":"patient-3","to":"PTEN","group":"genotype"},{"from":"patient-3","to":"NBN","group":"genotype"},{"from":"patient-1","to":"subtype-1","group":"has-condition"},{"from":"patient-2","to":"subtype-1","group":"has-condition"},{"from":"patient-3","to":"subtype-2","group":"has-condition"}]}'>
-  </drugst-one>
+              pluginId="2"
+              config='{"nodeGroups":{
+                "proteinCoding":{"type":"gene","color":{background:"#116466",border:"#000000"} ,"font":{"color":"#000000"},"borderWidth":2,"groupName":"gene","shape":"square", "id":"proteinCoding"},
+                "up":{"type":"gene","color":{background:"#FC6566",border:"#000000"},"font":{"color":"#000000"},"borderWidth":2,"groupName":"up-regulated gene","shape":"square","id":"up"},
+                "down":{"type":"gene","color":{background:"#1158E9",border:"#000000"},"font":{"color":"#000000"},"borderWidth":2,"groupName":"down-regulated gene","shape":"square","id":"down"},
+                "unchanged":{"type":"gene","color":{background:"#A0B89D",border:"#000000"},"font":{"color":"#000000"},"borderWidth":2,"groupName":"unchanged gene","shape":"square","id":"unchanged"},
+                "metMeta":{"type":"metabolite","color":{background:"#E8A87C",border:"#000000"},"font":{"color":"#000000"},"borderWidth":2,"groupName":"metabolite","shape":"dot","id":"metMeta"},
+                "trait":{"type":"trait","color":"#B4CADB","font":{"color":"#000000"},"groupName":"trait","shape":"ellipse","id":"trait"},
+                "traitMeta":{"type":"trait","color":"#8c3d37","font":{"color":"#000000"},"groupName":"traitMeta","shape":"star","id":"traitMeta"},
+                "foundDrug":{"type":"drug","color":"#B186B4","font":{"color":"#000000"},"groupName":"drug","shape":"diamond"},
+                "defaultDisorder":{"type":"disorder","color":"#F0E48C","font":{"color":"#000000"},"groupName":"disorder","shape":"triangle"}
+              },
+                "edgeGroups":{
+              "GENETIC_ASSOCIATION":{"type":"GENETIC_ASSOCIATION", "groupName":"mQTL","color":"#A9A9A9","dashes":false,"arrowStrikethrough":false},
+              "GENETIC_TRAIT_ASSOCIATION":{"type":"GENETIC_TRAIT_ASSOCIATION","groupName":"mQTL","color":"#b4cadb33","dashes":false,"arrowStrikethrough":false},
+              "COABUNDANCE":{"type":"COABUNDANCE","groupName":"coabundance","color":"#5a735a","dashes":false,"arrowStrikethrough":false}, 
+              "METABOLIC_ASSOCIATION":{"type":"METABOLIC_ASSOCIATION","groupName":"traitQTL/mWAS","color":"#b4cadb33","dashes":false,"arrowStrikethrough":false},
+              "COREGULATION":{"type":"COREGULATION","groupName":"coregulation","color":"#1db81d","dashes":false,"arrowStrikethrough":false},
+              "PARTIAL_CORRELATION":{"type":"PARTIAL_CORRELATION","groupName":"partial correlation","color":"#FFC31E","dashes":false,"arrowStrikethrough":false},
+              "COEXPRESSION":{"type":"COEXPRESSION","groupName":"coexpression","color":"#82B81D","dashes":false,"arrowStrikethrough":false}},
+              "identifier":"symbol","title":"Drugst.one network","sidebarPos":"right","showOverview":true,"nodeShadow":false,"edgeShadow":false,"showLegend":true,
+              "showFooter":true, "showSimpleAnalysis":true,"showAdvAnalysis":true,"showSelection":true,
+              "autofillEdges":false,"physicsOn":true}'
+   network='{"nodes": [{"type": "gene", "id": "ZNF235", "group": "proteinCoding", "shape": "circle", "label": "ZNF235", "x": 45.1427, "y": 183.494915, "value": 43}, {"type": "gene", "color": {"background": "#116466", "border": "#000000"}, "font": {"color": "#000000"}, "border_width": 2, "shape": "square", "id": "CEACAM16", "border_width_selected": 0, "shadow": false, "group": "proteinCoding", "label": "CEACAM16", "x": -257.39927, "y": 500, "value": 39, "scaling.min": 2, "scaling.max": 54, "physics": false}]}'>
+</drugst-one>
 </div>
 
 <!--<div >-->
-- 
GitLab