geotheory
geotheory

Reputation: 23650

Filtering graph by connectivity to a specific node in cytoscape.js

New to Cytoscape. I have a graph with dominant main network and some smaller networks unconnected to the main one that I want to remove. Looking through the documentation I can't see an obvious solution to this. I'm guessing maybe a custom approach is required that loops through all nodes, checks their graph distance from the most central node in the main cluster, and if this distance is undefined remove that node and all others it does connect to. But keen to get a steer from others with more experience with the library. Any advice is much appreciated. I note this unanswered but related question.

Here is an example graph. Though I can't get working on jsfiddle here is working version:

<!DOCTYPE>
<html>
  <head>
    <title>cytoscape-dagre.js demo</title>

    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">

    <script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/dagre.js"></script>
    <script src="cytoscape-dagre.js"></script>

    <style>
      #cy {
        width: 100%;
        height: 100%;
        position: absolute;
        left: 0;
        top: 0;
        z-index: 999;
      }
    </style>

    <script>
      window.addEventListener('DOMContentLoaded', function(){

        var cy = window.cy = cytoscape({
          container: document.getElementById('cy'),

          boxSelectionEnabled: false,
          autounselectify: true,

          layout: {
            name: 'dagre'
          },

          style: [
            {
              selector: 'node',
              style: {
                'background-color': '#11479e'
              }
            },

            {
              selector: 'edge',
              style: {
                'width': 4,
                'target-arrow-shape': 'triangle',
                'line-color': '#9dbaea',
                'target-arrow-color': '#9dbaea',
                'curve-style': 'bezier'
              }
            }
          ],

          elements: {
            nodes: [
              { data: { id: 'n0' } },
              { data: { id: 'n1' } },
              { data: { id: 'n2' } },
              { data: { id: 'n3' } },
              { data: { id: 'n4' } },
              { data: { id: 'n5' } },
              { data: { id: 'n6' } },
              { data: { id: 'n7' } },
              { data: { id: 'n8' } },
              { data: { id: 'n9' } },
              { data: { id: 'n10' } },
              { data: { id: 'n11' } },
              { data: { id: 'n12' } },
              { data: { id: 'n13' } },
              { data: { id: 'n14' } },
              { data: { id: 'n15' } },
              { data: { id: 'n16' } }
            ],
            edges: [
              { data: { source: 'n0', target: 'n1' } },
              { data: { source: 'n1', target: 'n2' } },
              { data: { source: 'n1', target: 'n3' } },
              { data: { source: 'n4', target: 'n5' } },
              { data: { source: 'n4', target: 'n6' } },
              { data: { source: 'n6', target: 'n7' } },
              { data: { source: 'n6', target: 'n8' } },
              { data: { source: 'n8', target: 'n9' } },
              { data: { source: 'n8', target: 'n10' } },
              { data: { source: 'n11', target: 'n12' } },
              { data: { source: 'n12', target: 'n13' } },
              { data: { source: 'n13', target: 'n14' } },
              { data: { source: 'n13', target: 'n15' } },
            ]
          }
        });

      });
    </script>
  </head>

  <body>
    <h1>cytoscape-dagre demo</h1>

    <div id="cy"></div>

  </body>
</html>

Upvotes: 4

Views: 2055

Answers (1)

Stephan T.
Stephan T.

Reputation: 6074

You can do this with the filtering methods provided in the docs, if you find some method better suited for this problem, just fiddle around with them until you get the right result. The important part here is the .union() and the .not() method. You can use these to:

  • traverse the graph in a controlled way, saving the important nodes on the way
  • and then filter the collection to fit your needs

You mentioned not being able to get the jsfiddle to work, you can test the code below in here

var cy = (window.cy = cytoscape({
  container: document.getElementById("cy"),

  style: [{
      selector: "node",
      css: {
        content: "data(id)",
        "text-valign": "center",
        "text-halign": "center",
        height: "60px",
        width: "60px",
        "border-color": "black",
        "border-opacity": "1",
        "border-width": "10px"
      }
    },
    {
      selector: "edge",
      css: {
        "target-arrow-shape": "triangle"
      }
    }
  ],

  elements: {
    nodes: [{
        data: {
          id: "n0"
        }
      },
      {
        data: {
          id: "n1"
        }
      },
      {
        data: {
          id: "n2"
        }
      },
      {
        data: {
          id: "n3"
        }
      },
      {
        data: {
          id: "n4"
        }
      },
      {
        data: {
          id: "n5"
        }
      },
      {
        data: {
          id: "n6"
        }
      },
      {
        data: {
          id: "n7"
        }
      },
      {
        data: {
          id: "n8"
        }
      },
      {
        data: {
          id: "n9"
        }
      },
      {
        data: {
          id: "n10"
        }
      },
      {
        data: {
          id: "n11"
        }
      },
      {
        data: {
          id: "n12"
        }
      },
      {
        data: {
          id: "n13"
        }
      },
      {
        data: {
          id: "n14"
        }
      },
      {
        data: {
          id: "n15"
        }
      },
      {
        data: {
          id: "n16"
        }
      }
    ],
    edges: [{
        data: {
          source: "n0",
          target: "n1"
        }
      },
      {
        data: {
          source: "n1",
          target: "n2"
        }
      },
      {
        data: {
          source: "n1",
          target: "n3"
        }
      },
      {
        data: {
          source: "n4",
          target: "n5"
        }
      },
      {
        data: {
          source: "n4",
          target: "n6"
        }
      },
      {
        data: {
          source: "n6",
          target: "n7"
        }
      },
      {
        data: {
          source: "n6",
          target: "n8"
        }
      },
      {
        data: {
          source: "n8",
          target: "n9"
        }
      },
      {
        data: {
          source: "n8",
          target: "n10"
        }
      },
      {
        data: {
          source: "n11",
          target: "n12"
        }
      },
      {
        data: {
          source: "n12",
          target: "n13"
        }
      },
      {
        data: {
          source: "n13",
          target: "n14"
        }
      },
      {
        data: {
          source: "n13",
          target: "n15"
        }
      }
    ]
  },

  layout: {
    name: "dagre",
    padding: 5
  }
}));


cy.unbind('click')
cy.bind('click', 'node', function(event) {
  // .union() takes two collections and adds both together without duplicates
  var connected = event.target
  connected = connected.union(event.target.predecessors())
  connected = connected.union(connected.successors())
  // in one line: 
  // event.target.union(event.target.predecessors().union(event.target.successors()))

  // .not() filters out whatever is not specified in connected, e.g. every other node/edge not present in connected
  var notConnected = cy.elements().not(connected)

  // if you want, you can later add the saved elements again
  var saved = cy.remove(notConnected)
});
body {
  font: 14px helvetica neue, helvetica, arial, sans-serif;
}

#cy {
  height: 100%;
  width: 100%;
  position: absolute;
  left: 0;
  top: 0;
  float: left;
}
<html>

<head>
  <script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
  <script src="https://unpkg.com/[email protected]/dist/dagre.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/cytoscape-dagre.min.js"></script>
</head>

<body>
  <div id="cy"></div>
</body>

</html>

Upvotes: 6

Related Questions