Graph database Analysis of the Steam Network
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
5.8 KiB

  1. sigma.plugins.filter
  2. ==================
  3. Plugin developed by [Sébastien Heymann](sheymann) for [Linkurious](https://github.com/Linkurious).
  4. ---
  5. ## General
  6. This plugin filters nodes and edges in a fancy manner:
  7. - Define your own filters on nodes and edges using the `nodesBy` and `edgesBy` methods, or execute more complex filters using the `neighborsOf` method.
  8. - Register multiple filters before applying them anytime at once.
  9. - Undo any filter while preserving the execution order.
  10. - Chain all methods for concise style.
  11. See the following [example code](../../examples/filters.html) and [unit tests](../../test/unit.plugins.filter.js) for full usage.
  12. To use, include all .js files under this folder. Then initialize it as follows:
  13. ````javascript
  14. var filter = new sigma.plugins.filter(sigInst);
  15. ````
  16. ## Predicates
  17. Predicates are truth tests (i.e. functions which return a boolean) on a single node or a single edge. They return true if the element should be visible. For instance:
  18. ````javascript
  19. // Only edges of size above one should be visible:
  20. function(e) {
  21. return e.size > 1;
  22. }
  23. ````
  24. In this example, notice that if the size attribute is undefined, the edge will be hidden. If you still want to display edges with no size attribute defined, you have to modify the predicate a bit:
  25. ````javascript
  26. // Only edges of size above one should be visible:
  27. function(e) {
  28. return e.size === undefined || e.size > 1;
  29. }
  30. ````
  31. Predicates are applied by predicate processors.
  32. ## Predicate processors
  33. Predicate processors are functions which wrap one predicate and apply it to the graph. Three predicate processors are available:
  34. - `nodesBy`
  35. - `edgesBy`
  36. - `neighborsOf`
  37. For each node of the graph, the `nodesBy` processor sets the attribute `hidden` to false if the predicate is true for the node. It also sets the `hidden` attribute of edges to true if one of the edge's extremities is hidden. For instance:
  38. ````javascript
  39. // Only connected nodes (i.e. nodes of positive degree) should be visible:
  40. filter.nodesBy(function(n) {
  41. return this.degree(n.id) > 0;
  42. }, 'non-isolates');
  43. ````
  44. For each edge of the graph, the `edgesBy` processor sets the attribute `hidden` to false if the predicate is true for the edge. For instance:
  45. ````javascript
  46. // Only edges of size above one should be visible:
  47. filter.edgesBy(function(e) {
  48. return e.size > 1;
  49. }, 'edge-size-above-one');
  50. ````
  51. For each neighbor node of a specified node, the `neighborsOf` processor sets the attribute `hidden` to true if it is not directly connected to the node. It also sets the `hidden` attribute of edges to true if one of the edge's extremities is hidden. For instance:
  52. ````javascript
  53. // Only neighbors of the node 'n0' should be visible:
  54. filter.neighborsOf('n0');
  55. ````
  56. Processors instanciated with a predicate are called filters. **Filters are not applied until the `apply` method is called.**
  57. ## Filters chain
  58. Combining filters is easy! Declare one filter after another, then call the `apply` method to execute them on the graph in that order. For instance:
  59. ````javascript
  60. // graph = {
  61. // nodes: [{id:'n0'}, {id:'n1'}, {id:'n2'}, {id:'n3'}],
  62. // edges: [
  63. // {id:'e0', source:'n0', target:'n1', size:1},
  64. // {id:'e1', source:'n1', target:'n2', size:0.5},
  65. // {id:'e2', source:'n1', target:'n2'}]
  66. // }
  67. filter
  68. .nodesBy(function(n) {
  69. return this.degree(n.id) > 0;
  70. })
  71. .edgesBy(function(e) {
  72. return e.size >= 1;
  73. })
  74. .apply();
  75. // n3.hidden == true
  76. // e1.hidden == true
  77. // e2.hidden == true
  78. ````
  79. Combined filters work like if there was an 'AND' operator between them. Be careful not to create mutually exclusive filters, for instance:
  80. ````javascript
  81. filter
  82. .nodesBy(function(n) {
  83. return n.attributes.animal === 'pony';
  84. })
  85. .nodesBy(function(n) {
  86. return n.attributes.animal !== 'pony';
  87. })
  88. .apply();
  89. // all nodes are hidden
  90. ````
  91. Filters are internally stored in an array called the `chain`.
  92. ## Undo filters
  93. Undoing filters means to remove them from the `chain`. Filters can be undone easily. Choose which filter(s) to undo, or undo all of them at once.
  94. Filters can be associated with keys at declaration, where keys are any string you give. For instance, the following filter has the key *node-animal*:
  95. ````javascript
  96. filter.nodesBy(function(n) {
  97. return n.attributes.animal === 'pony';
  98. }, 'node-animal');
  99. ````
  100. Manually undo this filter as follows:
  101. ````javascript
  102. filter
  103. .undo('node-animal')
  104. .apply(); // we want it applied now
  105. ````
  106. Multiple filters can be undone at once, for instance:
  107. ````javascript
  108. filter.undo('node-animal', 'edge-size', 'high-node-degree');
  109. // don't forget to call `apply()` anytime!
  110. ````
  111. Alternative syntax:
  112. ````javascript
  113. var a = ['node-animal', 'edge-size', 'high-node-degree'];
  114. filter.undo(a);
  115. // don't forget to call `apply()` anytime!
  116. ````
  117. Finally, undo all filters (with or without keys) as follows:
  118. ````javascript
  119. filter.undo();
  120. // don't forget to call `apply()` anytime!
  121. ````
  122. Warning: you can't declare two filters with the same key, or it will throw an exception.
  123. ## Export the chain
  124. The exported chain is an array of objects. Each object represents a filter by a triplet *(?key, processor, predicate)*. The processor value is the internal name of the processor: `filter.processors.nodes`, `filter.processors.edges`, `filter.processors.neighbors`. The predicate value is a copy of the predicate function. Dump the `chain` using the `export` method as follows:
  125. ````javascript
  126. var chain = filter.export();
  127. // chain == [
  128. // {
  129. // key: '...',
  130. // processor: '...',
  131. // predicate: function() {...}
  132. // }, ...
  133. // ]
  134. ````
  135. ## Import a chain
  136. You can load a filters chain using the `import` method:
  137. ````javascript
  138. var chain = [
  139. {
  140. key: 'my-filter',
  141. predicate: function(n) { return this.degree(n.id) > 0; },
  142. processor: 'filter.processors.nodes'
  143. }
  144. ];
  145. filter
  146. .import(chain)
  147. .apply();
  148. ````