- 1 :
/**
- 2 :
* ScatterPlot is a graph visualization of how words cluster in a corpus document similarity, correspondence analysis or principal component analysis.
- 3 :
*
- 4 :
* @example
- 5 :
*
- 6 :
* let config = {
- 7 :
* "analysis": null,
- 8 :
* "bins": null,
- 9 :
* "clusters": null,
- 10 :
* "comparisonType": null,
- 11 :
* "dimensions": null,
- 12 :
* "docId": null,
- 13 :
* "iterations": null,
- 14 :
* "label": null,
- 15 :
* "limit": null,
- 16 :
* "perplexity": null,
- 17 :
* "query": null,
- 18 :
* "stopList": null,
- 19 :
* "storeJson": null,
- 20 :
* "target": null,
- 21 :
* "term": null,
- 22 :
* "whitelist": null,
- 23 :
* };
- 24 :
*
- 25 :
* loadCorpus("austen").tool("scatterplot", config);
- 26 :
*
- 27 :
* @class ScatterPlot
- 28 :
* @tutorial scatterplot
- 29 :
* @memberof Tools
- 30 :
*/
- 31 :
Ext.define('Voyant.panel.ScatterPlot', {
- 32 :
extend: 'Ext.panel.Panel',
- 33 :
mixins: ['Voyant.panel.Panel'],
- 34 :
requires: ['Ext.chart.CartesianChart'],
- 35 :
alias: 'widget.scatterplot',
- 36 :
statics: {
- 37 :
i18n: {
- 38 :
},
- 39 :
api: {
- 40 :
/**
- 41 :
* @memberof Tools.ScatterPlot
- 42 :
* @instance
- 43 :
* @property {docId}
- 44 :
*/
- 45 :
docId: undefined,
- 46 :
- 47 :
/**
- 48 :
* @memberof Tools.ScatterPlot
- 49 :
* @instance
- 50 :
* @property {String} analysis The type of analysis to perform. Options are: 'ca', 'pca', 'tsne', and 'docSim'.
- 51 :
*/
- 52 :
analysis: 'ca',
- 53 :
- 54 :
/**
- 55 :
* @memberof Tools.ScatterPlot
- 56 :
* @instance
- 57 :
* @property {limit}
- 58 :
* @default
- 59 :
*/
- 60 :
limit: 50,
- 61 :
- 62 :
/**
- 63 :
* @memberof Tools.ScatterPlot
- 64 :
* @instance
- 65 :
* @property {Number} dimensions The number of dimensions to render, either 2 or 3.
- 66 :
* @default
- 67 :
*/
- 68 :
dimensions: 3,
- 69 :
- 70 :
/**
- 71 :
* @memberof Tools.ScatterPlot
- 72 :
* @instance
- 73 :
* @property {bins}
- 74 :
* @default
- 75 :
*/
- 76 :
bins: 10,
- 77 :
- 78 :
/**
- 79 :
* @memberof Tools.ScatterPlot
- 80 :
* @instance
- 81 :
* @property {Number} clusters The number of clusters within which to group words.
- 82 :
* @default
- 83 :
*/
- 84 :
clusters: 3,
- 85 :
- 86 :
/**
- 87 :
* @memberof Tools.ScatterPlot
- 88 :
* @instance
- 89 :
* @property {Number} perplexity The TSNE perplexity value.
- 90 :
* @default
- 91 :
*/
- 92 :
perplexity: 15,
- 93 :
- 94 :
/**
- 95 :
* @memberof Tools.ScatterPlot
- 96 :
* @instance
- 97 :
* @property {Number} iterations The TSNE iterations value.
- 98 :
* @default
- 99 :
*/
- 100 :
iterations: 1500,
- 101 :
- 102 :
/**
- 103 :
* @memberof Tools.ScatterPlot
- 104 :
* @instance
- 105 :
* @property {String} comparisonType The value to use for comparing terms. Options are: 'raw', 'relative', and 'tfidf'.
- 106 :
* @default
- 107 :
*/
- 108 :
comparisonType: 'relative',
- 109 :
- 110 :
/**
- 111 :
* @memberof Tools.ScatterPlot
- 112 :
* @instance
- 113 :
* @property {stopList}
- 114 :
* @default
- 115 :
*/
- 116 :
stopList: 'auto',
- 117 :
- 118 :
/**
- 119 :
* @memberof Tools.ScatterPlot
- 120 :
* @instance
- 121 :
* @property {String} target The term to set as the target. This will filter results to terms that are near the target.
- 122 :
*/
- 123 :
target: undefined,
- 124 :
- 125 :
/**
- 126 :
* @memberof Tools.ScatterPlot
- 127 :
* @instance
- 128 :
* @property {String[]} term Used in combination with "target" as a white list of terms to keep.
- 129 :
*/
- 130 :
term: undefined,
- 131 :
- 132 :
/**
- 133 :
* @memberof Tools.ScatterPlot
- 134 :
* @instance
- 135 :
* @property {query}
- 136 :
*/
- 137 :
query: undefined,
- 138 :
- 139 :
/**
- 140 :
* @memberof Tools.ScatterPlot
- 141 :
* @instance
- 142 :
* @property {String} whitelist TODO Unused or only used in CA?
- 143 :
*/
- 144 :
whitelist: undefined,
- 145 :
- 146 :
/**
- 147 :
* @memberof Tools.ScatterPlot
- 148 :
* @instance
- 149 :
* @property {String[]} label The label types to show. One or more of: 'summary', 'docs', and 'terms'.
- 150 :
*/
- 151 :
label: ['summary', 'docs', 'terms'],
- 152 :
- 153 :
/**
- 154 :
* @memberof Tools.ScatterPlot
- 155 :
* @instance
- 156 :
* @property {String} storeJson TODO used in embed
- 157 :
*/
- 158 :
storeJson: undefined
- 159 :
},
- 160 :
glyph: 'xf06e@FontAwesome'
- 161 :
},
- 162 :
config: {
- 163 :
options: [{xtype: 'stoplistoption'},{xtype: 'categoriesoption'}],
- 164 :
caStore: null,
- 165 :
pcaStore: null,
- 166 :
tsneStore: null,
- 167 :
docSimStore: null,
- 168 :
termStore: null,
- 169 :
chartMenu: null,
- 170 :
newTerm: null,
- 171 :
termsTimeout: null,
- 172 :
highlightData: {x: 0, y: 0, r: 0},
- 173 :
highlightTask: null
- 174 :
},
- 175 :
- 176 :
tokenFreqTipTemplate: null,
- 177 :
docFreqTipTemplate: null,
- 178 :
- 179 :
constructor: function(config) {
- 180 :
this.mixins['Voyant.util.Api'].constructor.apply(this, arguments);
- 181 :
if ("storeJson" in config) {
- 182 :
var json = JSON.parse(config.storeJson);
- 183 :
Ext.apply(config, json);
- 184 :
}
- 185 :
this.callParent(arguments);
- 186 :
this.mixins['Voyant.panel.Panel'].constructor.apply(this, arguments);
- 187 :
},
- 188 :
- 189 :
initComponent: function() {
- 190 :
this.setCaStore(Ext.create('Voyant.data.store.CAAnalysis', {
- 191 :
listeners: {load: this.maskAndBuildChart, scope: this}
- 192 :
}));
- 193 :
this.setPcaStore(Ext.create('Voyant.data.store.PCAAnalysis', {
- 194 :
listeners: {load: this.maskAndBuildChart, scope: this}
- 195 :
}));
- 196 :
this.setTsneStore(Ext.create('Voyant.data.store.TSNEAnalysis', {
- 197 :
listeners: {load: this.maskAndBuildChart, scope: this}
- 198 :
}));
- 199 :
this.setDocSimStore(Ext.create('Voyant.data.store.DocSimAnalysis', {
- 200 :
listeners: {load: this.maskAndBuildChart, scope: this}
- 201 :
}));
- 202 :
- 203 :
this.setTermStore(Ext.create('Ext.data.JsonStore', {
- 204 :
fields: [
- 205 :
{name: 'term'},
- 206 :
{name: 'rawFreq', type: 'int'},
- 207 :
{name: 'relativeFreq', type: 'number'},
- 208 :
{name: 'coordinates', mapping : 'vector'},
- 209 :
{name: 'category'}
- 210 :
],
- 211 :
sorters: [{property: 'rawFreq', direction: 'DESC'}],
- 212 :
groupField: 'category'
- 213 :
}));
- 214 :
- 215 :
this.setChartMenu(Ext.create('Ext.menu.Menu', {
- 216 :
items: [
- 217 :
{text: this.localize('remove'), itemId: 'remove', glyph: 'xf068@FontAwesome'},
- 218 :
{text: this.localize('nearby'), itemId: 'nearby', glyph: 'xf0b2@FontAwesome'}
- 219 :
],
- 220 :
listeners: {
- 221 :
hide: function() {
- 222 :
var series = this.down('#chart').getSeries();
- 223 :
series[0].enableToolTips();
- 224 :
series[1].enableToolTips();
- 225 :
},
- 226 :
scope: this
- 227 :
}
- 228 :
}));
- 229 :
- 230 :
this.tokenFreqTipTemplate = new Ext.Template(this.localize('tokenFreqTip'));
- 231 :
this.docFreqTipTemplate = new Ext.Template(this.localize('docFreqTip'));
- 232 :
- 233 :
Ext.apply(this, {
- 234 :
title: this.localize('title'),
- 235 :
layout: 'border',
- 236 :
autoDestroy: true,
- 237 :
items: [{
- 238 :
itemId: 'chartParent',
- 239 :
region: 'center',
- 240 :
layout: 'fit',
- 241 :
tbar: {
- 242 :
overflowHandler: 'scroller',
- 243 :
items: [{
- 244 :
xtype: 'querysearchfield',
- 245 :
itemId: 'filterTerms',
- 246 :
width: 150
- 247 :
},{
- 248 :
text: this.localize('labels'),
- 249 :
itemId: 'labels',
- 250 :
glyph: 'xf02b@FontAwesome',
- 251 :
menu: {
- 252 :
items: [
- 253 :
{text: this.localize("summaryLabel"), itemId: 'summary', xtype: 'menucheckitem'},
- 254 :
{text: this.localize("docsLabel"), itemId: 'docs', xtype: 'menucheckitem'},
- 255 :
{text: this.localize("termsLabel"), itemId: 'terms', xtype: 'menucheckitem'}
- 256 :
],
- 257 :
listeners: {
- 258 :
afterrender: function(menu) {
- 259 :
var labels = this.getApiParam('label');
- 260 :
menu.items.each(function(item) {
- 261 :
item.setChecked(labels.indexOf(item.getItemId())>-1)
- 262 :
})
- 263 :
},
- 264 :
click: function(menu, item) {
- 265 :
var labels = this.getApiParam("label");
- 266 :
var label = item.getItemId();
- 267 :
if (Ext.isString(labels)) {labels = [labels]}
- 268 :
if (item.checked && labels.indexOf(label)==-1) {
- 269 :
labels.push(label)
- 270 :
} else if (!item.checked && labels.indexOf(label)>-1) {
- 271 :
labels = labels.filter(function(item) {return item!=label})
- 272 :
}
- 273 :
this.setApiParam("label", labels);
- 274 :
this.doLabels();
- 275 :
this.queryById('chart').redraw();
- 276 :
},
- 277 :
scope: this
- 278 :
}
- 279 :
}
- 280 :
}]
- 281 :
- 282 :
},
- 283 :
listeners: {
- 284 :
query: function(component, value) {
- 285 :
this.getTermStore().filter([{property: 'term', value: value, anyMatch: true}]);
- 286 :
this.filterChart(value);
- 287 :
},
- 288 :
scope: this
- 289 :
}
- 290 :
},{
- 291 :
itemId: 'optionsPanel',
- 292 :
title: this.localize('options'),
- 293 :
region: 'west',
- 294 :
split: true,
- 295 :
collapsible: true,
- 296 :
collapseMode: 'header',
- 297 :
width: 135,
- 298 :
scrollable: 'y',
- 299 :
layout: {
- 300 :
type: 'vbox',
- 301 :
align: 'stretch'
- 302 :
},
- 303 :
defaults: {
- 304 :
xtype: 'button',
- 305 :
margin: '5',
- 306 :
labelAlign: 'top'
- 307 :
},
- 308 :
items: [{
- 309 :
xtype: 'label',
- 310 :
text: this.localize('input')
- 311 :
},{
- 312 :
xtype: 'documentselectorbutton'
- 313 :
},{
- 314 :
text: this.localize('freqsMode'),
- 315 :
itemId: 'comparisonType',
- 316 :
glyph: 'xf201@FontAwesome',
- 317 :
tooltip: this.localize('freqsModeTip'),
- 318 :
menu: {
- 319 :
items: [
- 320 :
{text: this.localize("rawFrequencies"), itemId: 'comparisonType_raw', group: 'freqsMode', xtype: 'menucheckitem'},
- 321 :
{text: this.localize("relativeFrequencies"), itemId: 'comparisonType_relative', group: 'freqsMode', xtype: 'menucheckitem'},
- 322 :
{text: this.localize("tfidf"), itemId: 'comparisonType_tfidf', group: 'freqsMode', xtype: 'menucheckitem'}
- 323 :
],
- 324 :
listeners: {
- 325 :
click: function(menu, item) {
- 326 :
if (item !== undefined) {
- 327 :
var type = item.getItemId().split('_')[1];
- 328 :
if (type !== this.getApiParam('comparisonType')) {
- 329 :
this.setApiParam('comparisonType', type);
- 330 :
this.loadFromApis(true);
- 331 :
}
- 332 :
}
- 333 :
},
- 334 :
scope: this
- 335 :
}
- 336 :
}
- 337 :
},{
- 338 :
fieldLabel: this.localize('numTerms'),
- 339 :
itemId: 'limit',
- 340 :
xtype: 'numberfield',
- 341 :
minValue: 5,
- 342 :
listeners: {
- 343 :
change: function(numb, newValue, oldValue) {
- 344 :
function doLoad() {
- 345 :
this.setApiParam('limit', newValue);
- 346 :
this.loadFromApis();
- 347 :
}
- 348 :
if (oldValue !== null) {
- 349 :
if (this.getTermsTimeout() !== null) {
- 350 :
clearTimeout(this.getTermsTimeout());
- 351 :
}
- 352 :
if (numb.isValid()) {
- 353 :
this.setTermsTimeout(setTimeout(doLoad.bind(this), 500));
- 354 :
}
- 355 :
}
- 356 :
},
- 357 :
scope: this
- 358 :
}
- 359 :
},{
- 360 :
xtype: 'container',
- 361 :
html: '<hr style="border: none; border-top: 1px solid #cfcfcf;"/>'
- 362 :
},{
- 363 :
xtype: 'label',
- 364 :
text: this.localize('output')
- 365 :
},{
- 366 :
text: this.localize('analysis'),
- 367 :
itemId: 'analysis',
- 368 :
glyph: 'xf1ec@FontAwesome',
- 369 :
overflowHandler: 'scroller',
- 370 :
menu: {
- 371 :
items: [
- 372 :
{text: this.localize('pca'), itemId: 'analysis_pca', group:'analysis', xtype: 'menucheckitem'},
- 373 :
{text: this.localize('ca'), itemId: 'analysis_ca', group:'analysis', xtype: 'menucheckitem'},
- 374 :
{text: this.localize('tsne'), itemId: 'analysis_tsne', group:'analysis', xtype: 'menucheckitem'},
- 375 :
{text: this.localize('docSim'), itemId: 'analysis_docSim', group:'analysis', xtype: 'menucheckitem'}
- 376 :
],
- 377 :
listeners: {
- 378 :
click: function(menu, item) {
- 379 :
if (item !== undefined) {
- 380 :
var analysis = item.getItemId().split('_')[1];
- 381 :
if (analysis !== this.getApiParam('analysis')) {
- 382 :
this.doAnalysisChange(analysis);
- 383 :
this.loadFromApis(true);
- 384 :
}
- 385 :
}
- 386 :
},
- 387 :
scope: this
- 388 :
}
- 389 :
}
- 390 :
},{
- 391 :
fieldLabel: this.localize('perplexity'),
- 392 :
itemId: 'perplexity',
- 393 :
xtype: 'slider',
- 394 :
minValue: 5,
- 395 :
maxValue: 100,
- 396 :
increment: 1,
- 397 :
listeners: {
- 398 :
changecomplete: function(slider, newValue) {
- 399 :
this.setApiParam('perplexity', newValue);
- 400 :
this.loadFromApis(true);
- 401 :
},
- 402 :
scope: this
- 403 :
}
- 404 :
},{
- 405 :
fieldLabel: this.localize('iterations'),
- 406 :
itemId: 'iterations',
- 407 :
xtype: 'slider',
- 408 :
minValue: 100,
- 409 :
maxValue: 5000,
- 410 :
increment: 100,
- 411 :
listeners: {
- 412 :
changecomplete: function(slider, newValue) {
- 413 :
this.setApiParam('iterations', newValue);
- 414 :
this.loadFromApis(true);
- 415 :
},
- 416 :
scope: this
- 417 :
}
- 418 :
},{
- 419 :
text: this.localize('clusters'),
- 420 :
itemId: 'clusters',
- 421 :
glyph: 'xf192@FontAwesome',
- 422 :
menu: {
- 423 :
items: [
- 424 :
{text: '1', itemId: 'clusters_1', group: 'clusters', xtype: 'menucheckitem'},
- 425 :
{text: '2', itemId: 'clusters_2', group: 'clusters', xtype: 'menucheckitem'},
- 426 :
{text: '3', itemId: 'clusters_3', group: 'clusters', xtype: 'menucheckitem'},
- 427 :
{text: '4', itemId: 'clusters_4', group: 'clusters', xtype: 'menucheckitem'},
- 428 :
{text: '5', itemId: 'clusters_5', group: 'clusters', xtype: 'menucheckitem'}
- 429 :
],
- 430 :
listeners: {
- 431 :
click: function(menu, item) {
- 432 :
if (item !== undefined) {
- 433 :
var clusters = parseInt(item.getItemId().split('_')[1]);
- 434 :
if (clusters !== this.getApiParam('clusters')) {
- 435 :
this.setApiParam('clusters', clusters);
- 436 :
this.loadFromApis(true);
- 437 :
}
- 438 :
}
- 439 :
},
- 440 :
scope: this
- 441 :
}
- 442 :
}
- 443 :
},{
- 444 :
text: this.localize('dimensions'),
- 445 :
itemId: 'dimensions',
- 446 :
glyph: 'xf1b2@FontAwesome',
- 447 :
menu: {
- 448 :
items: [
- 449 :
{text: '2', itemId: 'dimensions_2', group: 'dimensions', xtype: 'menucheckitem'},
- 450 :
{text: '3', itemId: 'dimensions_3', group: 'dimensions', xtype: 'menucheckitem'}
- 451 :
],
- 452 :
listeners: {
- 453 :
click: function(menu, item) {
- 454 :
if (item !== undefined) {
- 455 :
var dims = parseInt(item.getItemId().split('_')[1]);
- 456 :
if (dims !== this.getApiParam('dimensions')) {
- 457 :
if (dims == 3 && this.getApiParam('analysis') == 'ca' && this.getCorpus().getDocumentsCount() == 3) {
- 458 :
dims = 2;
- 459 :
// TODO add info message 'Because of the nature of Correspondence Analysis, you can only use 2 dimensions with 3 documents.'
- 460 :
return false;
- 461 :
}
- 462 :
- 463 :
this.setApiParam('dimensions', dims);
- 464 :
this.loadFromApis(true);
- 465 :
}
- 466 :
}
- 467 :
},
- 468 :
scope: this
- 469 :
}
- 470 :
}
- 471 :
},{
- 472 :
itemId: 'reloadButton',
- 473 :
text: this.localize('reload'),
- 474 :
glyph: 'xf021@FontAwesome',
- 475 :
handler: function() {
- 476 :
this.loadFromApis();
- 477 :
},
- 478 :
scope: this
- 479 :
}]
- 480 :
},{
- 481 :
itemId: 'termsGrid',
- 482 :
xtype: 'grid',
- 483 :
title: this.localize('terms'),
- 484 :
region: 'east',
- 485 :
width: 250,
- 486 :
split: true,
- 487 :
collapsible: true,
- 488 :
collapseMode: 'header',
- 489 :
forceFit: true,
- 490 :
features: [{
- 491 :
ftype: 'grouping',
- 492 :
hideGroupedHeader: true,
- 493 :
enableGroupingMenu: false
- 494 :
}],
- 495 :
bbar: {
- 496 :
overflowHandler: 'scroller',
- 497 :
items: [{
- 498 :
itemId: 'nearbyButton',
- 499 :
xtype: 'button',
- 500 :
text: this.localize('nearby'),
- 501 :
glyph: 'xf0b2@FontAwesome',
- 502 :
flex: 1,
- 503 :
handler: function(btn) {
- 504 :
var sel = btn.up('panel').getSelection()[0];
- 505 :
if (sel === undefined) {
- 506 :
this.toastError({
- 507 :
html: this.localize("noTermSelected"),
- 508 :
anchor: btn.up("panel").getTargetEl()
- 509 :
});
- 510 :
}
- 511 :
else {
- 512 :
var term = sel.get('term');
- 513 :
this.getNearbyForTerm(term);
- 514 :
}
- 515 :
},
- 516 :
scope: this
- 517 :
},{
- 518 :
itemId: 'removeButton',
- 519 :
xtype: 'button',
- 520 :
text: this.localize('remove'),
- 521 :
glyph: 'xf068@FontAwesome',
- 522 :
flex: 1,
- 523 :
handler: function(btn) {
- 524 :
var sel = btn.up('panel').getSelection()[0];
- 525 :
if (sel === undefined) {
- 526 :
this.toastError({
- 527 :
html: this.localize("noTermSelected"),
- 528 :
anchor: btn.up("panel").getTargetEl()
- 529 :
});
- 530 :
}
- 531 :
else {
- 532 :
var term = sel.get('term');
- 533 :
this.removeTerm(term);
- 534 :
}
- 535 :
},
- 536 :
scope: this
- 537 :
}]
- 538 :
- 539 :
},
- 540 :
tbar: {
- 541 :
overflowHandler: 'scroller',
- 542 :
items: [{
- 543 :
xtype: 'querysearchfield',
- 544 :
itemId: 'addTerms',
- 545 :
// emptyText: this.localize('addTerm'),
- 546 :
flex: 1
- 547 :
}]
- 548 :
},
- 549 :
columns: [{
- 550 :
text: this.localize('term'),
- 551 :
dataIndex: 'term',
- 552 :
flex: 1,
- 553 :
sortable: true
- 554 :
},{
- 555 :
text: this.localize('rawFreq'),
- 556 :
dataIndex: 'rawFreq',
- 557 :
flex: 0.75,
- 558 :
minWidth: 70,
- 559 :
sortable: true
- 560 :
},{
- 561 :
text: this.localize('relFreq'),
- 562 :
dataIndex: 'relativeFreq',
- 563 :
flex: 0.75,
- 564 :
minWidth: 70,
- 565 :
sortable: true,
- 566 :
hidden: true
- 567 :
}],
- 568 :
selModel: {
- 569 :
type: 'rowmodel',
- 570 :
mode: 'SINGLE',
- 571 :
allowDeselect: true,
- 572 :
toggleOnClick: true,
- 573 :
listeners: {
- 574 :
selectionchange: {
- 575 :
fn: function(sm, selections) {
- 576 :
// this.getApplication().dispatchEvent('corpusTermsClicked', this, selections);
- 577 :
var sel = selections[0];
- 578 :
if (sel !== undefined) {
- 579 :
var term = sel.get('term');
- 580 :
var isDoc = sel.get('category') === 'document';
- 581 :
this.selectTerm(term, isDoc);
- 582 :
- 583 :
if (isDoc) {
- 584 :
this.queryById('nearbyButton').disable();
- 585 :
this.queryById('removeButton').disable();
- 586 :
} else {
- 587 :
this.queryById('nearbyButton').enable();
- 588 :
this.queryById('removeButton').enable();
- 589 :
}
- 590 :
} else {
- 591 :
this.selectTerm();
- 592 :
}
- 593 :
},
- 594 :
scope: this
- 595 :
}
- 596 :
}
- 597 :
},
- 598 :
store: this.getTermStore(),
- 599 :
listeners: {
- 600 :
expand: function(panel) {
- 601 :
panel.getView().refresh();
- 602 :
},
- 603 :
query: function(component, value) {
- 604 :
if (value.length > 0 && this.getTermStore().findExact('term', value[0]) === -1) {
- 605 :
this.setNewTerm(value);
- 606 :
this.loadFromApis();
- 607 :
} else {
- 608 :
this.setNewTerm(null);
- 609 :
}
- 610 :
},
- 611 :
scope: this
- 612 :
}
- 613 :
}]
- 614 :
});
- 615 :
- 616 :
this.on('boxready', function(component, width, height) {
- 617 :
if (width < 400) {
- 618 :
this.queryById('optionsPanel').collapse();
- 619 :
this.queryById('termsGrid').collapse();
- 620 :
}
- 621 :
if (this.config.storeClass && this.config.storeData) {
- 622 :
this.loadStoreFromJson(this.config.storeClass, this.config.storeData);
- 623 :
}
- 624 :
}, this);
- 625 :
- 626 :
this.on('beforedestroy', function(component) {
- 627 :
var oldChart = this.queryById('chart');
- 628 :
if (oldChart !== null) {
- 629 :
this.queryById('chartParent').remove(oldChart);
- 630 :
}
- 631 :
}, this);
- 632 :
- 633 :
// create a listener for corpus loading (defined here, in case we need to load it next)
- 634 :
this.on('loadedCorpus', function(src, corpus) {
- 635 :
function setCheckItemFromApi(apiParamName) {
- 636 :
var value = this.getApiParam(apiParamName);
- 637 :
var menu = this.queryById(apiParamName);
- 638 :
var item = menu.down('#'+apiParamName+'_'+value);
- 639 :
item.setChecked(true);
- 640 :
}
- 641 :
var setCheckBound = setCheckItemFromApi.bind(this);
- 642 :
- 643 :
setCheckBound('analysis');
- 644 :
this.doAnalysisChange(this.getApiParam('analysis'));
- 645 :
- 646 :
setCheckBound('comparisonType');
- 647 :
setCheckBound('clusters');
- 648 :
- 649 :
this.queryById('perplexity').setValue(this.getApiParam('perplexity'));
- 650 :
this.queryById('iterations').setValue(this.getApiParam('iterations'));
- 651 :
- 652 :
if (corpus.getDocumentsCount() == 3) {
- 653 :
this.setApiParam('dimensions', 2);
- 654 :
}
- 655 :
setCheckBound('dimensions');
- 656 :
- 657 :
this.getCaStore().setCorpus(corpus);
- 658 :
this.getPcaStore().setCorpus(corpus);
- 659 :
this.getDocSimStore().setCorpus(corpus);
- 660 :
this.loadFromApis();
- 661 :
}, this);
- 662 :
- 663 :
this.on('documentsSelected', function(src, docIds) {
- 664 :
this.setApiParam('docId', docIds);
- 665 :
this.loadFromApis();
- 666 :
}, this);
- 667 :
- 668 :
this.callParent(arguments);
- 669 :
},
- 670 :
- 671 :
doAnalysisChange: function(analysis) {
- 672 :
this.setApiParam('analysis', analysis);
- 673 :
this.queryById('nearbyButton').setDisabled(analysis === 'tsne');
- 674 :
this.queryById('reloadButton').setVisible(analysis === 'tsne');
- 675 :
this.queryById('perplexity').setVisible(analysis === 'tsne');
- 676 :
this.queryById('iterations').setVisible(analysis === 'tsne');
- 677 :
if (analysis === 'ca') {
- 678 :
// TODO handling for when there's no corpus
- 679 :
if (this.getCorpus().getDocumentsCount() == 3) {
- 680 :
this.setApiParam('dimensions', 2);
- 681 :
this.queryById('dimensions').menu.items.get(0).setChecked(true); // need 1-2 docs or 4+ docs for 3 dimensions
- 682 :
}
- 683 :
}
- 684 :
},
- 685 :
- 686 :
loadStoreFromJson: function(storeClass, storeData) {
- 687 :
if (storeClass == 'Voyant.data.store.CAAnalysis') {
- 688 :
this.getCaStore().loadRawData(storeData);
- 689 :
this.doAnalysisChange('ca');
- 690 :
this.maskAndBuildChart.call(this, this.getCaStore());
- 691 :
} else if (storeClass == 'Voyant.data.store.PCAAnalysis') {
- 692 :
this.getPcaStore().loadRawData(storeData);
- 693 :
this.doAnalysisChange('pca');
- 694 :
this.maskAndBuildChart.call(this, this.getPcaStore());
- 695 :
} else if (storeClass == 'Voyant.data.store.TSNEAnalysis') {
- 696 :
this.getTsneStore().loadRawData(storeData);
- 697 :
this.doAnalysisChange('tsne');
- 698 :
this.maskAndBuildChart.call(this, this.getTsneStore());
- 699 :
} else if (storeClass == 'Voyant.data.store.DocSimAnalysis') {
- 700 :
this.getDocSimStore().loadRawData(storeData);
- 701 :
this.doAnalysisChange('docSim');
- 702 :
this.maskAndBuildChart.call(this, this.getDocSimStore());
- 703 :
}
- 704 :
},
- 705 :
- 706 :
maskAndBuildChart: function(store) {
- 707 :
this.queryById('chartParent').mask(this.localize('plotting'));
- 708 :
Ext.defer(this.buildChart, 50, this, [store]);
- 709 :
},
- 710 :
- 711 :
buildChart: function(store) {
- 712 :
var that = this; // needed for tooltip renderer
- 713 :
- 714 :
var oldChart = this.queryById('chart');
- 715 :
if (oldChart !== null) {
- 716 :
this.queryById('chartParent').remove(oldChart);
- 717 :
}
- 718 :
- 719 :
this.queryById('termsGrid').getSelectionModel().deselectAll();
- 720 :
- 721 :
var rec = store.getAt(0);
- 722 :
var numDims = this.getApiParam('dimensions');
- 723 :
- 724 :
var summary = '';
- 725 :
if (this.getApiParam('analysis') === 'pca') {
- 726 :
// calculate the percentage of original data represented by the dominant principal components
- 727 :
var pcs = rec.getPrincipalComponents();
- 728 :
var eigenTotal = 0;
- 729 :
for (var i = 0; i < pcs.length; i++) {
- 730 :
var pc = pcs[i];
- 731 :
eigenTotal += parseFloat(pc.get('eigenValue'));
- 732 :
}
- 733 :
if (eigenTotal == 0) {
- 734 :
// do nothing
- 735 :
} else {
- 736 :
summary = this.localize('pcTitle')+'\n';
- 737 :
var pcMapping = ['xAxis', 'yAxis', 'fill'];
- 738 :
for (var i = 0; i < pcs.length; i++) {
- 739 :
if (i >= numDims) break;
- 740 :
- 741 :
var eigenValue = pcs[i].get('eigenValue');
- 742 :
var percentage = eigenValue / eigenTotal * 100;
- 743 :
summary += this.localize('pc')+' '+(i+1)+' ('+this.localize(pcMapping[i])+'): '+Math.round(percentage*100)/100+'%\n';
- 744 :
}
- 745 :
}
- 746 :
} else if (this.getApiParam('analysis') === 'tsne') {
- 747 :
- 748 :
} else {
- 749 :
summary = this.localize('caTitle')+'\n';
- 750 :
var pcMapping = ['xAxis', 'yAxis', 'fill'];
- 751 :
- 752 :
var dimensions = rec.getDimensions();
- 753 :
for (var i = 0; i < dimensions.length; i++) {
- 754 :
if (i >= numDims) break;
- 755 :
- 756 :
var percentage = dimensions[i].get('percentage');
- 757 :
summary += this.localize('dimension')+' '+(i+1)+' ('+this.localize(pcMapping[i])+'): '+Math.round(percentage*100)/100+'%\n';
- 758 :
}
- 759 :
}
- 760 :
- 761 :
var maxFreq = 0;
- 762 :
var minFreq = Number.MAX_VALUE;
- 763 :
var maxFill = 0;
- 764 :
var minFill = Number.MAX_VALUE;
- 765 :
- 766 :
- 767 :
if (this.getApiParam('analysis') !== 'docSim') { // docSim doesn't return terms so keep the current ones
- 768 :
this.getTermStore().removeAll();
- 769 :
}
- 770 :
- 771 :
var tokens = rec.getTokens();
- 772 :
var termData = [];
- 773 :
var docData = [];
- 774 :
tokens.forEach(function(token) {
- 775 :
var freq = token.get('rawFreq');
- 776 :
var category = token.get('category');
- 777 :
if (category === undefined) {
- 778 :
category = 'term'; // some analyses don't define categories
- 779 :
token.set('category', 'term');
- 780 :
}
- 781 :
var isTerm = category === 'term';
- 782 :
if (isTerm) {
- 783 :
if (freq > maxFreq) maxFreq = freq;
- 784 :
if (freq < minFreq) minFreq = freq;
- 785 :
}
- 786 :
if (this.getTermStore().findExact('term', token.get('term') === -1)) {
- 787 :
this.getTermStore().addSorted(token);
- 788 :
}
- 789 :
if (numDims === 3) {
- 790 :
var z = token.get('vector')[2];
- 791 :
if (z !== undefined) {
- 792 :
if (z < minFill) minFill = z;
- 793 :
if (z > maxFill) maxFill = z;
- 794 :
}
- 795 :
}
- 796 :
var tokenData = {
- 797 :
x: token.get('vector')[0], y: token.get('vector')[1] || 0, z: token.get('vector')[2] || 0,
- 798 :
term: token.get('term'), rawFreq: freq, relativeFreq: token.get('relativeFreq'), cluster: token.get('cluster'), category: category,
- 799 :
disabled: false
- 800 :
};
- 801 :
if (!isTerm) {
- 802 :
if (token.get('category') === 'bin') {
- 803 :
tokenData.term = tokenData.title = "Bin "+token.get('docIndex');
- 804 :
} else {
- 805 :
tokenData.docIndex = token.get('docIndex');
- 806 :
var doc = this.getCorpus().getDocument(tokenData.docIndex);
- 807 :
if (doc !== null) {
- 808 :
tokenData.term = doc.getShortTitle();
- 809 :
tokenData.title = doc.getTitle();
- 810 :
}
- 811 :
}
- 812 :
docData.push(tokenData);
- 813 :
} else {
- 814 :
termData.push(tokenData);
- 815 :
}
- 816 :
}, this);
- 817 :
- 818 :
var newCount = this.getTermStore().getCount();
- 819 :
this.queryById('limit').setRawValue(newCount);
- 820 :
this.setApiParam('limit', newCount);
- 821 :
- 822 :
- 823 :
var termSeriesStore = Ext.create('Ext.data.JsonStore', {
- 824 :
fields: ['term', 'x', 'y', 'z', 'rawFreq', 'relativeFreq', 'cluster', 'category', 'docIndex', 'disabled'],
- 825 :
data: termData
- 826 :
});
- 827 :
var docSeriesStore = Ext.create('Ext.data.JsonStore', {
- 828 :
fields: ['term', 'x', 'y', 'z', 'rawFreq', 'relativeFreq', 'cluster', 'category', 'docIndex', 'disabled'],
- 829 :
data: docData
- 830 :
});
- 831 :
- 832 :
var config = {
- 833 :
itemId: 'chart',
- 834 :
xtype: 'cartesian',
- 835 :
interactions: ['crosszoom','panzoom','itemhighlight'],
- 836 :
plugins: {
- 837 :
ptype: 'chartitemevents'
- 838 :
},
- 839 :
axes: [{
- 840 :
type: 'numeric',
- 841 :
position: 'bottom',
- 842 :
fields: ['x'],
- 843 :
label: {
- 844 :
rotate:{degrees:-30}
- 845 :
}
- 846 :
},{
- 847 :
type: 'numeric',
- 848 :
position: 'left',
- 849 :
fields: ['y']
- 850 :
}],
- 851 :
sprites: [{
- 852 :
type: 'text',
- 853 :
text: summary,
- 854 :
x: 70,
- 855 :
y: 70
- 856 :
}],
- 857 :
innerPadding: {top: 25, right: 25, bottom: 25, left: 25},
- 858 :
series: [{
- 859 :
type: 'customScatter',
- 860 :
xField: 'x',
- 861 :
yField: 'y',
- 862 :
store: termSeriesStore,
- 863 :
label: {
- 864 :
font: '14px Helvetica',
- 865 :
field: 'term',
- 866 :
display: 'over'
- 867 :
},
- 868 :
tooltip: {
- 869 :
trackMouse: true,
- 870 :
style: 'background: #fff',
- 871 :
renderer: function (toolTip, record, ctx) {
- 872 :
toolTip.setHtml(that.tokenFreqTipTemplate.apply([record.get('term'),record.get('rawFreq'),record.get('relativeFreq')]));
- 873 :
}
- 874 :
},
- 875 :
marker: {
- 876 :
type: 'circle'
- 877 :
},
- 878 :
highlight: {
- 879 :
fillStyle: 'yellow',
- 880 :
strokeStyle: 'black'
- 881 :
},
- 882 :
renderer: function (sprite, config, rendererData, index) {
- 883 :
var store = rendererData.store;
- 884 :
var item = store.getAt(index);
- 885 :
if (item !== null) {
- 886 :
var clusterIndex = item.get('cluster');
- 887 :
var scatterplot = that;
- 888 :
- 889 :
if (clusterIndex === -1) {
- 890 :
// no clusters were specified in initial call
- 891 :
clusterIndex = 0;
- 892 :
}
- 893 :
- 894 :
var fillAlpha = 0.65;
- 895 :
var strokeAlpha = 1;
- 896 :
if (item.get('disabled') === true) {
- 897 :
fillAlpha = 0.1;
- 898 :
strokeAlpha = 0.1;
- 899 :
} else if (numDims === 3 && item.get('z')) {
- 900 :
fillAlpha = scatterplot.interpolate(item.get('z'), minFill, maxFill, 0, 1);
- 901 :
}
- 902 :
var color = scatterplot.getApplication().getColor(clusterIndex);
- 903 :
config.fillStyle = 'rgba('+color.join(',')+','+fillAlpha+')';
- 904 :
config.strokeStyle = 'rgba('+color.join(',')+','+strokeAlpha+')';
- 905 :
- 906 :
var freq = item.get('rawFreq');
- 907 :
var radius = scatterplot.interpolate(freq, minFreq, maxFreq, 2, 20);
- 908 :
config.radius = radius;
- 909 :
}
- 910 :
},
- 911 :
scope: this
- 912 :
},{
- 913 :
type: 'customScatter',
- 914 :
xField: 'x',
- 915 :
yField: 'y',
- 916 :
store: docSeriesStore,
- 917 :
label: {
- 918 :
font: '14px Helvetica',
- 919 :
field: 'term',
- 920 :
display: 'over',
- 921 :
color: this.getDefaultDocColor(true)
- 922 :
},
- 923 :
tooltip: {
- 924 :
trackMouse: true,
- 925 :
style: 'background: #fff',
- 926 :
renderer: function (toolTip, record, ctx) {
- 927 :
toolTip.setHtml(that.docFreqTipTemplate.apply([record.get('title'),record.get('rawFreq')]));
- 928 :
}
- 929 :
},
- 930 :
marker: {
- 931 :
type: 'diamond'
- 932 :
},
- 933 :
highlight: {
- 934 :
fillStyle: 'yellow',
- 935 :
strokeStyle: 'black'
- 936 :
},
- 937 :
renderer: function (sprite, config, rendererData, index) {
- 938 :
var store = rendererData.store;
- 939 :
var item = store.getAt(index);
- 940 :
if (item !== null) {
- 941 :
var clusterIndex = item.get('cluster');
- 942 :
var scatterplot = that;
- 943 :
- 944 :
var color;
- 945 :
if (clusterIndex === -1 || scatterplot.getApiParam('analysis') !== 'docSim') {
- 946 :
color = scatterplot.getDefaultDocColor();
- 947 :
} else {
- 948 :
color = scatterplot.getApplication().getColor(clusterIndex);
- 949 :
}
- 950 :
- 951 :
var a = 0.65;
- 952 :
if (numDims === 3 && item.get('z')) {
- 953 :
a = scatterplot.interpolate(item.get('z'), minFill, maxFill, 0, 1);
- 954 :
}
- 955 :
- 956 :
config.fillStyle = 'rgba('+color.join(',')+','+a+')';
- 957 :
config.strokeStyle = 'rgba('+color.join(',')+',1)';
- 958 :
config.radius = 5;
- 959 :
}
- 960 :
},
- 961 :
scope: this
- 962 :
- 963 :
- 964 :
}],
- 965 :
listeners: {
- 966 :
itemclick: function(chart, item, event) {
- 967 :
var data = item.record.data;
- 968 :
if (data.category === 'doc') {
- 969 :
var record = this.getCorpus().getDocument(data.docIndex);
- 970 :
this.getApplication().dispatchEvent('documentsClicked', this, [record]);
- 971 :
} else if (data.category === 'term') {
- 972 :
var record = Ext.create('Voyant.data.model.CorpusTerm', data);
- 973 :
this.getApplication().dispatchEvent('corpusTermsClicked', this, [record]);
- 974 :
}
- 975 :
},
- 976 :
render: function(chart) {
- 977 :
chart.body.on('contextmenu', function(event, target) {
- 978 :
event.preventDefault();
- 979 :
- 980 :
var xy = event.getXY();
- 981 :
var parentXY = Ext.fly(target).getXY();
- 982 :
var x = xy[0] - parentXY[0];
- 983 :
var y = xy[1] - parentXY[1];
- 984 :
var chartItem = this.down('#chart').getItemForPoint(x,y);
- 985 :
if (chartItem != null && chartItem.record.get('category') === 'term') {
- 986 :
var series = this.down('#chart').getSeries();
- 987 :
series[0].disableToolTips();
- 988 :
series[1].disableToolTips();
- 989 :
- 990 :
var term = chartItem.record.get('term');
- 991 :
- 992 :
var text = (new Ext.Template(this.localize('removeTerm'))).apply([term]);
- 993 :
this.getChartMenu().queryById('remove').setText(text);
- 994 :
text = (new Ext.Template(this.localize('nearbyTerm'))).apply([term]);
- 995 :
var nearby = this.getChartMenu().queryById('nearby');
- 996 :
nearby.setText(text);
- 997 :
nearby.setDisabled(this.getApiParam('analysis') === 'tsne');
- 998 :
- 999 :
this.getChartMenu().on('click', function(menu, item) {
- 1000 :
if (item !== undefined) {
- 1001 :
var term = chartItem.record.get('term');
- 1002 :
if (item.getItemId() === 'nearby') {
- 1003 :
this.getNearbyForTerm(term);
- 1004 :
} else {
- 1005 :
this.removeTerm(term);
- 1006 :
}
- 1007 :
}
- 1008 :
}, this, {single: true});
- 1009 :
this.getChartMenu().showAt(xy);
- 1010 :
}
- 1011 :
}, this);
- 1012 :
},
- 1013 :
scope: this
- 1014 :
}
- 1015 :
};
- 1016 :
- 1017 :
var chart = Ext.create('Ext.chart.CartesianChart', config);
- 1018 :
this.queryById('chartParent').insert(0, chart);
- 1019 :
- 1020 :
this.queryById('chartParent').unmask();
- 1021 :
- 1022 :
this.doLabels();
- 1023 :
- 1024 :
if (this.getNewTerm() !== null) {
- 1025 :
this.selectTerm(this.getNewTerm()[0]);
- 1026 :
this.setNewTerm(null);
- 1027 :
}
- 1028 :
},
- 1029 :
- 1030 :
getDefaultDocColor: function(returnHex) {
- 1031 :
var color = this.getApplication().getColor(6, returnHex);
- 1032 :
return color;
- 1033 :
},
- 1034 :
- 1035 :
doLabels: function() {
- 1036 :
var chart = this.queryById('chart');
- 1037 :
var series = chart.getSeries();
- 1038 :
var summary = chart.getSurface('chart').getItems()[0];
- 1039 :
var labels = this.getApiParam("label");
- 1040 :
if (labels.indexOf("summary")>-1) {summary.show();}
- 1041 :
else {summary.hide();}
- 1042 :
if (labels.indexOf("terms")>-1) {series[0].getLabel().show();}
- 1043 :
else {series[0].getLabel().hide();}
- 1044 :
if (labels.indexOf("docs")>-1) {series[1].getLabel().show();}
- 1045 :
else {series[1].getLabel().hide();}
- 1046 :
},
- 1047 :
- 1048 :
selectTerm: function(term, isDoc) {
- 1049 :
var chart = this.down('#chart');
- 1050 :
if (chart !== null) {
- 1051 :
if (term === undefined) {
- 1052 :
chart.getSeries()[0].setHighlightItem(null);
- 1053 :
chart.getSeries()[1].setHighlightItem(null);
- 1054 :
} else {
- 1055 :
var series, index;
- 1056 :
if (isDoc === true) {
- 1057 :
series = chart.getSeries()[1];
- 1058 :
index = series.getStore().findExact('title', term);
- 1059 :
} else {
- 1060 :
series = chart.getSeries()[0];
- 1061 :
index = series.getStore().findExact('term', term);
- 1062 :
}
- 1063 :
if (index !== -1) {
- 1064 :
var record = series.getStore().getAt(index);
- 1065 :
var sprite = series.getSprites()[0];
- 1066 :
// constructing series item, like in the chart series source
- 1067 :
var item = {
- 1068 :
series: series,
- 1069 :
category: series.getItemInstancing() ? 'items' : 'markers',
- 1070 :
index: index,
- 1071 :
record: record,
- 1072 :
field: series.getYField(),
- 1073 :
sprite: sprite
- 1074 :
};
- 1075 :
series.setHighlightItem(item);
- 1076 :
if (isDoc) {
- 1077 :
chart.getSeries()[0].setHighlightItem(null);
- 1078 :
} else {
- 1079 :
chart.getSeries()[1].setHighlightItem(null);
- 1080 :
}
- 1081 :
- 1082 :
var point = this.getPointFromIndex(series, index);
- 1083 :
this.setHighlightData({x: point[0], y: point[1], r: 50});
- 1084 :
- 1085 :
if (this.getHighlightTask() == null) {
- 1086 :
this.setHighlightTask(Ext.TaskManager.newTask({
- 1087 :
run: this.doHighlight,
- 1088 :
scope: this,
- 1089 :
interval: 25,
- 1090 :
repeat: this.getHighlightData().r
- 1091 :
}));
- 1092 :
}
- 1093 :
this.getHighlightTask().restart();
- 1094 :
}
- 1095 :
}
- 1096 :
}
- 1097 :
},
- 1098 :
- 1099 :
getPointFromIndex: function(series, index) {
- 1100 :
var sprite = series.getSprites()[0];
- 1101 :
if (sprite.surfaceMatrix !== null) {
- 1102 :
var matrix = sprite.attr.matrix.clone().prependMatrix(sprite.surfaceMatrix);
- 1103 :
var dataX = sprite.attr.dataX[index];
- 1104 :
var dataY = sprite.attr.dataY[index];
- 1105 :
return matrix.transformPoint([dataX, dataY]);
- 1106 :
} else {
- 1107 :
return [0,0];
- 1108 :
}
- 1109 :
},
- 1110 :
- 1111 :
doHighlight: function() {
- 1112 :
var chart = this.down('#chart');
- 1113 :
if (this.getHighlightData().r > 0) {
- 1114 :
var surf = chart.getSurface();
- 1115 :
var highlight = null;
- 1116 :
var items = surf.getItems();
- 1117 :
for (var i = 0; i < items.length; i++) {
- 1118 :
var item = items[i];
- 1119 :
if (item.id == 'customHighlight') {
- 1120 :
highlight = item;
- 1121 :
break;
- 1122 :
}
- 1123 :
}
- 1124 :
if (highlight == null) {
- 1125 :
surf.add({
- 1126 :
id: 'customHighlight',
- 1127 :
type: 'circle',
- 1128 :
strokeStyle: 'red',
- 1129 :
fillStyle: 'none',
- 1130 :
radius: this.getHighlightData().r,
- 1131 :
x: this.getHighlightData().x,
- 1132 :
y: this.getHighlightData().y
- 1133 :
});
- 1134 :
} else {
- 1135 :
highlight.setAttributes({
- 1136 :
x: this.getHighlightData().x,
- 1137 :
y: this.getHighlightData().y,
- 1138 :
radius: this.getHighlightData().r
- 1139 :
});
- 1140 :
this.getHighlightData().r -= 1.5;
- 1141 :
if (this.getHighlightData().r <= 0) {
- 1142 :
this.getHighlightData().r = 0;
- 1143 :
surf.remove(highlight, true);
- 1144 :
}
- 1145 :
}
- 1146 :
chart.redraw();
- 1147 :
}
- 1148 :
},
- 1149 :
- 1150 :
filterChart: function(query) {
- 1151 :
if (Ext.isString(query)) query = [query];
- 1152 :
var reQueries = [];
- 1153 :
for (var i = 0; i < query.length; i++) {
- 1154 :
var re = new RegExp(query[i]);
- 1155 :
reQueries.push(re);
- 1156 :
}
- 1157 :
- 1158 :
// filter terms
- 1159 :
var chart = this.queryById('chart');
- 1160 :
var series0 = chart.getSeries()[0];
- 1161 :
var label0 = series0.getLabel();
- 1162 :
series0.getStore().each(function(item) {
- 1163 :
var match = false;
- 1164 :
if (reQueries.length == 0) match = true;
- 1165 :
else {
- 1166 :
for (var i = 0; i < reQueries.length; i++) {
- 1167 :
match = match || reQueries[i].test(item.get('term'));
- 1168 :
if (match) break;
- 1169 :
}
- 1170 :
}
- 1171 :
item.set('disabled', !match);
- 1172 :
var index = item.store.indexOf(item);
- 1173 :
label0.setAttributesFor(index, {hidden: !match});
- 1174 :
}, this);
- 1175 :
- 1176 :
chart.redraw();
- 1177 :
},
- 1178 :
- 1179 :
getCurrentTerms: function() {
- 1180 :
var terms = [];
- 1181 :
this.getTermStore().each(function(r) {
- 1182 :
if (r.get('category') === 'term') {
- 1183 :
terms.push(r.get('term'));
- 1184 :
}
- 1185 :
});
- 1186 :
return terms;
- 1187 :
},
- 1188 :
- 1189 :
getNearbyForTerm: function(term) {
- 1190 :
var limit = Math.max(2000, Math.round(this.getCorpus().getWordTokensCount() / 100));
- 1191 :
this.setApiParams({limit: limit, target: term});
- 1192 :
this.loadFromApis();
- 1193 :
this.setApiParam('target', undefined);
- 1194 :
},
- 1195 :
- 1196 :
removeTerm: function(term) {
- 1197 :
var series = this.down('#chart').getSeries()[0];
- 1198 :
var index = series.getStore().findExact('term', term);
- 1199 :
series.getStore().removeAt(index);
- 1200 :
- 1201 :
index = this.getTermStore().findExact('term', term);
- 1202 :
this.getTermStore().removeAt(index);
- 1203 :
- 1204 :
var newCount = this.getTermStore().getCount();
- 1205 :
this.queryById('limit').setRawValue(newCount);
- 1206 :
},
- 1207 :
- 1208 :
loadFromApis: function(keepCurrentTerms) {
- 1209 :
this.queryById('chartParent').mask(this.localize('analyzing'));
- 1210 :
- 1211 :
var params = {};
- 1212 :
var terms = this.getCurrentTerms();
- 1213 :
if (this.getNewTerm() !== null) {
- 1214 :
terms = terms.concat(this.getNewTerm());
- 1215 :
this.setApiParam('limit', terms.length);
- 1216 :
}
- 1217 :
if (terms.length > 0) {
- 1218 :
if (this.getNewTerm() !== null || keepCurrentTerms) {
- 1219 :
params.query = terms.join(',');
- 1220 :
}
- 1221 :
// params.term = terms;
- 1222 :
}
- 1223 :
Ext.apply(params, this.getApiParams());
- 1224 :
if (params.target != null) {
- 1225 :
params.term = terms;
- 1226 :
}
- 1227 :
if (params.analysis === 'pca') {
- 1228 :
this.getPcaStore().load({
- 1229 :
params: params
- 1230 :
});
- 1231 :
} else if (params.analysis === 'tsne'){
- 1232 :
this.getTsneStore().load({
- 1233 :
params: params
- 1234 :
});
- 1235 :
} else if (params.analysis === 'docSim'){
- 1236 :
this.getDocSimStore().load({
- 1237 :
params: params
- 1238 :
});
- 1239 :
} else {
- 1240 :
this.getCaStore().load({
- 1241 :
params: params
- 1242 :
});
- 1243 :
}
- 1244 :
},
- 1245 :
- 1246 :
interpolate: function(lambda, minSrc, maxSrc, minDst, maxDst) {
- 1247 :
return minDst + (maxDst - minDst) * Math.max(0, Math.min(1, (lambda - minSrc) / (maxSrc - minSrc)));
- 1248 :
}
- 1249 :
});
- 1250 :
- 1251 :
/*
- 1252 :
* Adds tool tip disabling.
- 1253 :
*/
- 1254 :
Ext.define('Ext.chart.series.CustomScatter', {
- 1255 :
extend: 'Ext.chart.series.Scatter',
- 1256 :
- 1257 :
alias: 'series.customScatter',
- 1258 :
type: 'customScatter',
- 1259 :
seriesType: 'scatterSeries',
- 1260 :
- 1261 :
tipsDisabled: false,
- 1262 :
- 1263 :
enableToolTips: function() {
- 1264 :
this.tipsDisabled = false;
- 1265 :
},
- 1266 :
- 1267 :
disableToolTips: function() {
- 1268 :
this.tipsDisabled = true;
- 1269 :
},
- 1270 :
- 1271 :
showTip: function (item, xy) {
- 1272 :
if (this.tipsDisabled) {
- 1273 :
return;
- 1274 :
}
- 1275 :
- 1276 :
this.callParent(arguments);
- 1277 :
}
- 1278 :
});