SeaWolf-AI commited on
Commit
7f32ee8
ยท
verified ยท
1 Parent(s): d2fc099

Enrich nodes with real downloads/likes (All-Model-Repos 2.9M) + add Darwin Lineage atlas

Browse files
compressed_darwin_data.json.gz CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:9b4e1526ff07ff3ea856d80def745c5d26902cb8171193dd9c7980f8db99bb7a
3
- size 44245
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f6e7af6fdcfd4c1cb597ac18e111ee844c17d599b79b84b3bb3f8a48dc628abf
3
+ size 49074
compressed_darwin_lineage_data.json.gz ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:befc615b0fcfee462750e145a9b2eb9c5eff05071e258b8a2cccb408ef6fb98f
3
+ size 77143
compressed_large_nlp_data.json.gz CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:1eefbf1eb059a228f9573cc6646519288ee22e4dc9e94386e1eaca0703968b3c
3
- size 24837549
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8946a82b67df8c27de8a7fac0a271488800789a84c8ab435f252fab70cc8d38e
3
+ size 25826155
compressed_modalities_data.json.gz CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:4856e9c62b29c9668f2ace25d2cc68c6c5ca47cf41bf9afffc3a0ad6767ebbcb
3
- size 3327334
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e45c122f76f6f76d8a3586b863320936e11a6b3087179be84f921ab28167d82e
3
+ size 3487770
config.json CHANGED
@@ -1,53 +1,53 @@
1
- {
2
- "type": "network",
3
- "version": "1.0",
4
- "data": "compressed_modalities_data.json.gz",
5
- "logo": {
6
- "file": "",
7
- "link": "",
8
- "text": "Model Galaxy"
9
- },
10
- "text": {
11
- "more": "<p><strong>Model Galaxy</strong> is a fork of <a href=\"https://huggingface.co/spaces/Eliahu/Model-Atlas\" target=\"_blank\">Eliahu/Model-Atlas</a> with two custom overlays: <strong>(1) the entire VIDRAFT Darwin family</strong> (120 models, upper-right cluster) and <strong>(2) the 2026 trending originals</strong> (48 models โ€” DeepSeek-V4, MiMo-V2.5, Hy3, GLM-5.1, Hermes-4.3, Kimi-K2, gpt-oss, NVIDIA Nemotron-3, Llama-3.3, Granite-4.1, Qwen3-Coder-Next, VibeVoice, etc., lower-right cluster).</p><br><p><strong>Color schemes (Color By):</strong></p><ul><li><strong>base_model_relation</strong> โ€” Darwin red/amber/purple, trending = company colors</li><li><strong>modality</strong> โ€” NLP (yellow), TTS+LLM (pink), Image (indigo), Audio (teal), OCR (fuchsia), Embed (purple), Multi (rose)</li><li><strong>vidraft_family</strong> โ€” Darwin red vs others gray</li><li><strong>darwin_official</strong> โ€” FINAL-Bench official red, brand variants amber, others gray</li><li><strong>trending_2026</strong> โ€” trending red, others gray</li></ul><br><p>Switch atlas via the <strong>Atlas:</strong> selector to compare against the broader Modalities, Large NLP, or full HF Galaxy.</p><br><h2 class=\"title\">BibTeX (original Atlas paper)</h2><pre><code>@misc{horwitz2025chartingnavigatinghuggingfaces,<br>title={Charting and Navigating Hugging Face's Model Atlas},<br>author={Eliahu Horwitz and Nitzan Kurer and Jonathan Kahana and Liel Amar and Yedid Hoshen},<br>year={2025},<br>eprint={2503.10633},<br>archivePrefix={arXiv},<br>primaryClass={cs.LG},<br>url={https://arxiv.org/abs/2503.10633},<br>}</code></pre>",
12
- "intro": "<strong>Model Galaxy</strong> โ€” interactive ontology of the <strong>VIDRAFT Darwin family</strong> + <strong>2026 trending originals</strong> on the Hugging Face galaxy. <br><br>168 custom-injected nodes (120 Darwin family + 48 trending) on top of Eliahu Horwitz's HF Model Atlas. <br><br><div class=\"features\"> <h2>Key Features</h2> <ul> <li><strong>Search:</strong> Find any Darwin model (e.g. <em>Rogue-28B-MIX</em>, <em>Darwin-9B-NEG</em>) or trending model (e.g. <em>DeepSeek-V4-Pro</em>, <em>Hermes-4.3</em>).</li> <li><strong>Color By:</strong> base_model_relation, modality, license, vidraft_family, darwin_official, trending_2026.</li> <li><strong>Atlas:</strong> Switch between Modalities (default), Darwin Family Only, Large NLP, or full HF Galaxy.</li> <li><strong>Click a node</strong> to see its base_model parents and children (the merge / quantize / adapter chain).</li> </ul> </div> <br><strong>Clusters:</strong> ๐ŸŒณ Darwin upper-right (xโ‰ˆ7000) ยท โญ 2026 Trending lower-right (xโ‰ˆ6500, yโ‰ˆ-5500). <br>",
13
- "title": "Model Galaxy"
14
- },
15
- "legend": {
16
- "edgeLabel": "edgeLabel",
17
- "colorLabel": "colorLabel",
18
- "nodeLabel": "nodeLabel"
19
- },
20
- "features": {
21
- "search": true,
22
- "groupSelectorAttribute": false,
23
- "hoverBehavior": "dim"
24
- },
25
- "informationPanel": {
26
- "groupByEdgeDirection": false,
27
- "imageAttribute": false
28
- },
29
- "sigma": {
30
- "drawingProperties": {
31
- "defaultEdgeType": "curve",
32
- "defaultHoverLabelBGColor": "#fef3c7",
33
- "defaultLabelBGColor": "#ffffff",
34
- "activeFontStyle": "bold",
35
- "defaultLabelColor": "#0f172a",
36
- "labelThreshold": 10,
37
- "defaultLabelHoverColor": "#92400e",
38
- "fontStyle": "bold",
39
- "hoverFontStyle": "bold",
40
- "defaultLabelSize": 14
41
- },
42
- "graphProperties": {
43
- "maxEdgeSize": 2.5,
44
- "minEdgeSize": 2,
45
- "minNodeSize": 1,
46
- "maxNodeSize": 7
47
- },
48
- "mouseProperties": {
49
- "maxRatio": 20,
50
- "minRatio": 0.75
51
- }
52
- }
53
- }
 
