From b444945dd13a8aedd3465fc0092c47964b76f467 Mon Sep 17 00:00:00 2001
From: Michael Hartung <michi@Michaels-MacBook-Pro.local>
Date: Mon, 12 Jul 2021 19:44:58 +0200
Subject: [PATCH] fix dashed legend when colored background; node analysis
 style half fixed; default nodes style huge somehwoe

---
 .../analysis-panel.component.ts               | 77 ++++++++-----------
 .../network-legend.component.scss             |  1 +
 src/app/config.ts                             | 10 +--
 src/app/interfaces.ts                         |  1 +
 src/app/main-network.ts                       | 14 ----
 src/app/network-settings.ts                   |  5 +-
 .../explorer-page.component.html              |  9 ++-
 .../explorer-page/explorer-page.component.ts  | 46 +++++++----
 src/index.html                                |  4 +-
 src/styles.scss                               |  7 +-
 10 files changed, 85 insertions(+), 89 deletions(-)

diff --git a/src/app/components/analysis-panel/analysis-panel.component.ts b/src/app/components/analysis-panel/analysis-panel.component.ts
index 164b6a36..58746d63 100644
--- a/src/app/components/analysis-panel/analysis-panel.component.ts
+++ b/src/app/components/analysis-panel/analysis-panel.component.ts
@@ -214,10 +214,11 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
           if (nodeIds.length > 0) {
             const nodeId = nodeIds[0];
             const node = this.nodeData.nodes.get(nodeId);
-            if (node.nodeType === 'drug') {
+            console.log(node)
+            if (node.nodeType === 'drug' || node.netexId === undefined || !node.netexId.startsWith('p')) {
               return;
             }
-            const wrapper = node.wrapper;
+            const wrapper = getWrapperFromNode(node);
             if (this.analysis.inSelection(wrapper)) {
               this.analysis.removeItems([wrapper]);
               this.analysis.getCount();
@@ -231,17 +232,20 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
         this.network.on('click', (properties) => {
           const selectedNodes = this.nodeData.nodes.get(properties.nodes);
           if (selectedNodes.length > 0) {
-            const selectedNode = selectedNodes[0];
-            const wrapper = selectedNode.wrapper;
-            this.showDetailsChange.emit(wrapper);
+            this.showDetailsChange.emit(getWrapperFromNode(selectedNodes[0]));
           } else {
             this.showDetailsChange.emit(null);
           }
         });
 
         this.analysis.subscribeList((items, selected) => {
+          // return if analysis panel is closed or no nodes are loaded
+          if (!this.token) {
+            return;
+          }
+
           if (selected !== null) {
-            const updatedNodes = [];
+            const updatedNodes: Node[] = [];
             for (const item of items) {
               const node = this.nodeData.nodes.get(item.id);
               if (!node) {
@@ -250,11 +254,14 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
               const pos = this.network.getPositions([item.id]);
               node.x = pos[item.id].x;
               node.y = pos[item.id].y;
-              // Object.assign(node, NetworkSettings.getNodeStyle(
-              //   node.wrapper.type,
-              //   node.isSeed,
-              //   selected));
-              updatedNodes.push(node);
+              const nodeStyled = NetworkSettings.getNodeStyle(
+                node,
+                this.myConfig,
+                false,
+                selected,
+                1.0
+                )
+              updatedNodes.push(nodeStyled);
             }
             this.nodeData.nodes.update(updatedNodes);
 
@@ -276,21 +283,20 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
           } else {
             const updatedNodes = [];
             this.nodeData.nodes.forEach((node) => {
-              const nodeSelected = this.analysis.idInSelection(node.id);
               let drugType;
               let drugInTrial;
               if (node.wrapper.data.netexId && node.wrapper.data.netexId.startswith('d')) {
                 drugType = node.wrapper.data.status;
                 drugInTrial = node.wrapper.data.inTrial;
               }
-              // Object.assign(node, NetworkSettings.getNodeStyle(
-              //   node.wrapper.type,
-              //   node.isSeed,
-              //   nodeSelected,
-              //   drugType,
-              //   drugInTrial,
-              //   node.gradient));
-              updatedNodes.push(node);
+              const nodeStyled = NetworkSettings.getNodeStyle(
+                node,
+                this.myConfig,
+                false,
+                selected,
+                1.0
+                )
+              updatedNodes.push(nodeStyled);
             });
             this.nodeData.nodes.update(updatedNodes);
 
@@ -426,6 +432,8 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
 
     // add drugGroup and foundNodesGroup for added nodes
     // these groups can be overwritten by the user
+    console.log("result")
+    console.log(result)
 
     const nodes = [];
     const edges = [];
@@ -455,7 +463,11 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
         // node is custom input from user, could not be mapped to backend protein
         wrappers[node] = getWrapperFromCustom(details[node]);
       }
-      nodes.push(this.mapNode(config, wrappers[node], isSeed[node], scores[node]));
+      // IMPORTANT we set seeds to "selected" and not to seeds. The user should be inspired to run 
+      // further analysis and the button function can be used to highlight seeds
+      // option to use details[node] as gradient, but sccores are very small
+      console.log(details[node])
+      nodes.push(NetworkSettings.getNodeStyle(wrappers[node].data as Node, config, false, isSeed[node], 1))
     }
     for (const edge of network.edges) {
       edges.push(this.mapEdge(edge, this.inferEdgeGroup(edge), wrappers));
@@ -466,29 +478,6 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
     };
   }
 
-  /**
-   * maps node object returned from backend to frontend node, i.e. input to vis.js
-   * @param config
-   * @param wrapper
-   * @param isSeed
-   * @param score
-   * @returns
-   */
-  private mapNode(config: IConfig, wrapper: Wrapper, isSeed?: boolean, score?: number): any {
-    // override group is node is seed
-    // TODO Move this to extra function
-    // wrapper.data.group = isSeed ? 'seedNode' : wrapper.data.group;
-    const node = JSON.parse(JSON.stringify(config.nodeGroups[wrapper.data.group]));
-    node.id = wrapper.id;
-    node.label = this.inferNodeLabel(config, wrapper);
-    node.isSeed = isSeed;
-    node.wrapper = wrapper;
-    if (node.image) {
-      node.shape = 'image';
-    }
-    return node;
-  }
-
   private mapEdge(edge: any, type: 'protein-protein' | 'protein-drug', wrappers?: { [key: string]: Wrapper }): any {
     let edgeColor;
     if (type === 'protein-protein') {
diff --git a/src/app/components/network-legend/network-legend.component.scss b/src/app/components/network-legend/network-legend.component.scss
index ca7cfadd..01304490 100644
--- a/src/app/components/network-legend/network-legend.component.scss
+++ b/src/app/components/network-legend/network-legend.component.scss
@@ -122,6 +122,7 @@ div.legend {
         margin: 0 auto; 
         &.dashes {
           border-top: dotted;
+          background-color: transparent;
         }
 
       }
diff --git a/src/app/config.ts b/src/app/config.ts
index 7b6e0978..ef644117 100644
--- a/src/app/config.ts
+++ b/src/app/config.ts
@@ -149,15 +149,15 @@ export const defaultConfig: IConfig = {
       // shape: 'circle',
       // type: 'seed',
       color: {
-        border: '#F8981D',
-        background: '#F8981D',
+        border: '#F1111D',
+        background: '#F1111D',
         highlight: {
-          border: '#F8981D',
-          background: '#F8981D'
+          border: '#F1111D',
+          background: '#F1111D'
         },
       },
       font: {
-        color: '#F8981D',
+        color: '#F1111D',
         size: 14
       }
     },
diff --git a/src/app/interfaces.ts b/src/app/interfaces.ts
index 4871bace..ac8dee3c 100644
--- a/src/app/interfaces.ts
+++ b/src/app/interfaces.ts
@@ -158,6 +158,7 @@ export function getWrapperFromNode(gene: Node): Wrapper {
    */
   // if node does not have property group, it was found by the analysis
   gene.group = gene.group ? gene.group : 'foundNode';
+  gene.label = gene.label ? gene.label : gene.id
   return {
     id: getNetworkId(gene),
     data: gene,
diff --git a/src/app/main-network.ts b/src/app/main-network.ts
index 147d1bff..052d040b 100644
--- a/src/app/main-network.ts
+++ b/src/app/main-network.ts
@@ -68,20 +68,6 @@ export class ProteinNetwork {
     node = merge(node, customNode)
     // label is only used for network visualization
     node.label = customNode.label ? customNode.label : customNode.id;
-    if (node.image) {
-      node.shape = 'image';
-    }
-    // if color is set as string, add detail settings
-    if (typeof node.color === 'string') {
-      node.color = {
-        border: node.color,
-        background: node.color,
-        highlight: {
-          border: node.color,
-          background: node.color
-        }
-      }
-    }
     return node;
   }
 
diff --git a/src/app/network-settings.ts b/src/app/network-settings.ts
index acdf8bb9..71b6c28b 100644
--- a/src/app/network-settings.ts
+++ b/src/app/network-settings.ts
@@ -125,8 +125,7 @@ export class NetworkSettings {
     config: IConfig,
     isSeed: boolean,
     isSelected: boolean,
-    gradient: number = 1): any {
-
+    gradient: number = 1): Node {
       // delete possible old styles
       Object.keys(defaultConfig.nodeGroups.default).forEach(e => delete node[e]);
       // set group styles
@@ -144,7 +143,9 @@ export class NetworkSettings {
         node = merge(node, config.nodeGroups.seedNode);
       } else if (isSelected) {
         // apply selected node style to node
+        console.log(node)
         node = merge(node, config.nodeGroups.selectedNode);
+        console.log(node)
       }
       // show image if image url is given
       if (node.image) {
diff --git a/src/app/pages/explorer-page/explorer-page.component.html b/src/app/pages/explorer-page/explorer-page.component.html
index 28978dcb..30c5b4ac 100644
--- a/src/app/pages/explorer-page/explorer-page.component.html
+++ b/src/app/pages/explorer-page/explorer-page.component.html
@@ -135,7 +135,7 @@
           <footer *ngIf="myConfig.showFooter" class="card-footer toolbar explorer-footer">
 
             <ng-container *ngIf="myConfig.showFooterButtonScreenshot">
-              <button (click)="toImage()" class="button is-primary is-rounded has-tooltip"
+              <button (click)="toImage()" class="button is-primary is-rounded has-tooltip explorer-footer-element"
                       data-tooltip="Take a screenshot of the current network.">
               <span class="icon">
                 <i class="fas fa-camera" aria-hidden="true"></i>
@@ -145,7 +145,7 @@
             </ng-container>
 
             <ng-container *ngIf="myConfig.showFooterButtonExpression">
-              <div class="footer-buttons dropdown is-up" [class.is-active]="expressionExpanded">
+              <div class="footer-buttons dropdown is-up explorer-footer-element" [class.is-active]="expressionExpanded">
                 <div class="dropdown-trigger">
                   <button (click)="expressionExpanded=!expressionExpanded"
                           class="button is-rounded is-primary" [class.is-outlined]="!selectedTissue"
@@ -182,17 +182,18 @@
               </div>
             </ng-container>
         
-        <app-toggle class="footer-buttons" textOn="Drugs On" textOff="Off"
+        <app-toggle class="footer-buttons explorer-footer-element" textOn="Drugs On" textOff="Off"
             tooltipOn="Display adjacent drugs ON."
             tooltipOff="Display adjacent drugs OFF."
             [smallStyle]="smallStyle"
             [value]="adjacentDrugs" (valueChange)="updateAdjacentDrugs($event)"></app-toggle>
 
-        <app-toggle class="footer-buttons" textOn="Animation On" textOff="Off"
+        <app-toggle class="footer-buttons explorer-footer-element" textOn="Animation On" textOff="Off"
                     tooltipOn="Enable the network animation."
                     tooltipOff="Disable the network animation and freeze nodes."
                     [smallStyle]="smallStyle"
                     [value]="physicsEnabled" (valueChange)="updatePhysicsEnabled($event)"></app-toggle>
+
         </footer>
       </div>
     </div>
diff --git a/src/app/pages/explorer-page/explorer-page.component.ts b/src/app/pages/explorer-page/explorer-page.component.ts
index 964ac8d1..3f5d7760 100644
--- a/src/app/pages/explorer-page/explorer-page.component.ts
+++ b/src/app/pages/explorer-page/explorer-page.component.ts
@@ -184,7 +184,8 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
     this.showDetails = false;
 
     this.analysis.subscribeList((items, selected) => {
-      if (!this.nodeData.nodes) {
+      // return if analysis panel is open or no nodes are loaded
+      if (this.selectedAnalysisToken || !this.nodeData.nodes) {
         return;
       }
       if (selected !== null) {
@@ -201,7 +202,6 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
           const pos = this.networkInternal.getPositions([wrapper.id]);
           node.x = pos[wrapper.id].x;
           node.y = pos[wrapper.id].y;
-          console.log('before styling')
           const nodeStyled = NetworkSettings.getNodeStyle(
             node,
             this.myConfig,
@@ -209,7 +209,6 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
             selected,
             1.0
             )
-          console.log('after styling')
           nodeStyled.x = pos[wrapper.id].x;
           nodeStyled.y = pos[wrapper.id].y;
           updatedNodes.push(nodeStyled);
@@ -218,7 +217,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
       } else {
         const updatedNodes = [];
         this.nodeData.nodes.forEach((node) => {
-          const nodeSelected = this.analysis.idInSelection(node.id);
+          // const nodeSelected = this.analysis.idInSelection(node.id);
           // if (node.group == 'default') {
           //   Object.assign(node, this.myConfig.nodeGroups.default);
           // } else {
@@ -348,11 +347,11 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
       if (nodeIds.length > 0) {
         const nodeId = nodeIds[0];
         const node = this.nodeData.nodes.get(nodeId);
-        const wrapper = getWrapperFromNode(node);
-        if (wrapper.data.netexId === undefined || !wrapper.data.netexId.startsWith('p')) {
+        if (node.netexId === undefined || !node.netexId.startsWith('p')) {
           // skip if node is not a protein mapped to backend
           return;
         }
+        const wrapper = getWrapperFromNode(node);
         if (this.analysis.inSelection(node)) {
           this.analysis.removeItems([wrapper]);
         } else {
@@ -483,17 +482,32 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
       if (!group.borderWidthSelected) {
         group.borderWidthSelected = 0;
       }
-      // color needs to be hexacode to calculate gradient, group.color might not be set for seed and selected group
-      if (!group.color.startsWith('#')) {
-        // color is either rgba, rgb or string like "red"
-        if (group.color.startsWith('rgba')) {
-          group.color = rgbaToHex(group.color).slice(0, 7)
-        } else if (group.color.startsWith('rgb')) {
-          group.color = rgbToHex(group.color)
-        } else (
-          group.color = standardize_color(group.color)
-        )
+      // if color is set as string, add detail settings
+      if (typeof group.color === 'string') {
+        group.color = {
+          border: group.color,
+          background: group.color,
+          highlight: {
+            border: group.color,
+            background: group.color
+          }
+        }
       }
+      // if image is given, set node shape to image
+      if (group.image) {
+        group.shape = 'image';
+      }
+      // color needs to be hexacode to calculate gradient, group.color might not be set for seed and selected group
+      // if (!group.color.startsWith('#')) {
+      //   // color is either rgba, rgb or string like "red"
+      //   if (group.color.startsWith('rgba')) {
+      //     group.color = rgbaToHex(group.color).slice(0, 7)
+      //   } else if (group.color.startsWith('rgb')) {
+      //     group.color = rgbToHex(group.color)
+      //   } else (
+      //     group.color = standardize_color(group.color)
+      //   )
+      // }
     });
 
     // make sure that return-groups (seeds, drugs, found nodes) are set
diff --git a/src/index.html b/src/index.html
index 5225bf72..87b43fc7 100644
--- a/src/index.html
+++ b/src/index.html
@@ -36,13 +36,13 @@
   <network-expander id="netexp1"
                     config='{
                       "nodeGroups": {"selectedNode": {"font": {"size": "18"} }, "0.5": {"font": "18px verdana blue", "type": "0.5er Instanz", "color": "green", "groupName": "0.5", "shape": "hexagon"}, "patientgroup": {"type": "Patient", "detailShowLabel": "true", "color": "#632345", "groupName": "patient group", "shape": "dot", "size": "50"}, "pugGroup": {"type": "woof woof", "color": "grey", "groupName": "Pug Group", "shape": "triangle", "image": "https://static.raymondcamden.com/images/2016/11/pug.png"}},
-                      "edgeGroups": {"dashes": {"color": "black", "groupName": "dashes Group", "dashes": [1, 2]}, "notdashes": {"color": "black", "groupName": "not dashes Group"}},
+                      "edgeGroups": {"xxx": {"color": "black", "groupName": "xxx Group", "dashes": [1, 2]}, "notdashes": {"color": "black", "groupName": "not dashes Group"}},
                       "identifier": "symbol"
                     }'
                     network='{
                       "nodes": [{"id": "MYC", "label": "node w/o group"}, {"id": "TP53", "group": "0.5"}, {"id": "C5", "group": "pugGroup"}, {"id": "Patient No. 5", "group": "patientgroup"}, {"label": "PTEN", "id": "PTEN", "group": 0.5, "value":"5"}],
                       "edges": [
-                      {"from": "TP53","to": "C5","group": "dashes", "label": "this is a label", "title": "this is a title"},
+                      {"from": "TP53","to": "C5","group": "xxx", "label": "this is a label", "title": "this is a title"},
                       {"from": "Patient No. 5","to": "C5","label": "w/o group"}
                       ]
                     }'
diff --git a/src/styles.scss b/src/styles.scss
index 46417e24..8a4898db 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -18,10 +18,13 @@
 }
 
 .explorer-footer {
-  //position: absolute;
-  //overflow: auto;
+  position: absolute;
+  // overflow: auto;
   //width: $main-width;
   bottom: 0;
+  &-element {
+    position: relative;
+  } 
 }
 
 nav.navbar {
-- 
GitLab