Simplifier
De nombreux graphiques sont pour la plupart des répétitions. Deux événements partagent quarante IP, et chaque IP coûte un nœud, une étiquette et deux bords, même si ce qui compte, c'est "ces deux événements partagent quarante IP". Un hub comporte des dizaines de feuilles qui ne relient nulle part ailleurs. Simplifier replie les nœuds qui jouent le même rôle en un seul groupe, dessiné à leur place :
const options = {
render: {
nodeTypeAccessor: (node) => node.getData().type,
},
UI: {
simplify: {
rules: [{ kind: 'neighbours', minSize: 5 }],
},
},
}Les groupes sont une vue, pas des données
graph.getNodes(), getEdges(), le tableau, les exports et l'historique des annulations voient les vrais nœuds. Un groupe est recalculé à partir d'eux chaque fois que le graphique change, et rien n'est enregistré.
Voyez-le fonctionner sur la carte Simplifiez le graphique.
Règles
UI.simplify.rules est une liste ordonnée. Chaque règle donne une clé à certains nœuds, et les nœuds partageant une clé deviennent un groupe, tant qu'il y en a au moins minSize.
- Les règles s'exécutent dans l'ordre, et chacune voit les groupes que les règles ci-dessus ont créés comme des nœuds ordinaires. Un groupe peut donc être regroupé par une règle ultérieure.
- Les règles s'exécutent après les filtres de nœuds, de sorte qu'un groupe ne conserve que ce qui les transmet : masquez trois des quarante IP et le groupe lit 37. Les couches périphériques ne changent pas de groupe ; en désactiver un ne masque que les lignes.
- Un nœud avec une note attachée et un cluster développé sont jamais groupés. Un cluster fermé se regroupe comme n’importe quel autre nœud.
- Une règle déclarée est activée à moins qu'elle ne dise
enabled: false.
Sans UI.simplify, le mode full propose les règles intégrées désactivées dans le mode ferroviaire Simplifier ; les autres modes ne fonctionnent rien. UI.simplify.enabled: false supprime la fonctionnalité.
La règle du voisin
{ kind: 'neighbours', minSize: 5, typeOf: (node) => node.getData().type }Il plie les nœuds de un type qui relient à exactement les mêmes nœuds, de la même manière autour : les mêmes nœuds pointant vers eux et les mêmes nœuds vers lesquels ils pointent. Les feuilles d'un moyeu constituent le cas le plus simple. Avec les événements A et B partageant trois TTP et chacun en ayant deux qui lui sont propres, vous obtenez trois groupes : les trois partagés entre A et B, et deux de chaque côté.
- Le type est celui de la règle
typeOf, sinonUI.simplify.typeOf, sinonrender.nodeTypeAccessor. Nœuds sans groupe de type entre eux. - Un nœud lié à rien n'est jamais groupé : un groupe a besoin de quelque chose pour s'accrocher.
- Un nœud qui gagne un lien quitte son groupe pour celui qui correspond à ses nouveaux voisins. S'il reste moins de
minSize, le groupe se dissout. - Un groupe garde son identité tout en gardant la plupart de ses membres, donc un nouveau nœud atterrissant avec les mêmes voisins rejoint le groupe existant sans le déplacer.
La règle de la chaîne
{ kind: 'chains', minSize: 5, typeOf: (node) => node.getData().type }Il plie les chaînes qui pendent d’un nœud. Un événement contenant trente fichiers, chacun avec son propre hachage, correspond à trente chaînes file > sha256 : les fichiers ne partagent aucun voisin, puisque chacun lie son propre hachage, donc la règle de voisin les laisse tranquilles. La règle de chaîne les regroupe en un groupe de fichiers liés à un groupe de hachages et dessine les trente liens entre eux sur une seule ligne.
- La tail d'un nœud est un nœud dont le seul lien vient de lui, suivi en aval tandis que chaque étape ne lie que le long de la chaîne. Un nœud lié à deux autres, une branche ou un cycle termine là la chaîne.
- Les nœuds qui ** mènent des chaînes de même forme ** se replient ensemble, lorsqu'ils partagent les mêmes autres maillons et le même type. Cinq paires isolées
domain → ipdonnent un groupe de cinq domaines liés à un groupe de cinq IP. - Chaque niveau des chaînes se replie aussi : sous le groupe de leurs têtes, ou sous une tête qui leur est propre lorsqu'elle n'a pas d'allumette.
- Les liens comptent en aval uniquement : un nœud dont le seul lien pointe vers un autre n'est pas la queue de ce nœud.
- Placé après la règle du voisin, il replie ce qui reste de cette règle. Un groupe créé par la règle du voisin peut être une queue.
Quelques liens et le noyau
{ kind: 'degree', minDegree: 2 }
{ kind: 'kcore', k: 2 }Ces règles retirent les nœuds du canevas en fonction de leur degré de liaison et les replient dans les nœuds auxquels ils sont suspendus, de sorte que le décompte reste sur le canevas :
- Peu de liens (
degree) plie les nœuds avec moins deminDegreeliens : à 2, les feuilles d'un hub deviennent un groupe sur le hub. - En dehors du noyau (
kcore) décolle les nœuds avec moins dekliens, puis recommence avec ce qui reste, jusqu'à ce que chaque nœud debout aitkliens parmi les autres. À 2, il plie les arbres entiers qui pendent du graphique, pas seulement leurs feuilles.
Les nœuds pliés qui touchent les mêmes nœuds laissés debout partagent un groupe, quels que soient leurs types, et un groupe peut contenir un seul nœud : il lit « 1 de plus » sur son ancre. Les nœuds pliés liés entre eux vont dans le même groupe, donc un chemin suspendu à un moyeu se plie avec les feuilles du moyeu. Une série de nœuds repliés ne touchant rien qui reste debout constitue un groupe à part entière, et chaque nœud lié à rien partage un groupe. Les deux paramètres vont de 1 à 10 et les liens comptent dans les deux sens.
Après la règle de voisinage, un groupe est un nœud de ces règles : ses liens sont ses lignes. Un groupe accroché seul à son ancre reste tel quel.
Communautés
{ kind: 'communities', level: 4 }Pour les graphes trop grands pour les règles ci-dessus, Communities replie des quartiers entiers : les nœuds plus densément liés les uns aux autres qu'au reste du graphe forment un seul groupe, quels que soient leurs types. On les retrouve avec l'algorithme de Leiden, le même pour le même graphique à chaque fois.
levelva de 1, fine, de nombreuses petites communautés, à 7, grossière, une poignée de grandes. En mode Simplifier, il s'agit d'un curseur, appliqué lorsque vous lâchez prise.- Les communautés se retrouvent dans un travailleur, hors de la page, et seulement à nouveau lorsque la forme du graphe change. Pendant ce temps, la carte indique Groupement… et les groupes précédents restent. Lorsqu'aucun travailleur ne peut démarrer, une politique de sécurité du contenu bloquant les travailleurs blob par exemple, le même code s'exécute sur la page ;
useWorker: falsedemande cela. - Une communauté d'un nœud reste un nœud et les nœuds annotés restent en dehors, comme pour toute règle.
- Contrairement aux autres règles intégrées, les communautés sont uniquement en mode Simplifier lorsqu'elles sont déclarées.
Atterrissages pivots
{ kind: 'landings', minSize: 2 }Ingest in a group, dans le pied de page du pivot Review, affiche les lignes sélectionnées pliées : un groupe par type, suspendu au nœud sur lequel vous avez pivoté. Quarante IP arrivent sous la forme « 40 × ip » au lieu de quarante points.
- Un groupe détient ce qu'il ingère ajouté. Un nœud qui était déjà sur le canevas reste là où il se trouvait.
- Un membre reste quel que soit le lien auquel il est lié plus tard, contrairement à la règle du voisin. Retirez-le, supprimez-le ou annulez l'ingestion pour le supprimer. Annuler dissout le groupe et refaire le ramène.
- Un type avec moins de nœuds que
minSize(2 par défaut) apparaît comme des nœuds simples. - La règle s'exécute en premier, de sorte que les règles qui suivent considèrent chaque atterrissage comme un seul nœud. Vous n'avez pas besoin de le déclarer : le premier palier groupé l'ajoute en haut du mode Simplifier, activé. Déclarez-le pour le mettre ailleurs ou changez son plus petit groupe.
- Les atterrissages groupés durent pour la session, comme les groupes ouverts.
- Les noms
landingd'un groupe de destination d'où il vient :{ runId, pivotId, pivotLabel }, avec l'étiquette de la définition du pivot. Une puce peut lire12 × ip · Event elementssans analyser l'identifiant d'exécution.
Pour regrouper chaque résultat pivot, définissez pivotIngestGrouped. Exécutions en un clic et pivots autoIngest, qui n'ouvrent jamais Review, puis atterrissent également regroupés :
new Pivotick(el, data, { pivotIngestGrouped: true })Le pied de page de la revue suit l'option :
pivotIngestGrouped | Ingérer sélectionné et Tout ingérer | Deuxième bouton |
|---|---|---|
| désactivé (par défaut) | terre meuble | Ingérer dans un groupe |
| sur | terrain groupé | Ingérer en vrac |
Avec UI.simplify désactivé, l'option ne fait rien et il n'y a pas de deuxième bouton.
Pour choisir une ingération à partir du code, transmettez group :
await graph.pivots.ingest('correlations', 'triage', { group: true })Règles personnalisées
Votre propre règle est un partition(view) renvoyant une clé par nœud :
{
kind: 'custom',
id: 'bySensor',
label: 'By sensor', // its name in the Simplify mode
description: 'Sightings reported by the same sensor.',
minSize: 2, // the default for a custom rule
partition: (view) => new Map(view.nodes
.filter((node) => view.typeOf(node) === 'sighting')
.map((node) => [node.id, node.getData().sensor])),
}view est le graphique tel que le voit cette règle :
| Membre | Qu'est-ce que c'est |
|---|---|
nodes | Les nœuds que cette règle peut regrouper : ce qui passe les filtres, avec les groupes de règles précédentes à la place de leurs membres. Les nœuds annotés, les nœuds extraits et les clusters développés sont laissés de côté. |
inNeighbours(node) / outNeighbours(node) | Les nœuds dessinés avec une ligne vers ou depuis celui-ci. |
typeOf(node) | Le type par lequel la règle regroupe : UI.simplify.typeOf, sinon render.nodeTypeAccessor. |
groupOf(node) | Le groupe derrière un nœud, lorsqu'il s'agit d'un groupe défini par une règle antérieure. |
Un nœud laissé en dehors de la carte reste lui-même et les identifiants qui ne sont pas dans view.nodes sont ignorés. Une règle qui lance est désactivée, sa carte en mode Simplifier l'indique et les autres règles s'exécutent toujours.
Le mode Simplifier
Le bouton Simplifier sur le rail ouvre une carte par règle, dans l'ordre d'exécution : un interrupteur, son réglage et ce que la règle a plié. Le paramètre est un stepper − / + pour le plus petit groupe, le moins de liens ou la force de base, et un curseur pour le niveau Communautés. Les règles déclarées par l'application portent une balise app. Le résumé en haut indique combien de nœuds se trouvent sur le canevas parmi ceux qui passent les filtres, et le bouton de rail compte les groupes pendant qu'une règle se replie.
Travailler avec un groupe
Un groupe est dessiné comme un nœud et il agit pour ses membres partout où cela est sans ambiguïté.
- Ouvrez avec un double-clic, Entrée, la barre latérale ou le menu contextuel. Ses membres reviennent sous forme de nœuds ordinaires, à l'intérieur d'un lavis à la couleur du groupe, et une légère traction les maintient ensemble. Faites glisser la puce au-dessus d'eux pour tous les déplacer ; son × les replie. Son info-bulle nomme la règle qui a créé le groupe. Les membres reviennent là où ils étaient assis ; ceux qui n'ont pas de place libre se répartissent dans le groupe, et la physique en direct reçoit une légère poussée, comme pour un cluster.
simulation.fitViewOnExpandCollapsecorrespond à la vue d'ouverture et de fermeture. Un groupe avec plus de membres queUI.simplify.openConfirmAbove(100) demande en premier. - Sélectionnez pour voir ses membres dans la barre latérale, dans une liste triable. Pull out maintient un membre hors du groupe jusqu'à ce qu'il soit réinséré, depuis son menu contextuel : sur le canevas lorsque le groupe est ouvert, ou depuis sa ligne dans le data dock que le groupe soit ouvert ou non. Sur une sélection, il extrait tous les membres sélectionnés.
- Afficher dans le tableau, dans la barre latérale ou dans le menu contextuel, répertorie les membres dans le dock de données, où les filtres de colonnes les affinent davantage. La puce au-dessus de la table répertorie à nouveau chaque nœud.
- Sélectionner les membres, Pivot et Supprimer agissent sur les membres. Pivot et Suppr passent par les hooks habituels, donc
onBeforeDeletevoit les vrais nœuds. Masquer, supprimer et pivoter sur une sélection qui permet aux groupes d'agir également sur leurs membres. - La sélection d'un groupe éclaire les nœuds auxquels il est lié, tout comme la sélection d'un nœud éclaire ses voisins. L'édition et la connexion ne sont pas proposées sur un groupe : celui-ci ne dispose d'aucune donnée propre.
Les groupes ouverts et les nœuds retirés durent pour la session et ne constituent pas des étapes d'annulation. Pour les restaurer, appelez le graph.simplify.open() et le pullOut().
Groupes réalisés à la main
Sélectionnez deux nœuds ou plus, puis Groupe dans la barre de masse de la barre latérale ou Groupez les nœuds sélectionnés dans le menu contextuel d'un nœud sélectionné. Tapez un titre ou conservez celui proposé ("3 × ip, 2 × domaine"), et la sélection se replie en un seul groupe sous ce titre.
- Un groupe créé à la main gagne. Sa règle, À la main, s'exécute avant les autres, donc un nœud choisi quitte n'importe quel groupe de règles. Un groupe sélectionné donne ses membres, et un nœud choisi dans un deuxième groupe créé à la main quitte le premier. Les nœuds annotés et les clusters ouverts restent à l'écart, et l'invite indique leur nombre.
- Il conserve ses membres quels que soient leurs liens. Celui qui est supprimé ou filtré n'est pas dessiné ; un groupe laissé avec un membre n'est pas du tout tiré au sort et revient avec ses membres.
- Renommer et Dissocier depuis son panneau de barre latérale ou son menu contextuel. Un titre vide l'indique à nouveau par ses types. Le Ungroup de la barre de masse supprime tous les groupes créés à la main dans lesquels la sélection contient ou se trouve.
- Grouper, Renommer et Dissocier sont des étapes d'annulation, contrairement à l'ouverture ou au retrait.
- Il s'agit de l'état d'affichage : non exporté et rechargé. Pour le conserver, enregistrez
getManualGroups()et remettez-le àsetManualGroups(). Les groupes restaurés, ouverts ou extraits juste aprèsnew Graph()font partie de la disposition d'ouverture : un groupe fermé est placé comme un seul point, les membres d'un groupe ouvert sont conservés ensemble.
const id = graph.simplify.groupNodes(['ip-1', 'ip-2', 'dom-7'], 'Suspicious infra')
graph.simplify.renameGroup(id, 'Cleared infra')
graph.simplify.ungroup(id)Recherche
La recherche examine chaque nœud, y compris ceux pliés.
- Une correspondance à l'intérieur d'un groupe l'indique dans sa ligne de résultats : in 12 × ip.
- Le sélectionner ouvre le groupe et sélectionne le nœud, comme le ferait Sélectionner les membres. Un groupe avec plus de membres que
openConfirmAbovereste fermé et est sélectionné à la place. - Afficher tout sur le canevas, la dernière ligne des résultats ou Shift+Enter, ferme la recherche et allume chaque correspondance ; tout le reste s'estompe. Un groupe tenant des allumettes est également allumé, et un arc dans la couleur du thème au-dessus de son anneau montre leur part. Son info-bulle les compte : 2 sur 12 correspondent à "198.51". Esc, un clic sur un canevas vide ou la recherche suivante y met fin.
Le survol d'une entrée de légende marque les groupes de la même manière : un groupe contenant des nœuds de cette entrée est allumé, avec leur part sur son anneau, donc un groupe mélangeant les types ne se lit pas comme un seul.
Une application disposant de sa propre recherche peut marquer ses correspondances de la même manière avec graph.simplify.setMatches(nodes, query) et les effacer avec setMatches([]).
Le regard
Un groupe est un anneau autour d'un disque de la couleur de son type, avec le décompte sur le disque une fois qu'il y a de la place pour celui-ci et une étiquette en dessous. Il grandit avec son nombre, jusqu'à une limite. Un groupe mélangeant les types obtient un disque neutre et un anneau divisé par type.
L'étiquette est 12 × ip par défaut. typeLabel nomme vos types :
UI: {
simplify: {
typeLabel: (type, count) => `${count} ${count === 1 ? type : `${type}s`}`,
},
}render.groupStyle(group) renvoie un NodeStyle superposé à la valeur par défaut, donc tiers, html, shape et les badges fonctionnent sur un groupe comme sur un nœud. render.groupOutline(group) définit ce que dit la puce sur un groupe ouvert :
render: {
groupStyle: (group) => group.rule === 'bySensor' ? { color: '#6b7280' } : undefined,
groupOutline: (group) => `${group.members.length} from ${group.rule}`,
}groupStyle reçoit également base, le style que la bibliothèque dessinerait. Ce que vous retournez remplace ses clés, donc un hôte qui ajoute un niveau étale base.tiers pour conserver le décompte sur le disque :
render: {
groupStyle: (group, base) => ({
tiers: [...(base.tiers ?? []), { width: 140, height: 44, style: { html: () => chip(group) } }],
}),
}Chacun reçoit un GroupInfo :
| Champ | Qu'est-ce que c'est |
|---|---|
id | Stable alors que le groupe conserve la plupart de ses membres. |
rule | 'neighbours', 'chains', 'degree', 'kcore', 'communities', 'landings', 'manual' ou id d'une règle personnalisée. |
members | Les vrais nœuds qu’il représente. |
typeCounts | Combien de membres de chaque type ; '' n'est pas un type. |
anchors | Les nœuds dessinés auxquels il est lié, groupes inclus. |
open | Que ses membres soient de retour sur la toile. |
level | Le niveau des communautés où il a été trouvé. |
title | Un titre de groupe fait main. |
landing | Course et pivot d'un groupe d'atterrissage : { runId, pivotId, pivotLabel }. |
L'infobulle d'un groupe nomme sa règle, répertorie ce à quoi elle est liée et, pour un groupe mixte, ses membres par type. tooltip.renderGroupExtra(group, ctx) ajoute vos propres lignes, comme renderNodeExtra le fait pour un nœud. Un groupe ignore tooltip.render et renderNodeExtra, qui sont écrits pour les données d'un nœud.
Types et couleurs de l'hôte
Les groupes comptent leurs pièces par render.nodeTypeAccessor et les colorent selon la couleur du style de chaque membre. Deux options UI.simplify modifient cela pour chaque règle et groupe, sans toucher aux styles, à la légende ou aux filtres :
typeOf(node)est le type par lequel chaque règle regroupe et chaque groupe compte ses parties par : l'étiquette, les parts d'un anneau mixte, le titre d'un groupe fait à la main. LetypeOfd'une règle l'emporte toujours pour cette règle.colorOf(node)est la couleur qu'un nœud représente dans un groupe : le disque et l'anneau, le lavage ouvert, les éclats de l'info-bulle. Le retour deundefinedrevient à la couleur de style du nœud. LegroupStyled'un groupe a toujours le dernier mot sur le dessin fermé.
Un hôte qui stylise par élément, regroupe par sous-type et dessine lui-même ses nœuds :
const options = {
render: {
nodeTypeAccessor: (node) => node.getData().element,
nodeStyleMap: { attribute: { shape: 'none', html: drawAttribute } },
},
UI: {
simplify: {
typeOf: (node) => `${node.getData().element}:${node.getData().subtype}`,
colorOf: (node) => palette[node.getData().subtype],
},
},
}Dans le tableau
Le data dock répertorie les vrais nœuds. Un nœud plié lit grouped dans la colonne Visibility, et une colonne Group nomme son groupe alors qu'il y en a. Une arête dont la ligne est tracée vers un groupe indique également grouped.
Au moment de l'exécution
graph.simplify contient les règles et les groupes :
| Méthode | Ce que ça fait |
|---|---|
setRules(rules) / getRules() | Remplacez les règles ; lisez l'état de chacun et ce qu'il a plié. |
setRuleEnabled(id, on) / setRuleSetting(id, n) | Ce que font le commutateur et le stepper du mode Simplify. setRuleMinSize(id, n) définit uniquement le plus petit groupe. |
getGroups() / groupOf(node) | Chaque groupe et le premier groupe dans lequel un nœud a été intégré. Un groupe dont la règle est repliée ultérieurement est également répertorié, à côté du groupe qui le détient, et tous deux répertorient ses membres ; summary().groups compte les groupes fermés dessinés par le canevas. |
open(group) / close(group) | Placez les membres d'un groupe sur la toile ou repliez-les. |
pullOut(node) / putBack(node) / isPulledOut(node) | Gardez un nœud hors de tout groupe ou laissez-le revenir. |
groupNodes(nodes, title?) / renameGroup(group, title) / ungroup(groups) / isManual(group) | Créez, retitrez ou supprimez les groupes à la main ; chacun est une étape d’annulation. |
getManualGroups() / setManualGroups(list) | Enregistrez les groupes créés à la main et restaurez-les. |
groupLanding(runId) / ungroupLanding(runId) / isLandingGrouped(runId) | Pliez ce qu'une course de pivot ajoute dans groupes d'atterrissage, ou détachez-le à nouveau. |
summary() | Combien de nœuds sont dessinés, passent les filtres et sont pliés. |
setMatches(nodes, query) / matchesIn(group) | Marquer les correspondances d'une recherche sur les groupes qui les détiennent ; lisez combien un groupe en détient. |
onChange(listener) | Appelé après les changements de regroupement ; renvoie son désabonnement. |