1
+ {
2
+ "type": "network",
3
+ "version": "1.0",
4
+ "data": "compressed_modalities_data.json.gz",
5
+ "logo": {
6
+ "file": "",
7
+ "link": "",
8
+ "text": "Model Galaxy"
9
+ },
10
+ "text": {
11
+ "more": "<p><strong>Model Galaxy</strong> is a fork of <a href=\"https://huggingface.co/spaces/Eliahu/Model-Atlas\" target=\"_blank\">Eliahu/Model-Atlas</a> with two custom overlays: <strong>(1) the entire VIDRAFT Darwin family</strong> (120 models, upper-right cluster) and <strong>(2) the 2026 trending originals</strong> (48 models โ€” DeepSeek-V4, MiMo-V2.5, Hy3, GLM-5.1, Hermes-4.3, Kimi-K2, gpt-oss, NVIDIA Nemotron-3, Llama-3.3, Granite-4.1, Qwen3-Coder-Next, VibeVoice, etc., lower-right cluster).</p><br><p><strong>Color schemes (Color By):</strong></p><ul><li><strong>base_model_relation</strong> โ€” Darwin red/amber/purple, trending = company colors</li><li><strong>modality</strong> โ€” NLP (yellow), TTS+LLM (pink), Image (indigo), Audio (teal), OCR (fuchsia), Embed (purple), Multi (rose)</li><li><strong>vidraft_family</strong> โ€” Darwin red vs others gray</li><li><strong>darwin_official</strong> โ€” FINAL-Bench official red, brand variants amber, others gray</li><li><strong>trending_2026</strong> โ€” trending red, others gray</li></ul><br><p>Switch atlas via the <strong>Atlas:</strong> selector to compare against the broader Modalities, Large NLP, or full HF Galaxy.</p><br><h2 class=\"title\">BibTeX (original Atlas paper)</h2><pre><code>@misc{horwitz2025chartingnavigatinghuggingfaces,<br>title={Charting and Navigating Hugging Face's Model Atlas},<br>author={Eliahu Horwitz and Nitzan Kurer and Jonathan Kahana and Liel Amar and Yedid Hoshen},<br>year={2025},<br>eprint={2503.10633},<br>archivePrefix={arXiv},<br>primaryClass={cs.LG},<br>url={https://arxiv.org/abs/2503.10633},<br>}</code></pre>",
12
+ "intro": "<strong>Model Galaxy</strong> โ€” interactive ontology of the <strong>VIDRAFT Darwin family</strong> + <strong>2026 trending originals</strong> on the Hugging Face galaxy. <br><br>168 custom-injected nodes (120 Darwin family + 48 trending) on top of Eliahu Horwitz's HF Model Atlas. <br><br><div class=\"features\"> <h2>Key Features</h2> <ul> <li><strong>Search:</strong> Find any Darwin model (e.g. <em>Rogue-28B-MIX</em>, <em>Darwin-9B-NEG</em>) or trending model (e.g. <em>DeepSeek-V4-Pro</em>, <em>Hermes-4.3</em>).</li> <li><strong>Color By:</strong> base_model_relation, modality, license, vidraft_family, darwin_official, trending_2026.</li> <li><strong>Atlas:</strong> Switch between Modalities (default), Darwin Family Only, Large NLP, or full HF Galaxy.</li> <li><strong>Click a node</strong> to see its base_model parents and children (the merge / quantize / adapter chain).</li> </ul> </div> <br><strong>Clusters:</strong> ๐ŸŒณ Darwin upper-right (xโ‰ˆ7000) ยท โญ 2026 Trending lower-right (xโ‰ˆ6500, yโ‰ˆ-5500). <br> <br><br><strong>๐Ÿ†• 2026-05 update:</strong> all nodes now carry <strong>real download/like counts</strong> (joined from <a href=\"https://huggingface.co/datasets/HF-Collab-Center/All-Model-Repos\" target=\"_blank\">All-Model-Repos</a>, 2.9M HF repos), and a new <strong>๐ŸŒณ Darwin Lineage</strong> atlas traces every fine-tune / quantization / adapter / merge descending from the Darwin family across the full Hub.",
13
+ "title": "Model Galaxy"
14
+ },
15
+ "legend": {
16
+ "edgeLabel": "edgeLabel",
17
+ "colorLabel": "colorLabel",
18
+ "nodeLabel": "nodeLabel"
19
+ },
20
+ "features": {
21
+ "search": true,
22
+ "groupSelectorAttribute": false,
23
+ "hoverBehavior": "dim"
24
+ },
25
+ "informationPanel": {
26
+ "groupByEdgeDirection": false,
27
+ "imageAttribute": false
28
+ },
29
+ "sigma": {
30
+ "drawingProperties": {
31
+ "defaultEdgeType": "curve",
32
+ "defaultHoverLabelBGColor": "#fef3c7",
33
+ "defaultLabelBGColor": "#ffffff",
34
+ "activeFontStyle": "bold",
35
+ "defaultLabelColor": "#0f172a",
36
+ "labelThreshold": 10,
37
+ "defaultLabelHoverColor": "#92400e",
38
+ "fontStyle": "bold",
39
+ "hoverFontStyle": "bold",
40
+ "defaultLabelSize": 14
41
+ },
42
+ "graphProperties": {
43
+ "maxEdgeSize": 2.5,
44
+ "minEdgeSize": 2,
45
+ "minNodeSize": 1,
46
+ "maxNodeSize": 7
47
+ },
48
+ "mouseProperties": {
49
+ "maxRatio": 20,
50
+ "minRatio": 0.75
51
+ }
52
+ }
53
+ }
js/main.js CHANGED
@@ -1,865 +1,866 @@
1
- var sigInst, canvas, $GP
2
-
3
- //Load configuration file
4
- var config={};
5
- var currentColorAttribute = "base_model_relation";
6
- var currentAtlasFile = "";
7
-
8
- //For debug allow a config=file.json parameter to specify the config
9
- function GetQueryStringParams(sParam,defaultVal) {
10
- var sPageURL = ""+window.location;//.search.substring(1);//This might be causing error in Safari?
11
- if (sPageURL.indexOf("?")==-1) return defaultVal;
12
- sPageURL=sPageURL.substr(sPageURL.indexOf("?")+1);
13
- var sURLVariables = sPageURL.split('&');
14
- for (var i = 0; i < sURLVariables.length; i++) {
15
- var sParameterName = sURLVariables[i].split('=');
16
- if (sParameterName[0] == sParam) {
17
- return sParameterName[1];
18
- }
19
- }
20
- return defaultVal;
21
- }
22
-
23
-
24
- jQuery.getJSON(GetQueryStringParams("config","config.json"), function(data, textStatus, jqXHR) {
25
- config=data;
26
-
27
- currentAtlasFile = config.data;
28
-
29
- if (config.type!="network") {
30
- //bad config
31
- alert("Invalid configuration settings.")
32
- return;
33
- }
34
-
35
- //As soon as page is ready (and data ready) set up it
36
- $(document).ready(setupGUI(config));
37
- });//End JSON Config load
38
-
39
-
40
- // FUNCTION DECLARATIONS
41
-
42
- Object.size = function(obj) {
43
- var size = 0, key;
44
- for (key in obj) {
45
- if (obj.hasOwnProperty(key)) size++;
46
- }
47
- return size;
48
- };
49
-
50
-
51
- function initSigma(config) {
52
- var data=config.data
53
-
54
- var drawProps, graphProps,mouseProps;
55
- if (config.sigma && config.sigma.drawingProperties)
56
- drawProps=config.sigma.drawingProperties;
57
- else
58
- drawProps={
59
- defaultLabelColor: "#000",
60
- defaultLabelSize: 14,
61
- defaultLabelBGColor: "#ddd",
62
- defaultHoverLabelBGColor: "#002147",
63
- defaultLabelHoverColor: "#fff",
64
- labelThreshold: 10,
65
- defaultEdgeType: "curve",
66
- hoverFontStyle: "bold",
67
- fontStyle: "bold",
68
- activeFontStyle: "bold"
69
- };
70
-
71
- if (config.sigma && config.sigma.graphProperties)
72
- graphProps=config.sigma.graphProperties;
73
- else
74
- graphProps={
75
- minNodeSize: 1,
76
- maxNodeSize: 7,
77
- minEdgeSize: 0.2,
78
- maxEdgeSize: 0.5
79
- };
80
-
81
- if (config.sigma && config.sigma.mouseProperties)
82
- mouseProps=config.sigma.mouseProperties;
83
- else
84
- mouseProps={
85
- minRatio: 0.75, // How far can we zoom out?
86
- maxRatio: 20, // How far can we zoom in?
87
- };
88
-
89
- var a = sigma.init(document.getElementById("sigma-canvas")).drawingProperties(drawProps).graphProperties(graphProps).mouseProperties(mouseProps);
90
- sigInst = a;
91
- a.active = !1;
92
- a.neighbors = {};
93
- a.detail = !1;
94
-
95
-
96
- dataReady = function() {
97
- a.clusters = {};
98
-
99
- // Initialize node clusters based on current coloring
100
- a.iterNodes(function (b) {
101
- a.clusters[b.color] || (a.clusters[b.color] = []);
102
- a.clusters[b.color].push(b.id);
103
-
104
- // Make sure colors are properly copied from the JSON to node.attr
105
- if (!b.attr) b.attr = {};
106
- if (b.colors && !b.attr.colors) {
107
- b.attr.colors = b.colors;
108
- }
109
- });
110
-
111
- a.bind("upnodes", function (a) {
112
- nodeActive(a.content[0]);
113
- });
114
-
115
- a.draw();
116
- configSigmaElements(config);
117
-
118
- // Create the color legend
119
- updateColorLegend();
120
-
121
- // Find available color attributes from nodes
122
- var colorAttributes = [];
123
- var colorAttrsFound = {};
124
-
125
- a.iterNodes(function(node) {
126
- if (node.attr && node.attr.colors) {
127
- for (var attr in node.attr.colors) {
128
- if (!colorAttrsFound[attr]) {
129
- colorAttrsFound[attr] = true;
130
- colorAttributes.push('<div style="line-height:12px"><a href="#" style="color:black;" data-attr="' + attr + '">'+attr+'</a></div>');
131
- }
132
- }
133
- } else if (node.colors) {
134
- // If colors are in the original structure, copy them to attr
135
- if (!node.attr) node.attr = {};
136
- node.attr.colors = node.colors;
137
-
138
- for (var attr in node.colors) {
139
- if (!colorAttrsFound[attr]) {
140
- colorAttrsFound[attr] = true;
141
- colorAttributes.push('<div style="line-height:12px"><a href="#" style="color:black;" data-attr="' + attr + '">'+attr+'</a></div>');
142
- }
143
- }
144
- }
145
- });
146
-
147
- $GP.coloring.content(colorAttributes.join(""));
148
- $GP.coloring.select.text(currentColorAttribute);
149
- }
150
-
151
- if (data.indexOf("gexf")>0 || data.indexOf("xml")>0)
152
- a.parseGexf(data,dataReady);
153
- else
154
- a.parseJson(data,dataReady);
155
- gexf = sigmaInst = null;
156
- }
157
-
158
-
159
- function setupGUI(config) {
160
- // Initialise main interface elements
161
- var logo=""; // Logo elements
162
- if (config.logo.file) {
163
-
164
- logo = "<img src=\"" + config.logo.file +"\"";
165
- if (config.logo.text) logo+=" alt=\"" + config.logo.text + "\"";
166
- logo+=">";
167
- } else if (config.logo.text) {
168
- logo="<h1>"+config.logo.text+"</h1>";
169
- }
170
- if (config.logo.link) logo="<a href=\"" + config.logo.link + "\">"+logo+"</a>";
171
- $("#maintitle").html(logo);
172
-
173
- // #title
174
- $("#title").html("<h2>"+config.text.title+"</h2>");
175
-
176
- // #titletext
177
- $("#titletext").html(config.text.intro);
178
-
179
- // More information
180
- if (config.text.more) {
181
- $("#information").html(config.text.more);
182
- } else {
183
- //hide more information link
184
- $("#moreinformation").hide();
185
- }
186
-
187
- // Legend
188
-
189
- // Node
190
- if (config.legend.nodeLabel) {
191
- $(".node").next().html(config.legend.nodeLabel);
192
- } else {
193
- //hide more information link
194
- $(".node").hide();
195
- }
196
- // Edge
197
- if (config.legend.edgeLabel) {
198
- $(".edge").next().html(config.legend.edgeLabel);
199
- } else {
200
- //hide more information link
201
- $(".edge").hide();
202
- }
203
- // Colours
204
- if (config.legend.nodeLabel) {
205
- $(".colours").next().html(config.legend.colorLabel);
206
- } else {
207
- //hide more information link
208
- $(".colours").hide();
209
- }
210
-
211
-
212
- $GP = {
213
- calculating: !1,
214
- showgroup: !1
215
- };
216
- $GP.intro = $("#intro");
217
- $GP.minifier = $GP.intro.find("#minifier");
218
- $GP.mini = $("#minify");
219
- $GP.info = $("#attributepane");
220
- $GP.info_donnees = $GP.info.find(".nodeattributes");
221
- $GP.info_name = $GP.info.find(".name");
222
- $GP.info_link = $GP.info.find(".link");
223
- $GP.info_data = $GP.info.find(".data");
224
- $GP.info_close = $GP.info.find(".returntext");
225
- $GP.info_close2 = $GP.info.find(".close");
226
- $GP.info_p = $GP.info.find(".p");
227
- $GP.info_close.click(nodeNormal);
228
- $GP.info_close2.click(nodeNormal);
229
- $GP.form = $("#mainpanel").find("form");
230
- $GP.search = new Search($GP.form.find("#search"));
231
- if (!config.features.search) {
232
- $("#search").hide();
233
- }
234
- if (!config.features.groupSelectorAttribute) {
235
- $("#attributeselect").hide();
236
- }
237
- $GP.cluster = new Cluster($GP.form.find("#attributeselect"));
238
- $GP.coloring = new ColorSelector($GP.form.find("#coloringselect"));
239
-
240
-
241
-
242
- $GP.atlas = new AtlasSelector($GP.form.find("#atlasselect"));
243
- var atlases = getAvailableAtlases();
244
- var atlasLinks = [];
245
- for (var i = 0; i < atlases.length; i++) {
246
- atlasLinks.push('<div style="line-height:12px"><a href="#" data-file="' + atlases[i].file + '" style="color:black;">' + atlases[i].name + '</a></div>');
247
- }
248
-
249
- $GP.atlas.content(atlasLinks.join(""));
250
- $GP.atlas.select.text(atlases[0].name); // Set default atlas name
251
-
252
-
253
- config.GP=$GP;
254
- initSigma(config);
255
- }
256
-
257
- function configSigmaElements(config) {
258
- $GP=config.GP;
259
-
260
- // Node hover behaviour
261
- if (config.features.hoverBehavior == "dim") {
262
-
263
- var greyColor = '#ccc';
264
- sigInst.bind('overnodes',function(event){
265
- var nodes = event.content;
266
- var neighbors = {};
267
- sigInst.iterEdges(function(e){
268
- if(nodes.indexOf(e.source)<0 && nodes.indexOf(e.target)<0){
269
- if(!e.attr['grey']){
270
- e.attr['true_color'] = e.color;
271
- e.color = greyColor;
272
- e.attr['grey'] = 1;
273
- }
274
- }else{
275
- e.color = e.attr['grey'] ? e.attr['true_color'] : e.color;
276
- e.attr['grey'] = 0;
277
-
278
- neighbors[e.source] = 1;
279
- neighbors[e.target] = 1;
280
- }
281
- }).iterNodes(function(n){
282
- if(!neighbors[n.id]){
283
- if(!n.attr['grey']){
284
- n.attr['true_color'] = n.color;
285
- n.color = greyColor;
286
- n.attr['grey'] = 1;
287
- }
288
- }else{
289
- n.color = n.attr['grey'] ? n.attr['true_color'] : n.color;
290
- n.attr['grey'] = 0;
291
- }
292
- }).draw(2,2,2);
293
- }).bind('outnodes',function(){
294
- sigInst.iterEdges(function(e){
295
- e.color = e.attr['grey'] ? e.attr['true_color'] : e.color;
296
- e.attr['grey'] = 0;
297
- }).iterNodes(function(n){
298
- n.color = n.attr['grey'] ? n.attr['true_color'] : n.color;
299
- n.attr['grey'] = 0;
300
- }).draw(2,2,2);
301
- });
302
-
303
- } else if (config.features.hoverBehavior == "hide") {
304
-
305
- sigInst.bind('overnodes',function(event){
306
- var nodes = event.content;
307
- var neighbors = {};
308
- sigInst.iterEdges(function(e){
309
- if(nodes.indexOf(e.source)>=0 || nodes.indexOf(e.target)>=0){
310
- neighbors[e.source] = 1;
311
- neighbors[e.target] = 1;
312
- }
313
- }).iterNodes(function(n){
314
- if(!neighbors[n.id]){
315
- n.hidden = 1;
316
- }else{
317
- n.hidden = 0;
318
- }
319
- }).draw(2,2,2);
320
- }).bind('outnodes',function(){
321
- sigInst.iterEdges(function(e){
322
- e.hidden = 0;
323
- }).iterNodes(function(n){
324
- n.hidden = 0;
325
- }).draw(2,2,2);
326
- });
327
-
328
- }
329
- $GP.bg = $(sigInst._core.domElements.bg);
330
- $GP.bg2 = $(sigInst._core.domElements.bg2);
331
- var a = [],
332
- b,x=1;
333
- for (b in sigInst.clusters) a.push('<div style="line-height:12px"><a href="#' + b + '"><div style="width:40px;height:12px;border:1px solid #fff;background:' + b + ';display:inline-block"></div> Group ' + (x++) + ' (' + sigInst.clusters[b].length + ' members)</a></div>');
334
- //a.sort();
335
- $GP.cluster.content(a.join(""));
336
- b = {
337
- minWidth: 400,
338
- maxWidth: 800,
339
- maxHeight: 600
340
- };// minHeight: 300,
341
- $("a.fb").fancybox(b);
342
- $("#zoom").find("div.z").each(function () {
343
- var a = $(this),
344
- b = a.attr("rel");
345
- a.click(function () {
346
- if (b == "center") {
347
- sigInst.position(0,0,1).draw();
348
- } else {
349
- var a = sigInst._core;
350
- sigInst.zoomTo(a.domElements.nodes.width / 2, a.domElements.nodes.height / 2, a.mousecaptor.ratio * ("in" == b ? 1.5 : 0.5));
351
- }
352
-
353
- })
354
- });
355
- $GP.mini.click(function () {
356
- $GP.mini.hide();
357
- $GP.intro.show();
358
- $GP.minifier.show()
359
- });
360
- $GP.minifier.click(function () {
361
- $GP.intro.hide();
362
- $GP.minifier.hide();
363
- $GP.mini.show()
364
- });
365
- $GP.intro.find("#showGroups").click(function () {
366
- !0 == $GP.showgroup ? showGroups(!1) : showGroups(!0)
367
- });
368
- a = window.location.hash.substr(1);
369
- if (0 < a.length) switch (a) {
370
- case "Groups":
371
- showGroups(!0);
372
- break;
373
- case "information":
374
- $.fancybox.open($("#information"), b);
375
- break;
376
- default:
377
- $GP.search.exactMatch = !0, $GP.search.search(a)
378
- $GP.search.clean();
379
- }
380
- // $GP.coloring = new ColorSelector($GP.form.find("#coloringselect"));
381
-
382
- }
383
-
384
- function Search(a) {
385
- this.input = a.find("input[name=search]");
386
- this.state = a.find(".state");
387
- this.results = a.find(".results");
388
- this.exactMatch = !1;
389
- this.lastSearch = "";
390
- this.searching = !1;
391
- var b = this;
392
- this.input.focus(function () {
393
- var a = $(this);
394
- a.data("focus") || (a.data("focus", !0), a.removeClass("empty"));
395
- b.clean()
396
- });
397
- this.input.keydown(function (a) {
398
- if (13 == a.which) return b.state.addClass("searching"), b.search(b.input.val()), !1
399
- });
400
- this.state.click(function () {
401
- var a = b.input.val();
402
- b.searching && a == b.lastSearch ? b.close() : (b.state.addClass("searching"), b.search(a))
403
- });
404
- this.dom = a;
405
- this.close = function () {
406
- this.state.removeClass("searching");
407
- this.results.hide();
408
- this.searching = !1;
409
- this.input.val("");//SAH -- let's erase string when we close
410
- nodeNormal()
411
- };
412
- this.clean = function () {
413
- this.results.empty().hide();
414
- this.state.removeClass("searching");
415
- this.input.val("");
416
- };
417
- this.search = function (a) {
418
- var b = !1,
419
- c = [],
420
- b = this.exactMatch ? ("^" + a + "$").toLowerCase() : a.toLowerCase(),
421
- g = RegExp(b);
422
- this.exactMatch = !1;
423
- this.searching = !0;
424
- this.lastSearch = a;
425
- this.results.empty();
426
- if (2 >= a.length) this.results.html("<i>You must search for a name with a minimum of 3 letters.</i>");
427
- else {
428
- sigInst.iterNodes(function (a) {
429
- g.test(a.label.toLowerCase()) && c.push({
430
- id: a.id,
431
- name: a.label
432
- })
433
- });
434
- c.length ? (b = !0, nodeActive(c[0].id)) : b = showCluster(a);
435
- a = ["<b>Search Results: </b>"];
436
- if (1 < c.length) for (var d = 0, h = c.length; d < h; d++) a.push('<a href="#' + c[d].name + '" onclick="nodeActive(\'' + c[d].id + "')\">" + c[d].name + "</a>");
437
- 0 == c.length && !b && a.push("<i>No results found.</i>");
438
- 1 < a.length && this.results.html(a.join(""));
439
- }
440
- if(c.length!=1) this.results.show();
441
- if(c.length==1) this.results.hide();
442
- }
443
- }
444
-
445
- function Cluster(a) {
446
- this.cluster = a;
447
- this.display = !1;
448
- this.list = this.cluster.find(".list");
449
- this.list.empty();
450
- this.select = this.cluster.find(".select");
451
- this.select.click(function () {
452
- $GP.cluster.toggle()
453
- });
454
- this.toggle = function () {
455
- this.display ? this.hide() : this.show()
456
- };
457
- this.content = function (a) {
458
- this.list.html(a);
459
- this.list.find("a").click(function () {
460
- var a = $(this).attr("href").substr(1);
461
- showCluster(a)
462
- })
463
- };
464
- this.hide = function () {
465
- this.display = !1;
466
- this.list.hide();
467
- this.select.removeClass("close")
468
- };
469
- this.show = function () {
470
- this.display = !0;
471
- this.list.show();
472
- this.select.addClass("close")
473
- }
474
- }
475
-
476
- // Add this after the Cluster constructor
477
- function ColorSelector(a) {
478
- this.coloring = a;
479
- this.display = false;
480
- this.list = this.coloring.find(".list");
481
- this.list.empty();
482
- this.select = this.coloring.find(".select");
483
- this.select.click(function () {
484
- $GP.coloring.toggle();
485
- });
486
- this.toggle = function () {
487
- this.display ? this.hide() : this.show();
488
- };
489
- this.content = function (a) {
490
- this.list.html(a);
491
- this.list.find("a").click(function () {
492
- var a = $(this).attr("data-attr");
493
- changeNodeColors(a);
494
- });
495
- };
496
- this.hide = function () {
497
- this.display = false;
498
- this.list.hide();
499
- this.select.removeClass("close");
500
- };
501
- this.show = function () {
502
- this.display = true;
503
- this.list.show();
504
- this.select.addClass("close");
505
- };
506
- }
507
-
508
-
509
- // Add this function to change node colors
510
- function changeNodeColors(attribute) {
511
- currentColorAttribute = attribute;
512
- $GP.coloring.select.text(attribute);
513
- $GP.coloring.hide();
514
-
515
- // Reset clusters
516
- sigInst.clusters = {};
517
-
518
- // Update node colors based on the selected attribute
519
- sigInst.iterNodes(function (n) {
520
- if (n.attr && n.attr.colors && n.attr.colors[attribute]) {
521
- n.color = n.attr.colors[attribute];
522
- }
523
-
524
- // Update clusters
525
- sigInst.clusters[n.color] || (sigInst.clusters[n.color] = []);
526
- if (sigInst.clusters[n.color].indexOf(n.id) === -1) {
527
- sigInst.clusters[n.color].push(n.id);
528
- }
529
- });
530
-
531
-
532
- // Update node colors based on the selected attribute
533
- sigInst.iterEdges(function (e) {
534
- if (e.attr && e.attr.colors && e.attr.colors[attribute]) {
535
- e.color = e.attr.colors[attribute];
536
- }
537
- });
538
-
539
-
540
- // Update color legend
541
- updateColorLegend();
542
-
543
- // Redraw the graph
544
- sigInst.draw(2, 2, 2);
545
- }
546
-
547
-
548
-
549
- function updateColorLegend() {
550
- var legendColors = {};
551
- var legendHtml = "";
552
-
553
- // Collect unique colors and their values
554
- sigInst.iterNodes(function (n) {
555
- if (n.attr && n.attr.colors && n.attr.colors[currentColorAttribute]) {
556
- var color = n.attr.colors[currentColorAttribute];
557
- var attrValue = "";
558
-
559
- // Try to get the attribute value from node attributes
560
- if (n.attr.attributes && n.attr.attributes[currentColorAttribute]) {
561
- attrValue = n.attr.attributes[currentColorAttribute];
562
- } else {
563
- // If not found in attributes, use a generic label
564
- attrValue = "Value " + Object.keys(legendColors).length;
565
- }
566
-
567
- if (!legendColors[color]) {
568
- legendColors[color] = attrValue;
569
- }
570
- }
571
- });
572
-
573
- // Create legend HTML
574
- for (var color in legendColors) {
575
- legendHtml += '<li><div style="width:20px;height:12px;background:' + color +
576
- ';display:inline-block;margin-right:5px;border:1px solid #ccc;"></div>' +
577
- legendColors[color] + '</li>';
578
- }
579
-
580
- legendHtml += "</ul>";
581
- $("#colorLegend").html(legendHtml);
582
- }
583
-
584
-
585
- function showGroups(a) {
586
- a ? ($GP.intro.find("#showGroups").text("Hide groups"), $GP.bg.show(), $GP.bg2.hide(), $GP.showgroup = !0) : ($GP.intro.find("#showGroups").text("View Groups"), $GP.bg.hide(), $GP.bg2.show(), $GP.showgroup = !1)
587
- }
588
-
589
- function nodeNormal() {
590
- !0 != $GP.calculating && !1 != sigInst.detail && (showGroups(!1), $GP.calculating = !0, sigInst.detail = !0, $GP.info.delay(400).animate({width:'hide'},350),$GP.cluster.hide(), sigInst.iterEdges(function (a) {
591
- a.attr.color = !1;
592
- a.hidden = !1
593
- }), sigInst.iterNodes(function (a) {
594
- a.hidden = !1;
595
- a.attr.color = !1;
596
- a.attr.lineWidth = !1;
597
- a.attr.size = !1
598
- }), sigInst.draw(2, 2, 2, 2), sigInst.neighbors = {}, sigInst.active = !1, $GP.calculating = !1, window.location.hash = "")
599
- }
600
-
601
- function nodeActive(a) {
602
-
603
- var groupByDirection=false;
604
- if (config.informationPanel.groupByEdgeDirection && config.informationPanel.groupByEdgeDirection==true) groupByDirection=true;
605
-
606
- sigInst.neighbors = {};
607
- sigInst.detail = !0;
608
- var b = sigInst._core.graph.nodesIndex[a];
609
- showGroups(!1);
610
- var outgoing={},incoming={},mutual={};//SAH
611
- sigInst.iterEdges(function (b) {
612
- b.attr.lineWidth = !1;
613
- b.hidden = !0;
614
-
615
- n={
616
- name: b.label,
617
- colour: b.color
618
- };
619
-
620
- if (a==b.source) outgoing[b.target]=n; //SAH
621
- else if (a==b.target) incoming[b.source]=n; //SAH
622
- if (a == b.source || a == b.target) sigInst.neighbors[a == b.target ? b.source : b.target] = n;
623
- b.hidden = !1, b.attr.color = "rgba(0, 0, 0, 1)";
624
- });
625
- var f = [];
626
- sigInst.iterNodes(function (a) {
627
- a.hidden = !0;
628
- a.attr.lineWidth = !1;
629
- a.attr.color = a.color
630
- });
631
-
632
- if (groupByDirection) {
633
- //SAH - Compute intersection for mutual and remove these from incoming/outgoing
634
- for (e in outgoing) {
635
- //name=outgoing[e];
636
- if (e in incoming) {
637
- mutual[e]=outgoing[e];
638
- delete incoming[e];
639
- delete outgoing[e];
640
- }
641
- }
642
- }
643
-
644
- var createList=function(c) {
645
- var f = [];
646
- var e = [],
647
- //c = sigInst.neighbors,
648
- g;
649
- for (g in c) {
650
- var d = sigInst._core.graph.nodesIndex[g];
651
- d.hidden = !1;
652
- d.attr.lineWidth = !1;
653
- d.attr.color = c[g].colour;
654
- a != g && e.push({
655
- id: g,
656
- name: d.label,
657
- group: (c[g].name)? c[g].name:"",
658
- colour: c[g].colour
659
- })
660
- }
661
- e.sort(function (a, b) {
662
- var c = a.group.toLowerCase(),
663
- d = b.group.toLowerCase(),
664
- e = a.name.toLowerCase(),
665
- f = b.name.toLowerCase();
666
- return c != d ? c < d ? -1 : c > d ? 1 : 0 : e < f ? -1 : e > f ? 1 : 0
667
- });
668
- d = "";
669
- for (g in e) {
670
- c = e[g];
671
- /*if (c.group != d) {
672
- d = c.group;
673
- f.push('<li class="cf" rel="' + c.color + '"><div class=""></div><div class="">' + d + "</div></li>");
674
- }*/
675
- f.push('<li class="membership"><a href="#' + c.name + '" onmouseover="sigInst._core.plotter.drawHoverNode(sigInst._core.graph.nodesIndex[\'' + c.id + '\'])\" onclick=\"nodeActive(\'' + c.id + '\')" onmouseout="sigInst.refresh()">' + c.name + "</a></li>");
676
- }
677
- return f;
678
- }
679
-
680
- /*console.log("mutual:");
681
- console.log(mutual);
682
- console.log("incoming:");
683
- console.log(incoming);
684
- console.log("outgoing:");
685
- console.log(outgoing);*/
686
-
687
-
688
- var f=[];
689
-
690
- //console.log("neighbors:");
691
- //console.log(sigInst.neighbors);
692
-
693
- if (groupByDirection) {
694
- size=Object.size(mutual);
695
- f.push("<h2>Mututal (" + size + ")</h2>");
696
- (size>0)? f=f.concat(createList(mutual)) : f.push("No mutual links<br>");
697
- size=Object.size(incoming);
698
- f.push("<h2>Incoming (" + size + ")</h2>");
699
- (size>0)? f=f.concat(createList(incoming)) : f.push("No incoming links<br>");
700
- size=Object.size(outgoing);
701
- f.push("<h2>Outgoing (" + size + ")</h2>");
702
- (size>0)? f=f.concat(createList(outgoing)) : f.push("No outgoing links<br>");
703
- } else {
704
- f=f.concat(createList(sigInst.neighbors));
705
- }
706
- //b is object of active node -- SAH
707
- b.hidden = !1;
708
- b.attr.color = b.color;
709
- b.attr.lineWidth = 6;
710
- b.attr.strokeStyle = "#000000";
711
- sigInst.draw(2, 2, 2, 2);
712
-
713
- $GP.info_link.find("ul").html(f.join(""));
714
- $GP.info_link.find("li").each(function () {
715
- var a = $(this),
716
- b = a.attr("rel");
717
- });
718
- f = b.attr;
719
- if (f.attributes) {
720
- var image_attribute = false;
721
- if (config.informationPanel.imageAttribute) {
722
- image_attribute=config.informationPanel.imageAttribute;
723
- }
724
- e = [];
725
-
726
- e.push('<span><strong>Model page:</strong> <a href=\"https://huggingface.co/' + f.attributes['id'] + '\" target=\"_blank\">https://huggingface.co/' + f.attributes['id'] + '</a> </span><br/>')
727
- e.push('<span><strong>Update model information:</strong> <a href=\"https://huggingface.co/'+ f.attributes['id'] + '/edit/main/README.md\" target=\"_blank\">edit</a> </span><br/>')
728
- temp_array = [];
729
- g = 0;
730
- for (var attr in f.attributes) {
731
- var d = f.attributes[attr],
732
- h = "";
733
- if (attr!=image_attribute) {
734
- h = '<span><strong>' + attr + ':</strong> ' + d + '</span><br/>'
735
- }
736
- //temp_array.push(f.attributes[g].attr);
737
- e.push(h)
738
- }
739
-
740
- if (image_attribute) {
741
- //image_index = jQuery.inArray(image_attribute, temp_array);
742
- $GP.info_name.html("<div><img src=" + f.attributes[image_attribute] + " style=\"vertical-align:middle\" /> <span onmouseover=\"sigInst._core.plotter.drawHoverNode(sigInst._core.graph.nodesIndex['" + b.id + '\'])" onmouseout="sigInst.refresh()">' + b.label + "</span></div>");
743
- } else {
744
- $GP.info_name.html("<div><span onmouseover=\"sigInst._core.plotter.drawHoverNode(sigInst._core.graph.nodesIndex['" + b.id + '\'])" onmouseout="sigInst.refresh()">' + b.label + "</span></div>");
745
- }
746
- // Image field for attribute pane
747
- $GP.info_data.html(e.join("<br/>"))
748
- }
749
- $GP.info_data.show();
750
-
751
- $GP.info_p.html("Connections:");
752
- $GP.info.animate({width:'show'},350);
753
- $GP.info_donnees.hide();
754
- $GP.info_donnees.show();
755
- sigInst.active = a;
756
- window.location.hash = b.label;
757
- }
758
-
759
- function showCluster(a) {
760
- var b = sigInst.clusters[a];
761
- if (b && 0 < b.length) {
762
- showGroups(!1);
763
- sigInst.detail = !0;
764
- b.sort();
765
- sigInst.iterEdges(function (a) {
766
- a.hidden = !1;
767
- a.attr.lineWidth = !1;
768
- a.attr.color = !1
769
- });
770
- sigInst.iterNodes(function (a) {
771
- a.hidden = !0
772
- });
773
- for (var f = [], e = [], c = 0, g = b.length; c < g; c++) {
774
- var d = sigInst._core.graph.nodesIndex[b[c]];
775
- !0 == d.hidden && (e.push(b[c]), d.hidden = !1, d.attr.lineWidth = !1, d.attr.color = d.color, f.push('<li class="membership"><a href="#'+d.label+'" onmouseover="sigInst._core.plotter.drawHoverNode(sigInst._core.graph.nodesIndex[\'' + d.id + "'])\" onclick=\"nodeActive('" + d.id + '\')" onmouseout="sigInst.refresh()">' + d.label + "</a></li>"))
776
- }
777
- sigInst.clusters[a] = e;
778
- sigInst.draw(2, 2, 2, 2);
779
- $GP.info_name.html("<b>" + a + "</b>");
780
- $GP.info_data.hide();
781
- $GP.info_p.html("Group Members:");
782
- $GP.info_link.find("ul").html(f.join(""));
783
- $GP.info.animate({width:'show'},350);
784
- $GP.search.clean();
785
- $GP.cluster.hide();
786
- return !0
787
- }
788
- return !1
789
- }
790
-
791
-
792
-
793
- function AtlasSelector(a) {
794
- this.atlas = a;
795
- this.display = false;
796
- this.list = this.atlas.find(".list");
797
- this.list.empty();
798
- this.select = this.atlas.find(".select");
799
- this.select.click(function () {
800
- $GP.atlas.toggle();
801
- });
802
- this.toggle = function () {
803
- this.display ? this.hide() : this.show();
804
- };
805
- this.content = function (a) {
806
- this.list.html(a);
807
- this.list.find("a").click(function () {
808
- var dataFile = $(this).attr("data-file");
809
- loadNewAtlas(dataFile);
810
- });
811
- };
812
- this.hide = function () {
813
- this.display = false;
814
- this.list.hide();
815
- this.select.removeClass("close");
816
- };
817
- this.show = function () {
818
- this.display = true;
819
- this.list.show();
820
- this.select.addClass("close");
821
- };
822
- }
823
-
824
- function getAvailableAtlases() {
825
- return [
826
- { name: "Modalities Atlas (+ Darwin + Trending)", file: "compressed_modalities_data.json.gz" },
827
- { name: "Large NLP Atlas (+ Darwin + Trending)", file: "compressed_large_nlp_data.json.gz" },
828
- { name: "DARWIN Family Only", file: "compressed_darwin_data.json.gz" },
829
- { name: "Hugging Face Galaxy", file: "compressed_galaxy.json.gz" },
830
- ];
831
- }
832
-
833
- function loadNewAtlas(dataFile) {
834
- // Update the currently selected atlas in the dropdown
835
- $GP.atlas.select.text(getAtlasNameByFile(dataFile));
836
- $GP.atlas.hide();
837
-
838
- config.data = dataFile;
839
- reinitializeSigma(config);
840
- }
841
-
842
- function reinitializeSigma(config) {
843
- // Remove the old sigma instance
844
- if (sigInst) {
845
- sigInst.kill();
846
- }
847
-
848
- // Recreate the sigma canvas
849
- $(".sigma-expand").empty();
850
-
851
- // Initialize new sigma instance
852
- initSigma(config);
853
- }
854
-
855
-
856
- function getAtlasNameByFile(dataFile) {
857
- var atlases = getAvailableAtlases();
858
- for (var i = 0; i < atlases.length; i++) {
859
- if (atlases[i].file === dataFile) {
860
- return atlases[i].name;
861
- }
862
- }
863
- return "Unknown Atlas";
864
- }
865
-
 
 
1
+ var sigInst, canvas, $GP
2
+
3
+ //Load configuration file
4
+ var config={};
5
+ var currentColorAttribute = "base_model_relation";
6
+ var currentAtlasFile = "";
7
+
8
+ //For debug allow a config=file.json parameter to specify the config
9
+ function GetQueryStringParams(sParam,defaultVal) {
10
+ var sPageURL = ""+window.location;//.search.substring(1);//This might be causing error in Safari?
11
+ if (sPageURL.indexOf("?")==-1) return defaultVal;
12
+ sPageURL=sPageURL.substr(sPageURL.indexOf("?")+1);
13
+ var sURLVariables = sPageURL.split('&');
14
+ for (var i = 0; i < sURLVariables.length; i++) {
15
+ var sParameterName = sURLVariables[i].split('=');
16
+ if (sParameterName[0] == sParam) {
17
+ return sParameterName[1];
18
+ }
19
+ }
20
+ return defaultVal;
21
+ }
22
+
23
+
24
+ jQuery.getJSON(GetQueryStringParams("config","config.json"), function(data, textStatus, jqXHR) {
25
+ config=data;
26
+
27
+ currentAtlasFile = config.data;
28
+
29
+ if (config.type!="network") {
30
+ //bad config
31
+ alert("Invalid configuration settings.")
32
+ return;
33
+ }
34
+
35
+ //As soon as page is ready (and data ready) set up it
36
+ $(document).ready(setupGUI(config));
37
+ });//End JSON Config load
38
+
39
+
40
+ // FUNCTION DECLARATIONS
41
+
42
+ Object.size = function(obj) {
43
+ var size = 0, key;
44
+ for (key in obj) {
45
+ if (obj.hasOwnProperty(key)) size++;
46
+ }
47
+ return size;
48
+ };
49
+
50
+
51
+ function initSigma(config) {
52
+ var data=config.data
53
+
54
+ var drawProps, graphProps,mouseProps;
55
+ if (config.sigma && config.sigma.drawingProperties)
56
+ drawProps=config.sigma.drawingProperties;
57
+ else
58
+ drawProps={
59
+ defaultLabelColor: "#000",
60
+ defaultLabelSize: 14,
61
+ defaultLabelBGColor: "#ddd",
62
+ defaultHoverLabelBGColor: "#002147",
63
+ defaultLabelHoverColor: "#fff",
64
+ labelThreshold: 10,
65
+ defaultEdgeType: "curve",
66
+ hoverFontStyle: "bold",
67
+ fontStyle: "bold",
68
+ activeFontStyle: "bold"
69
+ };
70
+
71
+ if (config.sigma && config.sigma.graphProperties)
72
+ graphProps=config.sigma.graphProperties;
73
+ else
74
+ graphProps={
75
+ minNodeSize: 1,
76
+ maxNodeSize: 7,
77
+ minEdgeSize: 0.2,
78
+ maxEdgeSize: 0.5
79
+ };
80
+
81
+ if (config.sigma && config.sigma.mouseProperties)
82
+ mouseProps=config.sigma.mouseProperties;
83
+ else
84
+ mouseProps={
85
+ minRatio: 0.75, // How far can we zoom out?
86
+ maxRatio: 20, // How far can we zoom in?
87
+ };
88
+
89
+ var a = sigma.init(document.getElementById("sigma-canvas")).drawingProperties(drawProps).graphProperties(graphProps).mouseProperties(mouseProps);
90
+ sigInst = a;
91
+ a.active = !1;
92
+ a.neighbors = {};
93
+ a.detail = !1;
94
+
95
+
96
+ dataReady = function() {
97
+ a.clusters = {};
98
+
99
+ // Initialize node clusters based on current coloring
100
+ a.iterNodes(function (b) {
101
+ a.clusters[b.color] || (a.clusters[b.color] = []);
102
+ a.clusters[b.color].push(b.id);
103
+
104
+ // Make sure colors are properly copied from the JSON to node.attr
105
+ if (!b.attr) b.attr = {};
106
+ if (b.colors && !b.attr.colors) {
107
+ b.attr.colors = b.colors;
108
+ }
109
+ });
110
+
111
+ a.bind("upnodes", function (a) {
112
+ nodeActive(a.content[0]);
113
+ });
114
+
115
+ a.draw();
116
+ configSigmaElements(config);
117
+
118
+ // Create the color legend
119
+ updateColorLegend();
120
+
121
+ // Find available color attributes from nodes
122
+ var colorAttributes = [];
123
+ var colorAttrsFound = {};
124
+
125
+ a.iterNodes(function(node) {
126
+ if (node.attr && node.attr.colors) {
127
+ for (var attr in node.attr.colors) {
128
+ if (!colorAttrsFound[attr]) {
129
+ colorAttrsFound[attr] = true;
130
+ colorAttributes.push('<div style="line-height:12px"><a href="#" style="color:black;" data-attr="' + attr + '">'+attr+'</a></div>');
131
+ }
132
+ }
133
+ } else if (node.colors) {
134
+ // If colors are in the original structure, copy them to attr
135
+ if (!node.attr) node.attr = {};
136
+ node.attr.colors = node.colors;
137
+
138
+ for (var attr in node.colors) {
139
+ if (!colorAttrsFound[attr]) {
140
+ colorAttrsFound[attr] = true;
141
+ colorAttributes.push('<div style="line-height:12px"><a href="#" style="color:black;" data-attr="' + attr + '">'+attr+'</a></div>');
142
+ }
143
+ }
144
+ }
145
+ });
146
+
147
+ $GP.coloring.content(colorAttributes.join(""));
148
+ $GP.coloring.select.text(currentColorAttribute);
149
+ }
150
+
151
+ if (data.indexOf("gexf")>0 || data.indexOf("xml")>0)
152
+ a.parseGexf(data,dataReady);
153
+ else
154
+ a.parseJson(data,dataReady);
155
+ gexf = sigmaInst = null;
156
+ }
157
+
158
+
159
+ function setupGUI(config) {
160
+ // Initialise main interface elements
161
+ var logo=""; // Logo elements
162
+ if (config.logo.file) {
163
+
164
+ logo = "<img src=\"" + config.logo.file +"\"";
165
+ if (config.logo.text) logo+=" alt=\"" + config.logo.text + "\"";
166
+ logo+=">";
167
+ } else if (config.logo.text) {
168
+ logo="<h1>"+config.logo.text+"</h1>";
169
+ }
170
+ if (config.logo.link) logo="<a href=\"" + config.logo.link + "\">"+logo+"</a>";
171
+ $("#maintitle").html(logo);
172
+
173
+ // #title
174
+ $("#title").html("<h2>"+config.text.title+"</h2>");
175
+
176
+ // #titletext
177
+ $("#titletext").html(config.text.intro);
178
+
179
+ // More information
180
+ if (config.text.more) {
181
+ $("#information").html(config.text.more);
182
+ } else {
183
+ //hide more information link
184
+ $("#moreinformation").hide();
185
+ }
186
+
187
+ // Legend
188
+
189
+ // Node
190
+ if (config.legend.nodeLabel) {
191
+ $(".node").next().html(config.legend.nodeLabel);
192
+ } else {
193
+ //hide more information link
194
+ $(".node").hide();
195
+ }
196
+ // Edge
197
+ if (config.legend.edgeLabel) {
198
+ $(".edge").next().html(config.legend.edgeLabel);
199
+ } else {
200
+ //hide more information link
201
+ $(".edge").hide();
202
+ }
203
+ // Colours
204
+ if (config.legend.nodeLabel) {
205
+ $(".colours").next().html(config.legend.colorLabel);
206
+ } else {
207
+ //hide more information link
208
+ $(".colours").hide();
209
+ }
210
+
211
+
212
+ $GP = {
213
+ calculating: !1,
214
+ showgroup: !1
215
+ };
216
+ $GP.intro = $("#intro");
217
+ $GP.minifier = $GP.intro.find("#minifier");
218
+ $GP.mini = $("#minify");
219
+ $GP.info = $("#attributepane");
220
+ $GP.info_donnees = $GP.info.find(".nodeattributes");
221
+ $GP.info_name = $GP.info.find(".name");
222
+ $GP.info_link = $GP.info.find(".link");
223
+ $GP.info_data = $GP.info.find(".data");
224
+ $GP.info_close = $GP.info.find(".returntext");
225
+ $GP.info_close2 = $GP.info.find(".close");
226
+ $GP.info_p = $GP.info.find(".p");
227
+ $GP.info_close.click(nodeNormal);
228
+ $GP.info_close2.click(nodeNormal);
229
+ $GP.form = $("#mainpanel").find("form");
230
+ $GP.search = new Search($GP.form.find("#search"));
231
+ if (!config.features.search) {
232
+ $("#search").hide();
233
+ }
234
+ if (!config.features.groupSelectorAttribute) {
235
+ $("#attributeselect").hide();
236
+ }
237
+ $GP.cluster = new Cluster($GP.form.find("#attributeselect"));
238
+ $GP.coloring = new ColorSelector($GP.form.find("#coloringselect"));
239
+
240
+
241
+
242
+ $GP.atlas = new AtlasSelector($GP.form.find("#atlasselect"));
243
+ var atlases = getAvailableAtlases();
244
+ var atlasLinks = [];
245
+ for (var i = 0; i < atlases.length; i++) {
246
+ atlasLinks.push('<div style="line-height:12px"><a href="#" data-file="' + atlases[i].file + '" style="color:black;">' + atlases[i].name + '</a></div>');
247
+ }
248
+
249
+ $GP.atlas.content(atlasLinks.join(""));
250
+ $GP.atlas.select.text(atlases[0].name); // Set default atlas name
251
+
252
+
253
+ config.GP=$GP;
254
+ initSigma(config);
255
+ }
256
+
257
+ function configSigmaElements(config) {
258
+ $GP=config.GP;
259
+
260
+ // Node hover behaviour
261
+ if (config.features.hoverBehavior == "dim") {
262
+
263
+ var greyColor = '#ccc';
264
+ sigInst.bind('overnodes',function(event){
265
+ var nodes = event.content;
266
+ var neighbors = {};
267
+ sigInst.iterEdges(function(e){
268
+ if(nodes.indexOf(e.source)<0 && nodes.indexOf(e.target)<0){
269
+ if(!e.attr['grey']){
270
+ e.attr['true_color'] = e.color;
271
+ e.color = greyColor;
272
+ e.attr['grey'] = 1;
273
+ }
274
+ }else{
275
+ e.color = e.attr['grey'] ? e.attr['true_color'] : e.color;
276
+ e.attr['grey'] = 0;
277
+
278
+ neighbors[e.source] = 1;
279
+ neighbors[e.target] = 1;
280
+ }
281
+ }).iterNodes(function(n){
282
+ if(!neighbors[n.id]){
283
+ if(!n.attr['grey']){
284
+ n.attr['true_color'] = n.color;
285
+ n.color = greyColor;
286
+ n.attr['grey'] = 1;
287
+ }
288
+ }else{
289
+ n.color = n.attr['grey'] ? n.attr['true_color'] : n.color;
290
+ n.attr['grey'] = 0;
291
+ }
292
+ }).draw(2,2,2);
293
+ }).bind('outnodes',function(){
294
+ sigInst.iterEdges(function(e){
295
+ e.color = e.attr['grey'] ? e.attr['true_color'] : e.color;
296
+ e.attr['grey'] = 0;
297
+ }).iterNodes(function(n){
298
+ n.color = n.attr['grey'] ? n.attr['true_color'] : n.color;
299
+ n.attr['grey'] = 0;
300
+ }).draw(2,2,2);
301
+ });
302
+
303
+ } else if (config.features.hoverBehavior == "hide") {
304
+
305
+ sigInst.bind('overnodes',function(event){
306
+ var nodes = event.content;
307
+ var neighbors = {};
308
+ sigInst.iterEdges(function(e){
309
+ if(nodes.indexOf(e.source)>=0 || nodes.indexOf(e.target)>=0){
310
+ neighbors[e.source] = 1;
311
+ neighbors[e.target] = 1;
312
+ }
313
+ }).iterNodes(function(n){
314
+ if(!neighbors[n.id]){
315
+ n.hidden = 1;
316
+ }else{
317
+ n.hidden = 0;
318
+ }
319
+ }).draw(2,2,2);
320
+ }).bind('outnodes',function(){
321
+ sigInst.iterEdges(function(e){
322
+ e.hidden = 0;
323
+ }).iterNodes(function(n){
324
+ n.hidden = 0;
325
+ }).draw(2,2,2);
326
+ });
327
+
328
+ }
329
+ $GP.bg = $(sigInst._core.domElements.bg);
330
+ $GP.bg2 = $(sigInst._core.domElements.bg2);
331
+ var a = [],
332
+ b,x=1;
333
+ for (b in sigInst.clusters) a.push('<div style="line-height:12px"><a href="#' + b + '"><div style="width:40px;height:12px;border:1px solid #fff;background:' + b + ';display:inline-block"></div> Group ' + (x++) + ' (' + sigInst.clusters[b].length + ' members)</a></div>');
334
+ //a.sort();
335
+ $GP.cluster.content(a.join(""));
336
+ b = {
337
+ minWidth: 400,
338
+ maxWidth: 800,
339
+ maxHeight: 600
340
+ };// minHeight: 300,
341
+ $("a.fb").fancybox(b);
342
+ $("#zoom").find("div.z").each(function () {
343
+ var a = $(this),
344
+ b = a.attr("rel");
345
+ a.click(function () {
346
+ if (b == "center") {
347
+ sigInst.position(0,0,1).draw();
348
+ } else {
349
+ var a = sigInst._core;
350
+ sigInst.zoomTo(a.domElements.nodes.width / 2, a.domElements.nodes.height / 2, a.mousecaptor.ratio * ("in" == b ? 1.5 : 0.5));
351
+ }
352
+
353
+ })
354
+ });
355
+ $GP.mini.click(function () {
356
+ $GP.mini.hide();
357
+ $GP.intro.show();
358
+ $GP.minifier.show()
359
+ });
360
+ $GP.minifier.click(function () {
361
+ $GP.intro.hide();
362
+ $GP.minifier.hide();
363
+ $GP.mini.show()
364
+ });
365
+ $GP.intro.find("#showGroups").click(function () {
366
+ !0 == $GP.showgroup ? showGroups(!1) : showGroups(!0)
367
+ });
368
+ a = window.location.hash.substr(1);
369
+ if (0 < a.length) switch (a) {
370
+ case "Groups":
371
+ showGroups(!0);
372
+ break;
373
+ case "information":
374
+ $.fancybox.open($("#information"), b);
375
+ break;
376
+ default:
377
+ $GP.search.exactMatch = !0, $GP.search.search(a)
378
+ $GP.search.clean();
379
+ }
380
+ // $GP.coloring = new ColorSelector($GP.form.find("#coloringselect"));
381
+
382
+ }
383
+
384
+ function Search(a) {
385
+ this.input = a.find("input[name=search]");
386
+ this.state = a.find(".state");
387
+ this.results = a.find(".results");
388
+ this.exactMatch = !1;
389
+ this.lastSearch = "";
390
+ this.searching = !1;
391
+ var b = this;
392
+ this.input.focus(function () {
393
+ var a = $(this);
394
+ a.data("focus") || (a.data("focus", !0), a.removeClass("empty"));
395
+ b.clean()
396
+ });
397
+ this.input.keydown(function (a) {
398
+ if (13 == a.which) return b.state.addClass("searching"), b.search(b.input.val()), !1
399
+ });
400
+ this.state.click(function () {
401
+ var a = b.input.val();
402
+ b.searching && a == b.lastSearch ? b.close() : (b.state.addClass("searching"), b.search(a))
403
+ });
404
+ this.dom = a;
405
+ this.close = function () {
406
+ this.state.removeClass("searching");
407
+ this.results.hide();
408
+ this.searching = !1;
409
+ this.input.val("");//SAH -- let's erase string when we close
410
+ nodeNormal()
411
+ };
412
+ this.clean = function () {
413
+ this.results.empty().hide();
414
+ this.state.removeClass("searching");
415
+ this.input.val("");
416
+ };
417
+ this.search = function (a) {
418
+ var b = !1,
419
+ c = [],
420
+ b = this.exactMatch ? ("^" + a + "$").toLowerCase() : a.toLowerCase(),
421
+ g = RegExp(b);
422
+ this.exactMatch = !1;
423
+ this.searching = !0;
424
+ this.lastSearch = a;
425
+ this.results.empty();
426
+ if (2 >= a.length) this.results.html("<i>You must search for a name with a minimum of 3 letters.</i>");
427
+ else {
428
+ sigInst.iterNodes(function (a) {
429
+ g.test(a.label.toLowerCase()) && c.push({
430
+ id: a.id,
431
+ name: a.label
432
+ })
433
+ });
434
+ c.length ? (b = !0, nodeActive(c[0].id)) : b = showCluster(a);
435
+ a = ["<b>Search Results: </b>"];
436
+ if (1 < c.length) for (var d = 0, h = c.length; d < h; d++) a.push('<a href="#' + c[d].name + '" onclick="nodeActive(\'' + c[d].id + "')\">" + c[d].name + "</a>");
437
+ 0 == c.length && !b && a.push("<i>No results found.</i>");
438
+ 1 < a.length && this.results.html(a.join(""));
439
+ }
440
+ if(c.length!=1) this.results.show();
441
+ if(c.length==1) this.results.hide();
442
+ }
443
+ }
444
+
445
+ function Cluster(a) {
446
+ this.cluster = a;
447
+ this.display = !1;
448
+ this.list = this.cluster.find(".list");
449
+ this.list.empty();
450
+ this.select = this.cluster.find(".select");
451
+ this.select.click(function () {
452
+ $GP.cluster.toggle()
453
+ });
454
+ this.toggle = function () {
455
+ this.display ? this.hide() : this.show()
456
+ };
457
+ this.content = function (a) {
458
+ this.list.html(a);
459
+ this.list.find("a").click(function () {
460
+ var a = $(this).attr("href").substr(1);
461
+ showCluster(a)
462
+ })
463
+ };
464
+ this.hide = function () {
465
+ this.display = !1;
466
+ this.list.hide();
467
+ this.select.removeClass("close")
468
+ };
469
+ this.show = function () {
470
+ this.display = !0;
471
+ this.list.show();
472
+ this.select.addClass("close")
473
+ }
474
+ }
475
+
476
+ // Add this after the Cluster constructor
477
+ function ColorSelector(a) {
478
+ this.coloring = a;
479
+ this.display = false;
480
+ this.list = this.coloring.find(".list");
481
+ this.list.empty();
482
+ this.select = this.coloring.find(".select");
483
+ this.select.click(function () {
484
+ $GP.coloring.toggle();
485
+ });
486
+ this.toggle = function () {
487
+ this.display ? this.hide() : this.show();
488
+ };
489
+ this.content = function (a) {
490
+ this.list.html(a);
491
+ this.list.find("a").click(function () {
492
+ var a = $(this).attr("data-attr");
493
+ changeNodeColors(a);
494
+ });
495
+ };
496
+ this.hide = function () {
497
+ this.display = false;
498
+ this.list.hide();
499
+ this.select.removeClass("close");
500
+ };
501
+ this.show = function () {
502
+ this.display = true;
503
+ this.list.show();
504
+ this.select.addClass("close");
505
+ };
506
+ }
507
+
508
+
509
+ // Add this function to change node colors
510
+ function changeNodeColors(attribute) {
511
+ currentColorAttribute = attribute;
512
+ $GP.coloring.select.text(attribute);
513
+ $GP.coloring.hide();
514
+
515
+ // Reset clusters
516
+ sigInst.clusters = {};
517
+
518
+ // Update node colors based on the selected attribute
519
+ sigInst.iterNodes(function (n) {
520
+ if (n.attr && n.attr.colors && n.attr.colors[attribute]) {
521
+ n.color = n.attr.colors[attribute];
522
+ }
523
+
524
+ // Update clusters
525
+ sigInst.clusters[n.color] || (sigInst.clusters[n.color] = []);
526
+ if (sigInst.clusters[n.color].indexOf(n.id) === -1) {
527
+ sigInst.clusters[n.color].push(n.id);
528
+ }
529
+ });
530
+
531
+
532
+ // Update node colors based on the selected attribute
533
+ sigInst.iterEdges(function (e) {
534
+ if (e.attr && e.attr.colors && e.attr.colors[attribute]) {
535
+ e.color = e.attr.colors[attribute];
536
+ }
537
+ });
538
+
539
+
540
+ // Update color legend
541
+ updateColorLegend();
542
+
543
+ // Redraw the graph
544
+ sigInst.draw(2, 2, 2);
545
+ }
546
+
547
+
548
+
549
+ function updateColorLegend() {
550
+ var legendColors = {};
551
+ var legendHtml = "";
552
+
553
+ // Collect unique colors and their values
554
+ sigInst.iterNodes(function (n) {
555
+ if (n.attr && n.attr.colors && n.attr.colors[currentColorAttribute]) {
556
+ var color = n.attr.colors[currentColorAttribute];
557
+ var attrValue = "";
558
+
559
+ // Try to get the attribute value from node attributes
560
+ if (n.attr.attributes && n.attr.attributes[currentColorAttribute]) {
561
+ attrValue = n.attr.attributes[currentColorAttribute];
562
+ } else {
563
+ // If not found in attributes, use a generic label
564
+ attrValue = "Value " + Object.keys(legendColors).length;
565
+ }
566
+
567
+ if (!legendColors[color]) {
568
+ legendColors[color] = attrValue;
569
+ }
570
+ }
571
+ });
572
+
573
+ // Create legend HTML
574
+ for (var color in legendColors) {
575
+ legendHtml += '<li><div style="width:20px;height:12px;background:' + color +
576
+ ';display:inline-block;margin-right:5px;border:1px solid #ccc;"></div>' +
577
+ legendColors[color] + '</li>';
578
+ }
579
+
580
+ legendHtml += "</ul>";
581
+ $("#colorLegend").html(legendHtml);
582
+ }
583
+
584
+
585
+ function showGroups(a) {
586
+ a ? ($GP.intro.find("#showGroups").text("Hide groups"), $GP.bg.show(), $GP.bg2.hide(), $GP.showgroup = !0) : ($GP.intro.find("#showGroups").text("View Groups"), $GP.bg.hide(), $GP.bg2.show(), $GP.showgroup = !1)
587
+ }
588
+
589
+ function nodeNormal() {
590
+ !0 != $GP.calculating && !1 != sigInst.detail && (showGroups(!1), $GP.calculating = !0, sigInst.detail = !0, $GP.info.delay(400).animate({width:'hide'},350),$GP.cluster.hide(), sigInst.iterEdges(function (a) {
591
+ a.attr.color = !1;
592
+ a.hidden = !1
593
+ }), sigInst.iterNodes(function (a) {
594
+ a.hidden = !1;
595
+ a.attr.color = !1;
596
+ a.attr.lineWidth = !1;
597
+ a.attr.size = !1
598
+ }), sigInst.draw(2, 2, 2, 2), sigInst.neighbors = {}, sigInst.active = !1, $GP.calculating = !1, window.location.hash = "")
599
+ }
600
+
601
+ function nodeActive(a) {
602
+
603
+ var groupByDirection=false;
604
+ if (config.informationPanel.groupByEdgeDirection && config.informationPanel.groupByEdgeDirection==true) groupByDirection=true;
605
+
606
+ sigInst.neighbors = {};
607
+ sigInst.detail = !0;
608
+ var b = sigInst._core.graph.nodesIndex[a];
609
+ showGroups(!1);
610
+ var outgoing={},incoming={},mutual={};//SAH
611
+ sigInst.iterEdges(function (b) {
612
+ b.attr.lineWidth = !1;
613
+ b.hidden = !0;
614
+
615
+ n={
616
+ name: b.label,
617
+ colour: b.color
618
+ };
619
+
620
+ if (a==b.source) outgoing[b.target]=n; //SAH
621
+ else if (a==b.target) incoming[b.source]=n; //SAH
622
+ if (a == b.source || a == b.target) sigInst.neighbors[a == b.target ? b.source : b.target] = n;
623
+ b.hidden = !1, b.attr.color = "rgba(0, 0, 0, 1)";
624
+ });
625
+ var f = [];
626
+ sigInst.iterNodes(function (a) {
627
+ a.hidden = !0;
628
+ a.attr.lineWidth = !1;
629
+ a.attr.color = a.color
630
+ });
631
+
632
+ if (groupByDirection) {
633
+ //SAH - Compute intersection for mutual and remove these from incoming/outgoing
634
+ for (e in outgoing) {
635
+ //name=outgoing[e];
636
+ if (e in incoming) {
637
+ mutual[e]=outgoing[e];
638
+ delete incoming[e];
639
+ delete outgoing[e];
640
+ }
641
+ }
642
+ }
643
+
644
+ var createList=function(c) {
645
+ var f = [];
646
+ var e = [],
647
+ //c = sigInst.neighbors,
648
+ g;
649
+ for (g in c) {
650
+ var d = sigInst._core.graph.nodesIndex[g];
651
+ d.hidden = !1;
652
+ d.attr.lineWidth = !1;
653
+ d.attr.color = c[g].colour;
654
+ a != g && e.push({
655
+ id: g,
656
+ name: d.label,
657
+ group: (c[g].name)? c[g].name:"",
658
+ colour: c[g].colour
659
+ })
660
+ }
661
+ e.sort(function (a, b) {
662
+ var c = a.group.toLowerCase(),
663
+ d = b.group.toLowerCase(),
664
+ e = a.name.toLowerCase(),
665
+ f = b.name.toLowerCase();
666
+ return c != d ? c < d ? -1 : c > d ? 1 : 0 : e < f ? -1 : e > f ? 1 : 0
667
+ });
668
+ d = "";
669
+ for (g in e) {
670
+ c = e[g];
671
+ /*if (c.group != d) {
672
+ d = c.group;
673
+ f.push('<li class="cf" rel="' + c.color + '"><div class=""></div><div class="">' + d + "</div></li>");
674
+ }*/
675
+ f.push('<li class="membership"><a href="#' + c.name + '" onmouseover="sigInst._core.plotter.drawHoverNode(sigInst._core.graph.nodesIndex[\'' + c.id + '\'])\" onclick=\"nodeActive(\'' + c.id + '\')" onmouseout="sigInst.refresh()">' + c.name + "</a></li>");
676
+ }
677
+ return f;
678
+ }
679
+
680
+ /*console.log("mutual:");
681
+ console.log(mutual);
682
+ console.log("incoming:");
683
+ console.log(incoming);
684
+ console.log("outgoing:");
685
+ console.log(outgoing);*/
686
+
687
+
688
+ var f=[];
689
+
690
+ //console.log("neighbors:");
691
+ //console.log(sigInst.neighbors);
692
+
693
+ if (groupByDirection) {
694
+ size=Object.size(mutual);
695
+ f.push("<h2>Mututal (" + size + ")</h2>");
696
+ (size>0)? f=f.concat(createList(mutual)) : f.push("No mutual links<br>");
697
+ size=Object.size(incoming);
698
+ f.push("<h2>Incoming (" + size + ")</h2>");
699
+ (size>0)? f=f.concat(createList(incoming)) : f.push("No incoming links<br>");
700
+ size=Object.size(outgoing);
701
+ f.push("<h2>Outgoing (" + size + ")</h2>");
702
+ (size>0)? f=f.concat(createList(outgoing)) : f.push("No outgoing links<br>");
703
+ } else {
704
+ f=f.concat(createList(sigInst.neighbors));
705
+ }
706
+ //b is object of active node -- SAH
707
+ b.hidden = !1;
708
+ b.attr.color = b.color;
709
+ b.attr.lineWidth = 6;
710
+ b.attr.strokeStyle = "#000000";
711
+ sigInst.draw(2, 2, 2, 2);
712
+
713
+ $GP.info_link.find("ul").html(f.join(""));
714
+ $GP.info_link.find("li").each(function () {
715
+ var a = $(this),
716
+ b = a.attr("rel");
717
+ });
718
+ f = b.attr;
719
+ if (f.attributes) {
720
+ var image_attribute = false;
721
+ if (config.informationPanel.imageAttribute) {
722
+ image_attribute=config.informationPanel.imageAttribute;
723
+ }
724
+ e = [];
725
+
726
+ e.push('<span><strong>Model page:</strong> <a href=\"https://huggingface.co/' + f.attributes['id'] + '\" target=\"_blank\">https://huggingface.co/' + f.attributes['id'] + '</a> </span><br/>')
727
+ e.push('<span><strong>Update model information:</strong> <a href=\"https://huggingface.co/'+ f.attributes['id'] + '/edit/main/README.md\" target=\"_blank\">edit</a> </span><br/>')
728
+ temp_array = [];
729
+ g = 0;
730
+ for (var attr in f.attributes) {
731
+ var d = f.attributes[attr],
732
+ h = "";
733
+ if (attr!=image_attribute) {
734
+ h = '<span><strong>' + attr + ':</strong> ' + d + '</span><br/>'
735
+ }
736
+ //temp_array.push(f.attributes[g].attr);
737
+ e.push(h)
738
+ }
739
+
740
+ if (image_attribute) {
741
+ //image_index = jQuery.inArray(image_attribute, temp_array);
742
+ $GP.info_name.html("<div><img src=" + f.attributes[image_attribute] + " style=\"vertical-align:middle\" /> <span onmouseover=\"sigInst._core.plotter.drawHoverNode(sigInst._core.graph.nodesIndex['" + b.id + '\'])" onmouseout="sigInst.refresh()">' + b.label + "</span></div>");
743
+ } else {
744
+ $GP.info_name.html("<div><span onmouseover=\"sigInst._core.plotter.drawHoverNode(sigInst._core.graph.nodesIndex['" + b.id + '\'])" onmouseout="sigInst.refresh()">' + b.label + "</span></div>");
745
+ }
746
+ // Image field for attribute pane
747
+ $GP.info_data.html(e.join("<br/>"))
748
+ }
749
+ $GP.info_data.show();
750
+
751
+ $GP.info_p.html("Connections:");
752
+ $GP.info.animate({width:'show'},350);
753
+ $GP.info_donnees.hide();
754
+ $GP.info_donnees.show();
755
+ sigInst.active = a;
756
+ window.location.hash = b.label;
757
+ }
758
+
759
+ function showCluster(a) {
760
+ var b = sigInst.clusters[a];
761
+ if (b && 0 < b.length) {
762
+ showGroups(!1);
763
+ sigInst.detail = !0;
764
+ b.sort();
765
+ sigInst.iterEdges(function (a) {
766
+ a.hidden = !1;
767
+ a.attr.lineWidth = !1;
768
+ a.attr.color = !1
769
+ });
770
+ sigInst.iterNodes(function (a) {
771
+ a.hidden = !0
772
+ });
773
+ for (var f = [], e = [], c = 0, g = b.length; c < g; c++) {
774
+ var d = sigInst._core.graph.nodesIndex[b[c]];
775
+ !0 == d.hidden && (e.push(b[c]), d.hidden = !1, d.attr.lineWidth = !1, d.attr.color = d.color, f.push('<li class="membership"><a href="#'+d.label+'" onmouseover="sigInst._core.plotter.drawHoverNode(sigInst._core.graph.nodesIndex[\'' + d.id + "'])\" onclick=\"nodeActive('" + d.id + '\')" onmouseout="sigInst.refresh()">' + d.label + "</a></li>"))
776
+ }
777
+ sigInst.clusters[a] = e;
778
+ sigInst.draw(2, 2, 2, 2);
779
+ $GP.info_name.html("<b>" + a + "</b>");
780
+ $GP.info_data.hide();
781
+ $GP.info_p.html("Group Members:");
782
+ $GP.info_link.find("ul").html(f.join(""));
783
+ $GP.info.animate({width:'show'},350);
784
+ $GP.search.clean();
785
+ $GP.cluster.hide();
786
+ return !0
787
+ }
788
+ return !1
789
+ }
790
+
791
+
792
+
793
+ function AtlasSelector(a) {
794
+ this.atlas = a;
795
+ this.display = false;
796
+ this.list = this.atlas.find(".list");
797
+ this.list.empty();
798
+ this.select = this.atlas.find(".select");
799
+ this.select.click(function () {
800
+ $GP.atlas.toggle();
801
+ });
802
+ this.toggle = function () {
803
+ this.display ? this.hide() : this.show();
804
+ };
805
+ this.content = function (a) {
806
+ this.list.html(a);
807
+ this.list.find("a").click(function () {
808
+ var dataFile = $(this).attr("data-file");
809
+ loadNewAtlas(dataFile);
810
+ });
811
+ };
812
+ this.hide = function () {
813
+ this.display = false;
814
+ this.list.hide();
815
+ this.select.removeClass("close");
816
+ };
817
+ this.show = function () {
818
+ this.display = true;
819
+ this.list.show();
820
+ this.select.addClass("close");
821
+ };
822
+ }
823
+
824
+ function getAvailableAtlases() {
825
+ return [
826
+ { name: "Modalities Atlas (+ Darwin + Trending)", file: "compressed_modalities_data.json.gz" },
827
+ { name: "Large NLP Atlas (+ Darwin + Trending)", file: "compressed_large_nlp_data.json.gz" },
828
+ { name: "DARWIN Family Only", file: "compressed_darwin_data.json.gz" },
829
+ { name: "Hugging Face Galaxy", file: "compressed_galaxy.json.gz" },
830
+ { name: "๐ŸŒณ Darwin Lineage (full HF coverage)", file: "compressed_darwin_lineage_data.json.gz" },
831
+ ];
832
+ }
833
+
834
+ function loadNewAtlas(dataFile) {
835
+ // Update the currently selected atlas in the dropdown
836
+ $GP.atlas.select.text(getAtlasNameByFile(dataFile));
837
+ $GP.atlas.hide();
838
+
839
+ config.data = dataFile;
840
+ reinitializeSigma(config);
841
+ }
842
+
843
+ function reinitializeSigma(config) {
844
+ // Remove the old sigma instance
845
+ if (sigInst) {
846
+ sigInst.kill();
847
+ }
848
+
849
+ // Recreate the sigma canvas
850
+ $(".sigma-expand").empty();
851
+
852
+ // Initialize new sigma instance
853
+ initSigma(config);
854
+ }
855
+
856
+
857
+ function getAtlasNameByFile(dataFile) {
858
+ var atlases = getAvailableAtlases();
859
+ for (var i = 0; i < atlases.length; i++) {
860
+ if (atlases[i].file === dataFile) {
861
+ return atlases[i].name;
862
+ }
863
+ }
864
+ return "Unknown Atlas";
865
+ }
866
+