From 68563156d8dce6f17c24d5c5f734d4a85e1aea4f Mon Sep 17 00:00:00 2001
From: Julian Matschinske <julian@vyze.ai>
Date: Wed, 16 Dec 2020 17:43:03 +0100
Subject: [PATCH] Add custom groups

---
 Dockerfile.dev                                |  2 +-
 src/app/analysis.service.ts                   |  8 +-
 .../analysis-panel.component.ts               | 22 +++---
 .../info-tile/info-tile.component.html        | 40 +---------
 .../query-tile/query-tile.component.ts        |  7 +-
 src/app/config.ts                             | 29 +++++++
 .../add-expressed-proteins.component.ts       |  4 +-
 .../custom-proteins.component.ts              |  4 +-
 src/app/interfaces.ts                         | 25 +++---
 src/app/main-network.ts                       |  8 +-
 .../explorer-page/explorer-page.component.ts  | 77 +++++++++----------
 src/index.html                                | 31 ++++----
 12 files changed, 126 insertions(+), 131 deletions(-)

diff --git a/Dockerfile.dev b/Dockerfile.dev
index b7be260b..9a856703 100644
--- a/Dockerfile.dev
+++ b/Dockerfile.dev
@@ -23,7 +23,7 @@ RUN cp -r website/* /usr/share/nginx/html/
 RUN mkdir /usr/share/nginx/html/lib
 RUN cp dist/covid19/bundle-es2015.js /usr/share/nginx/html/lib/
 RUN cp dist/covid19/bundle-es5.js /usr/share/nginx/html/lib/
-RUN cp dist/covid19/styles.scss /usr/share/nginx/html/lib/
+RUN cp dist/covid19/styles.css /usr/share/nginx/html/lib/
 
 COPY nginx/default.conf /etc/nginx/conf.d/
 COPY nginx/htpasswd /etc/nginx/htpasswd
diff --git a/src/app/analysis.service.ts b/src/app/analysis.service.ts
index 23ce8084..3e679780 100644
--- a/src/app/analysis.service.ts
+++ b/src/app/analysis.service.ts
@@ -1,4 +1,4 @@
-import {Wrapper, Task, getWrapperFromProtein, Protein, Dataset, Tissue} from './interfaces';
+import {Wrapper, Task, getWrapperFromProtein, Node, Dataset, Tissue} from './interfaces';
 import {Subject} from 'rxjs';
 import {HttpClient} from '@angular/common/http';
 import {environment} from '../environments/environment';
@@ -173,7 +173,7 @@ export class AnalysisService {
     this.selectListSubject.next({items: newSelection, selected: null});
   }
 
-  public addExpressedHostProteins(nodes, proteins: Protein[], threshold: number): number {
+  public addExpressedHostProteins(nodes, proteins: Node[], threshold: number): number {
     const items: Wrapper[] = [];
     const visibleIds = new Set<string>(nodes.getIds());
     for (const protein of proteins) {
@@ -188,7 +188,7 @@ export class AnalysisService {
     return items.length;
   }
 
-  public addVisibleHostProteins(nodes, proteins: Protein[]): number {
+  public addVisibleHostProteins(nodes, proteins: Node[]): number {
     const items: Wrapper[] = [];
     const visibleIds = new Set<string>(nodes.getIds());
     for (const protein of proteins) {
@@ -224,7 +224,7 @@ export class AnalysisService {
     return this.selectedItems.has(wrapper.nodeId);
   }
 
-  proteinInSelection(protein: Protein): boolean {
+  proteinInSelection(protein: Node): boolean {
     return this.inSelection(getWrapperFromProtein(protein));
   }
 
diff --git a/src/app/components/analysis-panel/analysis-panel.component.ts b/src/app/components/analysis-panel/analysis-panel.component.ts
index ca204933..76e741d2 100644
--- a/src/app/components/analysis-panel/analysis-panel.component.ts
+++ b/src/app/components/analysis-panel/analysis-panel.component.ts
@@ -13,7 +13,7 @@ import {HttpClient, HttpErrorResponse} from '@angular/common/http';
 import {environment} from '../../../environments/environment';
 import {AnalysisService, algorithmNames} from '../../analysis.service';
 import {
-  Protein,
+  Node,
   Task,
   Drug,
   Wrapper,
@@ -57,7 +57,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
 
   @Output() tokenChange = new EventEmitter<string | null>();
   @Output() showDetailsChange = new EventEmitter<Wrapper>();
-  @Output() visibleItems = new EventEmitter<[any[], [Protein[], Tissue]]>();
+  @Output() visibleItems = new EventEmitter<[any[], [Node[], Tissue]]>();
 
   public task: Task | null = null;
 
@@ -73,8 +73,8 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
   public effects: any;
 
   public tableDrugs: Array<Drug & Scored & Baited> = [];
-  public tableProteins: Array<Protein & Scored & Seeded & Baited> = [];
-  public tableSelectedProteins: Array<Protein & Scored & Seeded & Baited> = [];
+  public tableProteins: Array<Node & Scored & Seeded & Baited> = [];
+  public tableSelectedProteins: Array<Node & Scored & Seeded & Baited> = [];
   public tableViralProteins: Array<Scored & Seeded> = [];
   public tableSelectedViralProteins: Array<Scored & Seeded> = [];
   public tableNormalize = false;
@@ -171,7 +171,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
             this.tableSelectedProteins = [];
             this.tableProteins.forEach((r) => {
               r.rawScore = r.score;
-              r.isSeed = isSeed[r.proteinAc];
+              r.isSeed = isSeed[r.id];
               r.closestViralProteins = (r.closestViralProteins as any).split(',');
               if (this.analysis.proteinInSelection(r)) {
                 this.tableSelectedProteins.push(r);
@@ -410,17 +410,17 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
     };
   }
 
-  private mapNode(nodeType: WrapperType, details: Protein | Drug, isSeed?: boolean, score?: number): any {
+  private mapNode(nodeType: WrapperType, details: Node | Drug, isSeed?: boolean, score?: number): any {
     let nodeLabel;
     let wrapper: Wrapper;
     let drugType;
     let drugInTrial;
     if (nodeType === 'protein') {
-      const protein = details as Protein;
+      const protein = details as Node;
       wrapper = getWrapperFromProtein(protein);
       nodeLabel = protein.name;
       if (!protein.name) {
-        nodeLabel = protein.proteinAc;
+        nodeLabel = protein.id;
       }
     } else if (nodeType === 'drug') {
       const drug = details as Drug;
@@ -596,14 +596,14 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
         node.wrapper = item;
         node.gradient = 1.0;
         protein.expressionLevel = undefined;
-        (node.wrapper.data as Protein).expressionLevel = undefined;
+        (node.wrapper.data as Node).expressionLevel = undefined;
         updatedNodes.push(node);
       }
       this.nodeData.nodes.update(updatedNodes);
     } else {
       this.selectedTissue = tissue;
       const minExp = 0.3;
-      this.http.get<Array<{ protein: Protein, level: number }>>(
+      this.http.get<Array<{ protein: Node, level: number }>>(
         `${environment.backend}tissue_expression/?tissue=${tissue.id}&token=${this.token}`)
         .subscribe((levels) => {
           const updatedNodes = [];
@@ -629,7 +629,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
             node.wrapper = item;
             node.gradient = gradient;
             this.proteins.find(prot => getProteinNodeId(prot) === item.nodeId).expressionLevel = lvl.level;
-            (node.wrapper.data as Protein).expressionLevel = lvl.level;
+            (node.wrapper.data as Node).expressionLevel = lvl.level;
             updatedNodes.push(node);
           }
           this.nodeData.nodes.update(updatedNodes);
diff --git a/src/app/components/info-tile/info-tile.component.html b/src/app/components/info-tile/info-tile.component.html
index 9d64bd44..ff2286df 100644
--- a/src/app/components/info-tile/info-tile.component.html
+++ b/src/app/components/info-tile/info-tile.component.html
@@ -1,52 +1,20 @@
 <div *ngIf="wrapper">
-  <div *ngIf="wrapper.type === 'protein'">
+  <div>
     <p>
-      <b><span>Gene Name: </span></b>
+      <b><span>Name:</span></b>
       {{ wrapper.data.name }}
-      <span class="icon is-small"><i class="fas fa-dna"></i></span>
     </p>
     <p>
-      <b><span>Uniprot AC :</span></b>
+      <b><span>Access:</span></b>
       <a href="https://www.uniprot.org/uniprot/{{ wrapper.data.proteinAc }}" target="_blank">
-        {{ wrapper.data.proteinAc }}
+        {{ wrapper.data.access }}
       </a>
     </p>
-    <p>
-      <b><span>Name: </span></b>
-      {{ wrapper.data.proteinName }}
-    </p>
     <p *ngIf="wrapper.data.expressionLevel">
       <b><span>Expression level: </span></b>
       {{ wrapper.data.expressionLevel|number }}
     </p>
   </div>
-  <div *ngIf="wrapper.type === 'drug'">
-    <p>
-      <b><span>Name: </span></b>
-      {{ wrapper.data.name }}
-      <span class="icon is-small"><i class="fas fa-capsules"></i></span>
-    </p>
-    <p>
-      <b>DrugBank ID: </b>
-      <a href="https://www.drugbank.ca/drugs/{{ wrapper.data.drugId }}" target="_blank"> {{ wrapper.data.drugId }}</a>
-    </p>
-    <p *ngIf="wrapper.data.status === 'unapproved' ">
-      <b>Status: </b> Unapproved
-      <span class="icon is-small"><i class="fas fa-search investigational"></i></span>
-    <p *ngIf="wrapper.data.status === 'approved' ">
-      <b>Status: </b> Approved
-      <span class="icon is-small"><i class="fas fa-check"></i></span>
-    </p>
-    <p *ngIf="wrapper.data.inTrial">
-      <b>In trial(s) </b> <span class="icon is-small"><i class="fas fa-check"></i></span>
-    </p>
-    <div *ngIf="wrapper.data.inTrial && wrapper.data.trialLinks.length > 0" class="list">
-      <div *ngFor="let link of wrapper.data.trialLinks" class="list-item">
-        <a [href]="link" target="_blank">{{beautify(link)}}</a>
-      </div>
-      <small class="list-item"><i>Links provided by WHO</i></small>
-    </div>
-  </div>
 
   <div class="field has-addons add-remove-toggle" *ngIf="wrapper.type !== 'drug'">
     <app-toggle [value]="analysis.inSelection(wrapper)"
diff --git a/src/app/components/query-tile/query-tile.component.ts b/src/app/components/query-tile/query-tile.component.ts
index 63997a24..effd4a12 100644
--- a/src/app/components/query-tile/query-tile.component.ts
+++ b/src/app/components/query-tile/query-tile.component.ts
@@ -1,5 +1,5 @@
 import {Component, Input, Output, EventEmitter} from '@angular/core';
-import {Protein, Wrapper} from '../../interfaces';
+import {Node, Wrapper} from '../../interfaces';
 
 @Component({
   selector: 'app-query-tile-component',
@@ -14,9 +14,8 @@ export class QueryTileComponent {
 
   querySearch(term: string, item: Wrapper) {
     term = term.toLowerCase();
-    const data = item.data as Protein;
-    return data.name.toLowerCase().indexOf(term) > -1 || data.proteinName.toLowerCase().indexOf(term) > -1 ||
-      item.type.toLowerCase().indexOf(term) > -1;
+    const data = item.data as Node;
+    return data.name.toLowerCase().indexOf(term) > -1 || item.type.toLowerCase().indexOf(term) > -1;
   }
 
   select(item) {
diff --git a/src/app/config.ts b/src/app/config.ts
index 34a5a918..6495a82b 100644
--- a/src/app/config.ts
+++ b/src/app/config.ts
@@ -1,3 +1,14 @@
+// export interface NodeGroup {
+//   fill: string;
+// }
+//
+// export interface EdgeGroup {
+//   color: string;
+// }
+
+type NodeGroup = any;
+type EdgeGroup = any;
+
 export interface IConfig {
   legendUrl: string;
   legendClass: string;
@@ -11,6 +22,8 @@ export interface IConfig {
   showTasks: boolean;
   showSelection: boolean;
   showFooter: boolean;
+  nodeGroups: { [key: string]: NodeGroup };
+  edgeGroups: { [key: string]: EdgeGroup };
 }
 
 export const defaultConfig: IConfig = {
@@ -26,4 +39,20 @@ export const defaultConfig: IConfig = {
   showSelection: true,
   showTasks: true,
   showFooter: true,
+  nodeGroups: {
+    default: {
+      color: 'white'
+    },
+    protein: {
+      color: 'red'
+    },
+    drug: {
+      color: 'green'
+    }
+  },
+  edgeGroups: {
+    default: {
+      color: 'black'
+    }
+  },
 };
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 6b9e1987..13d96d13 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
@@ -1,6 +1,6 @@
 import {Component, EventEmitter, Input, OnChanges, Output, SimpleChanges} from '@angular/core';
 import {AnalysisService} from '../../analysis.service';
-import {getWrapperFromProtein, Protein, Tissue} from '../../interfaces';
+import {getWrapperFromProtein, Node, Tissue} from '../../interfaces';
 import {environment} from '../../../environments/environment';
 import {HttpClient} from '@angular/common/http';
 
@@ -18,7 +18,7 @@ export class AddExpressedProteinsComponent implements OnChanges {
   @Input()
   public visibleNodes: Array<any> = [];
   @Input()
-  public currentViewProteins: Array<Protein> = [];
+  public currentViewProteins: Array<Node> = [];
   @Input()
   public selectedTissue: Tissue | null = null;
 
diff --git a/src/app/dialogs/custom-proteins/custom-proteins.component.ts b/src/app/dialogs/custom-proteins/custom-proteins.component.ts
index a6994260..1dd7e869 100644
--- a/src/app/dialogs/custom-proteins/custom-proteins.component.ts
+++ b/src/app/dialogs/custom-proteins/custom-proteins.component.ts
@@ -1,7 +1,7 @@
 import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
 import {HttpClient} from '@angular/common/http';
 import {environment} from '../../../environments/environment';
-import {getWrapperFromProtein, Protein, Wrapper} from '../../interfaces';
+import {getWrapperFromProtein, Node, Wrapper} from '../../interfaces';
 import {AnalysisService} from '../../analysis.service';
 
 @Component({
@@ -73,7 +73,7 @@ export class CustomProteinsComponent implements OnInit {
     const proteinItems = [];
     const items = [];
     for (const detail of details) {
-      proteinItems.push(detail as Protein);
+      proteinItems.push(detail as Node);
       items.push(getWrapperFromProtein(detail));
     }
     this.itemsFound = items;
diff --git a/src/app/interfaces.ts b/src/app/interfaces.ts
index 230bb223..e03acc01 100644
--- a/src/app/interfaces.ts
+++ b/src/app/interfaces.ts
@@ -1,10 +1,12 @@
 import {AlgorithmType, QuickAlgorithmType} from './analysis.service';
 
-export interface Protein {
+export interface Node {
   name: string;
-  proteinAc: string;
-  proteinName: string;
-  interactions?: Protein[];
+  id: string;
+  access: string;
+  group?: string;
+
+  interactions?: Node[];
   x?: number;
   y?: number;
   expressionLevel?: number;
@@ -15,9 +17,10 @@ export interface Tissue {
   name: string;
 }
 
-export interface ProteinProteinInteraction {
+export interface NodeInteraction {
   from: string;
   to: string;
+  group?: string;
 }
 
 export interface NetworkEdge {
@@ -51,15 +54,15 @@ export interface Task {
   };
 }
 
-export function getProteinNodeId(protein: Protein) {
-  return `p_${protein.proteinAc}`;
+export function getProteinNodeId(protein: Node) {
+  return `p_${protein.id}`;
 }
 
-export function getProteinBackendId(protein: Protein) {
-  return protein.proteinAc;
+export function getProteinBackendId(protein: Node) {
+  return protein.id;
 }
 
-export function getNodeIdsFromI(pvi: ProteinProteinInteraction) {
+export function getNodeIdsFromI(pvi: NodeInteraction) {
   return {
     from: `p_${pvi.from}`,
     to: `p_${pvi.to}`,
@@ -88,7 +91,7 @@ export function getDrugBackendId(drug: Drug) {
   return drug.drugId;
 }
 
-export function getWrapperFromProtein(protein: Protein): Wrapper {
+export function getWrapperFromProtein(protein: Node): Wrapper {
   return {
     backendId: getProteinBackendId(protein),
     nodeId: getProteinNodeId(protein),
diff --git a/src/app/main-network.ts b/src/app/main-network.ts
index 2217f357..27e2f203 100644
--- a/src/app/main-network.ts
+++ b/src/app/main-network.ts
@@ -1,5 +1,5 @@
 import {HttpClient} from '@angular/common/http';
-import {ProteinProteinInteraction, Protein, getProteinNodeId} from './interfaces';
+import {NodeInteraction, Node, getProteinNodeId} from './interfaces';
 
 export function getDatasetFilename(dataset: Array<[string, string]>): string {
   return `network-${JSON.stringify(dataset).replace(/[\[\]\",]/g, '')}.json`;
@@ -7,7 +7,7 @@ export function getDatasetFilename(dataset: Array<[string, string]>): string {
 
 export class ProteinNetwork {
 
-  constructor(public proteins: Protein[], public edges: ProteinProteinInteraction[]) {
+  constructor(public proteins: Node[], public edges: NodeInteraction[]) {
   }
 
   public async loadPositions(http: HttpClient, dataset: Array<[string, string]>) {
@@ -21,8 +21,8 @@ export class ProteinNetwork {
     });
   }
 
-  public getProtein(ac: string): Protein | undefined {
-    return this.proteins.find((p) => p.proteinAc === ac);
+  public getProtein(ac: string): Node | undefined {
+    return this.proteins.find((p) => p.id === ac);
   }
 
   public linkNodes() {
diff --git a/src/app/pages/explorer-page/explorer-page.component.ts b/src/app/pages/explorer-page/explorer-page.component.ts
index 66f901e6..8ac0357a 100644
--- a/src/app/pages/explorer-page/explorer-page.component.ts
+++ b/src/app/pages/explorer-page/explorer-page.component.ts
@@ -6,8 +6,8 @@ import {
   ViewChild
 } from '@angular/core';
 import {
-  ProteinProteinInteraction,
-  Protein,
+  NodeInteraction,
+  Node,
   Wrapper,
   getWrapperFromProtein,
   Tissue, getNodeIdsFromI
@@ -44,6 +44,10 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
 
     const configObj = JSON.parse(config);
     for (const key of Object.keys(configObj)) {
+      if (key === 'nodeGroups' || key === 'edgeGroups') {
+        this.myConfig[key] = {...this.myConfig[key], ...configObj[key]};
+        continue;
+      }
       this.myConfig[key] = configObj[key];
     }
   }
@@ -98,7 +102,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
 
   public currentDataset = [];
 
-  public currentViewProteins: Protein[];
+  public currentViewProteins: Node[];
   public currentViewSelectedTissue: Tissue | null = null;
   public currentViewNodes: any[];
 
@@ -133,13 +137,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
           node.y = pos[item.nodeId].y;
           node.x = pos[item.nodeId].x;
           node.y = pos[item.nodeId].y;
-          Object.assign(node, NetworkSettings.getNodeStyle(
-            node.wrapper.type,
-            true,
-            selected,
-            undefined,
-            undefined,
-            node.gradient));
+          Object.assign(node, this.myConfig.nodeGroups[node.wrapper.data.group]);
           updatedNodes.push(node);
         }
         this.nodeData.nodes.update(updatedNodes);
@@ -147,14 +145,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
         const updatedNodes = [];
         this.nodeData.nodes.forEach((node) => {
           const nodeSelected = this.analysis.idInSelection(node.id);
-          Object.assign(node, NetworkSettings.getNodeStyle(
-            node.wrapper.type,
-            true,
-            nodeSelected,
-            undefined,
-            undefined,
-            node.gradient));
-          updatedNodes.push(node);
+          Object.assign(node, this.myConfig.nodeGroups[node.wrapper.data.group]);
         });
         this.nodeData.nodes.update(updatedNodes);
       }
@@ -269,7 +260,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
     }
   }
 
-  fillQueryItems(hostProteins: Protein[]) {
+  fillQueryItems(hostProteins: Node[]) {
     this.queryItems = [];
     hostProteins.forEach((protein) => {
       this.queryItems.push(getWrapperFromProtein(protein));
@@ -297,30 +288,32 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
     });
   }
 
-  private mapHostProteinToNode(hostProtein: Protein): any {
-    const wrapper = getWrapperFromProtein(hostProtein);
-    const node = NetworkSettings.getNodeStyle('protein', true, this.analysis.inSelection(wrapper));
-    let nodeLabel = hostProtein.name;
-    if (hostProtein.name.length === 0) {
-      nodeLabel = hostProtein.proteinAc;
+  private mapCustomNode(customNode: Node): any {
+    let group = customNode.group;
+    if (typeof group === 'undefined' || typeof this.myConfig.nodeGroups[group] === 'undefined') {
+      group = 'default';
+    }
+    const node = JSON.parse(JSON.stringify(this.myConfig.nodeGroups[group]));
+    let nodeLabel = customNode.name;
+    if (customNode.name.length === 0) {
+      nodeLabel = customNode.id;
     }
     node.label = nodeLabel;
-    node.id = wrapper.nodeId;
-    node.x = hostProtein.x;
-    node.y = hostProtein.y;
-    node.wrapper = wrapper;
+    node.id = customNode.id;
+    node.x = customNode.x;
+    node.y = customNode.y;
     return node;
   }
 
-  private mapEdge(edge: ProteinProteinInteraction): any {
-    const {from, to} = getNodeIdsFromI(edge);
-    return {
-      from, to,
-      color: {
-        color: NetworkSettings.getColor('edgeHostVirus'),
-        highlight: NetworkSettings.getColor('edgeHostVirusHighlight')
-      },
-    };
+  private mapCustomEdge(customEdge: NodeInteraction): any {
+    let group = customEdge.group;
+    if (typeof group === 'undefined' || typeof this.myConfig.edgeGroups[group] === 'undefined') {
+      group = 'default';
+    }
+    const edge = JSON.parse(JSON.stringify(this.myConfig.edgeGroups[group]));
+    edge.from = customEdge.from;
+    edge.to = customEdge.to;
+    return edge;
   }
 
   private mapDataToNodes(data: ProteinNetwork): { nodes: any[], edges: any[] } {
@@ -328,11 +321,11 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
     const edges = [];
 
     for (const protein of data.proteins) {
-      nodes.push(this.mapHostProteinToNode(protein));
+      nodes.push(this.mapCustomNode(protein));
     }
 
     for (const edge of data.edges) {
-      edges.push(this.mapEdge(edge));
+      edges.push(this.mapCustomEdge(edge));
     }
 
     return {
@@ -351,7 +344,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
     });
   }
 
-  analysisWindowChanged($event: [any[], [Protein[], Tissue]]) {
+  analysisWindowChanged($event: [any[], [Node[], Tissue]]) {
     if ($event) {
       this.currentViewNodes = $event[0];
       this.currentViewProteins = $event[1][0];
@@ -409,7 +402,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
         node.wrapper = item;
         node.gradient = 1.0;
         protein.expressionLevel = undefined;
-        (node.wrapper.data as Protein).expressionLevel = undefined;
+        (node.wrapper.data as Node).expressionLevel = undefined;
         updatedNodes.push(node);
       }
       this.nodeData.nodes.update(updatedNodes);
diff --git a/src/index.html b/src/index.html
index 5fc741c8..36090d59 100644
--- a/src/index.html
+++ b/src/index.html
@@ -24,7 +24,7 @@
 <button onclick="setNetwork('netexp1')">Add proteins</button>
 
 <div>
-  <network-expander id="netexp1" config='{"legendClass": "my-legend-1", "showQuery": false}' onload="init1()" style="height: 100vh"></network-expander>
+  <network-expander id="netexp1" config='{"showQuery": false, "nodeGroups": {"default": {"color": "grey"}}, "edgeGroups":{"default": {"color": "grey"}, "custom": {"color": "red"}}}' onload="init1()" style="height: 100vh"></network-expander>
 </div>
 
 <!--
@@ -55,29 +55,32 @@
     netexp.setAttribute('network', JSON.stringify({
       nodes: [
         {
-          name: "SIRT5",
-          proteinAc: "Q9NXA8",
-          proteinName: "NAD-dependent protein deacylase sirtuin-5"
+          name: "Protein 1",
+          id: "1",
+          access: "A",
+          group: "protein"
         },
         {
-          name: "RPL36",
-          proteinAc: "Q9Y3U8",
-          proteinName: "60S ribosomal protein L36"
+          name: "Unknown type",
+          id: "2",
+          access: "B"
         },
         {
-          name: "G3BP2",
-          proteinAc: "Q9UNAA86",
-          proteinName: "Ras GTPase-activating protein-binding protein 2"
+          name: "Drug 123",
+          id: "3",
+          access: "C",
+          group: "drug"
         }
       ],
       edges: [
         {
-          from: 'Q9NXA8',
-          to: 'Q9Y3U8',
+          from: '1',
+          to: '2',
         },
         {
-          from: 'Q9Y3U8',
-          to: 'Q9UN86',
+          from: '2',
+          to: '3',
+          group: 'custom'
         }
       ]
     }));
-- 
GitLab