diff --git a/app/static/js/CorpusAnalysis/CorpusAnalysisApp.js b/app/static/js/CorpusAnalysis/CorpusAnalysisApp.js
index 25f58a65..ea7aed3a 100644
--- a/app/static/js/CorpusAnalysis/CorpusAnalysisApp.js
+++ b/app/static/js/CorpusAnalysis/CorpusAnalysisApp.js
@@ -34,11 +34,6 @@ class CorpusAnalysisApp {
.then((cqiCorpora) => {
this.data.corpus = {o: cqiCorpora[0]};
console.log(this.data.corpus.o.staticData);
- // this.renderGeneralCorpusInfo();
- // this.renderTextInfoList();
- // this.renderTextProportionsGraphic()
- // this.renderFrequenciesGraphic();
- // this.renderBoundsGraphic();
// TODO: Don't do this hgere
this.data.corpus.o.updateDb();
diff --git a/app/static/js/CorpusAnalysis/CorpusAnalysisStaticVisualization.js b/app/static/js/CorpusAnalysis/CorpusAnalysisStaticVisualization.js
index 81e1d466..2d8f9002 100644
--- a/app/static/js/CorpusAnalysis/CorpusAnalysisStaticVisualization.js
+++ b/app/static/js/CorpusAnalysis/CorpusAnalysisStaticVisualization.js
@@ -18,9 +18,10 @@ class CorpusAnalysisStaticVisualization {
this.data.corpus = this.app.data.corpus;
this.renderGeneralCorpusInfo();
this.renderTextInfoList();
- this.renderTextProportionsGraphic()
+ this.renderTextProportionsGraphic();
+ this.renderTokenList();
this.renderFrequenciesGraphic();
- this.renderBoundsGraphic();
+
// Add event listeners
let frequenciesStopwordSettingModal = document.querySelector('#frequencies-stopwords-setting-modal');
let frequenciesStopwordSettingModalButton = document.querySelector('#frequencies-stopwords-setting-modal-button');
@@ -30,6 +31,35 @@ class CorpusAnalysisStaticVisualization {
M.Modal.init(frequenciesStopwordSettingModal, {dismissible: false});
});
+ let textProportionsGraphModeButtons = document.querySelectorAll('.text-proportions-graph-mode-button');
+ textProportionsGraphModeButtons.forEach(graphModeButton => {
+ graphModeButton.addEventListener('click', (event) => {
+ textProportionsGraphModeButtons.forEach(btn => {
+ btn.classList.remove('disabled');
+ });
+ event.target.closest('.text-proportions-graph-mode-button').classList.add('disabled');
+ this.renderTextProportionsGraphic();
+ });
+ });
+
+ let frequenciesTokenCategoryDropdownElement = document.querySelector('[data-target="frequencies-token-category-dropdown"]');
+ let frequenciesTokenCategoryDropdownListElement = document.querySelector("#frequencies-token-category-dropdown");
+ frequenciesTokenCategoryDropdownListElement.addEventListener('click', (event) => {
+ frequenciesTokenCategoryDropdownElement.firstChild.textContent = event.target.innerHTML;
+ this.renderFrequenciesGraphic();
+ });
+
+ let frequenciesGraphModeButtons = document.querySelectorAll('.frequencies-graph-mode-button');
+ frequenciesGraphModeButtons.forEach(graphModeButton => {
+ graphModeButton.addEventListener('click', (event) => {
+ frequenciesGraphModeButtons.forEach(btn => {
+ btn.classList.remove('disabled');
+ });
+ event.target.closest('.frequencies-graph-mode-button').classList.add('disabled');
+ this.renderFrequenciesGraphic();
+ });
+ });
+
for (let actionButton of document.querySelectorAll('.frequencies-stopword-setting-modal-action-buttons')) {
actionButton.addEventListener('click', (event) => {
let action = event.target.closest('.frequencies-stopword-setting-modal-action-buttons').dataset.action;
@@ -101,70 +131,121 @@ class CorpusAnalysisStaticVisualization {
let corpusData = this.data.corpus.o.staticData;
let textProportionsGraphicElement = document.querySelector('#text-proportions-graphic');
let texts = Object.entries(corpusData.s_attrs.text.lexicon);
- let graphData = [
- {
- values: texts.map(text => text[1].counts.token),
- labels: texts.map(text => `${corpusData.values.s_attrs.text[text[0]].title} (${corpusData.values.s_attrs.text[text[0]].publishing_year})`),
- type: 'pie'
- }
- ];
+ let graphtype = document.querySelector('.text-proportions-graph-mode-button.disabled').dataset.graphType;
+ let textProportionsTitleElement = document.querySelector('#text-proportions-title-element');
+
+ if (graphtype === 'bar') {
+ textProportionsTitleElement.innerHTML = 'Bounds';
+ } else if (graphtype === 'pie') {
+ textProportionsTitleElement.innerHTML = 'Proportions';
+ }
+
+ let graphData = this.createTextProportionsGraphData(texts, graphtype);
let graphLayout = {
- showlegend: true,
- height: 486,
+ barmode: graphtype === 'bar' ? 'relative' : '',
+ type: graphtype,
+ showgrid: false,
+ height: 447,
margin: {
l: 10,
r: 10,
- b: 10,
- t: 10
+ b: graphtype === 'bar' ? 80 : 10,
+ t: graphtype === 'bar' ? 80 : 10,
},
legend: {
"orientation": "h",
font: {
size: 10
}
+ },
+ xaxis: {
+ rangemode: 'nonnegative',
+ autorange: true
+ },
+ yaxis: {
+ autorange: true,
+ showticklabels: false
}
};
let config = {
responsive: true,
+ modeBarButtonsToRemove: ['zoom2d', 'select2d', 'lasso2d', 'zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'],
displaylogo: false
};
Plotly.newPlot(textProportionsGraphicElement, graphData, graphLayout, config);
}
+ createTextProportionsGraphData(texts, graphtype) {
+ let corpusData = this.data.corpus.o.staticData;
+ let graphData = [];
+ switch (graphtype) {
+ case 'bar':
+ for (let text of texts) {
+ let textData = {
+ type: 'bar',
+ orientation: 'h',
+ x: [text[1].bounds[1] - text[1].bounds[0]],
+ y: [0.5],
+ text: [`${text[1].bounds[0]} - ${text[1].bounds[1]}`],
+ name: `${corpusData.values.s_attrs.text[text[0]].title} (${corpusData.values.s_attrs.text[text[0]].publishing_year})`,
+ hovertemplate: `${text[1].bounds[0]} - ${text[1].bounds[1]}`,
+ };
+ graphData.push(textData);
+ }
+ break;
+ default:
+ graphData = [
+ {
+ values: texts.map(text => text[1].counts.token),
+ labels: texts.map(text => `${corpusData.values.s_attrs.text[text[0]].title} (${corpusData.values.s_attrs.text[text[0]].publishing_year})`),
+ type: graphtype
+ }
+ ];
+ break;
+ }
+ return graphData;
+ }
+
+ async renderTokenList() {
+ let corpusData = this.data.corpus.o.staticData;
+ let corpusTokenListElement = document.querySelector('.corpus-token-list');
+ let corpusTokenList = new CorpusTokenList(corpusTokenListElement);
+ let stopwords = this.data.stopwords;
+ if (this.data.stopwords === undefined) {
+ stopwords = await this.getStopwords();
+ }
+ stopwords = Object.values(stopwords).flat();
+ let mostFrequent = Object.entries(corpusData.corpus.freqs.word)
+ .sort((a, b) => b[1] - a[1])
+ .filter(item => !stopwords.includes(corpusData.values.p_attrs.word[item[0]].toLowerCase()))
+ .slice(0, 4)
+ .map(item => parseInt(item[0]));
+ let tokenData = [];
+ for (let i = 0; i < Object.values(corpusData.corpus.freqs.word).length; i++) {
+ let resource = {
+ term: corpusData.values.p_attrs.word[i].toLowerCase(),
+ count: corpusData.corpus.freqs.word[i],
+ mostFrequent: mostFrequent.includes(i)
+ };
+ if (!Object.values(stopwords).includes(resource.term)) {
+ tokenData.push(resource);
+ }
+ }
+ corpusTokenList.add(tokenData);
+ }
+
async renderFrequenciesGraphic() {
let corpusData = this.data.corpus.o.staticData;
let frequenciesTokenCategoryDropdownElement = document.querySelector('[data-target="frequencies-token-category-dropdown"]');
- let frequenciesTokenCategoryDropdownListElement = document.querySelector("#frequencies-token-category-dropdown");
let frequenciesGraphicElement = document.querySelector('#frequencies-graphic');
let texts = Object.entries(corpusData.s_attrs.text.lexicon);
let graphtype = document.querySelector('.frequencies-graph-mode-button.disabled').dataset.graphType;
- let graphModeButtons = document.querySelectorAll('.frequencies-graph-mode-button');
-
- frequenciesTokenCategoryDropdownListElement.addEventListener('click', (event) => {
- frequenciesTokenCategoryDropdownElement.firstChild.textContent = event.target.innerHTML;
- this.renderFrequenciesGraphic(corpusData);
- });
-
- graphModeButtons.forEach(graphModeButton => {
- graphModeButton.addEventListener('click', (event) => {
- graphModeButtons.forEach(btn => {
- btn.classList.remove('disabled');
- });
- event.target.closest('.frequencies-graph-mode-button').classList.add('disabled');
- this.renderFrequenciesGraphic(corpusData);
- });
- });
-
let tokenCategory = frequenciesTokenCategoryDropdownElement.firstChild.textContent.toLowerCase();
- let graphData = await this.createFrequenciesGraphData(tokenCategory, texts, corpusData, graphtype);
+ let graphData = await this.createFrequenciesGraphData(tokenCategory, texts, graphtype);
let graphLayout = {
barmode: graphtype === 'bar' ? 'stack' : '',
- margin: {
- t: 20,
- l: 50
- },
yaxis: {
showticklabels: graphtype === 'markers' ? false : true
},
@@ -177,44 +258,48 @@ class CorpusAnalysisStaticVisualization {
Plotly.newPlot(frequenciesGraphicElement, graphData, graphLayout, config);
}
- async createFrequenciesGraphData(category, texts, corpusData, graphtype) {
+ async createFrequenciesGraphData(tokenCategory, texts, graphtype) {
+ let corpusData = this.data.corpus.o.staticData;
let stopwords = this.data.stopwords;
if (this.data.stopwords === undefined) {
stopwords = await this.getStopwords();
}
let stopwordList = Object.values(stopwords).flat();
let graphData = [];
- let filteredData = Object.entries(corpusData.corpus.freqs[category])
+ let filteredData = Object.entries(corpusData.corpus.freqs[tokenCategory])
.sort((a, b) => b[1] - a[1])
- .filter(item => !stopwordList.includes(corpusData.values.p_attrs[category][item[0]].toLowerCase()))
+ .filter(item => !stopwordList.includes(corpusData.values.p_attrs[tokenCategory][item[0]].toLowerCase()))
.slice(0, 5);
- if (graphtype !== 'markers') {
- for (let item of filteredData) {
- let data = {
- x: texts.map(text => `${corpusData.values.s_attrs.text[text[0]].title} (${corpusData.values.s_attrs.text[text[0]].publishing_year})`),
- y: texts.map(text => text[1].freqs[category][item[0]] || 0),
- name: corpusData.values.p_attrs[category][item[0]],
- type: graphtype
- };
- graphData.push(data);
- }
- } else {
- for (let item of filteredData) {
- let size = texts.map(text => text[1].freqs[category][item[0]] || 0);
- let data = {
- x: texts.map(text => `${corpusData.values.s_attrs.text[text[0]].title} (${corpusData.values.s_attrs.text[text[0]].publishing_year})`),
- y: texts.map(text => corpusData.values.p_attrs[category][item[0]]),
- name: corpusData.values.p_attrs[category][item[0]],
- text: texts.map(text => `${corpusData.values.p_attrs[category][item[0]]}
${text[1].freqs[category][item[0]] || 0}`),
- mode: 'markers',
- marker: {
- size: size,
- sizeref: 0.4
- }
- };
- graphData.push(data);
- }
+ switch (graphtype) {
+ case 'markers':
+ for (let item of filteredData) {
+ let size = texts.map(text => text[1].freqs[tokenCategory][item[0]] || 0);
+ let data = {
+ x: texts.map(text => `${corpusData.values.s_attrs.text[text[0]].title} (${corpusData.values.s_attrs.text[text[0]].publishing_year})`),
+ y: texts.map(text => corpusData.values.p_attrs[tokenCategory][item[0]]),
+ name: corpusData.values.p_attrs[tokenCategory][item[0]],
+ text: texts.map(text => `${corpusData.values.p_attrs[tokenCategory][item[0]]}
${text[1].freqs[tokenCategory][item[0]] || 0}`),
+ mode: 'markers',
+ marker: {
+ size: size,
+ sizeref: 0.4
+ }
+ };
+ graphData.push(data);
+ }
+ break;
+ default:
+ for (let item of filteredData) {
+ let data = {
+ x: texts.map(text => `${corpusData.values.s_attrs.text[text[0]].title} (${corpusData.values.s_attrs.text[text[0]].publishing_year})`),
+ y: texts.map(text => text[1].freqs[tokenCategory][item[0]] || 0),
+ name: corpusData.values.p_attrs[tokenCategory][item[0]],
+ type: graphtype
+ };
+ graphData.push(data);
+ }
+ break;
}
return graphData;
}
@@ -320,45 +405,4 @@ class CorpusAnalysisStaticVisualization {
}
this.buttonRendering();
}
-
- renderBoundsGraphic() {
- let corpusData = this.data.corpus.o.staticData;
- let boundsGraphicElement = document.querySelector('#bounds-graphic');
-
- let graphData = [];
- let texts = Object.entries(corpusData.s_attrs.text.lexicon);
-
- graphData = [{
- type: 'bar',
- x: texts.map(text => text[1].bounds[1] - text[1].bounds[0]),
- y: texts.map(text => corpusData.values.s_attrs.text[text[0]].title),
- base: texts.map(text => text[1].bounds[0]),
- text: texts.map(text => `${corpusData.values.s_attrs.text[text[0]].title} (${corpusData.values.s_attrs.text[text[0]].publishing_year})`),
- orientation: 'h',
- hovertemplate: '%{base} - %{x}
%{y}',
- showlegend: false
- }];
-
- let graphLayout = {
- barmode: 'stack',
- type: 'bar',
- showgrid: false,
- xaxis: {
- rangemode: 'nonnegative',
- autorange: true
- },
- yaxis: {
- autorange: true,
- showticklabels: false
- }
- };
-
- let config = {
- responsive: true,
- modeBarButtonsToRemove: ['zoom2d', 'select2d', 'lasso2d', 'zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'],
- displaylogo: false
- };
-
- Plotly.newPlot(boundsGraphicElement, graphData, graphLayout, config);
- }
}
diff --git a/app/static/js/ResourceLists/CorpusTextInfoList.js b/app/static/js/ResourceLists/CorpusTextInfoList.js
index 8338c70a..f1545d70 100644
--- a/app/static/js/ResourceLists/CorpusTextInfoList.js
+++ b/app/static/js/ResourceLists/CorpusTextInfoList.js
@@ -7,7 +7,7 @@ class CorpusTextInfoList extends ResourceList {
}
static defaultOptions = {
- page: 4
+ page: 5
};
constructor(listContainerElement, options = {}) {
@@ -67,12 +67,12 @@ class CorpusTextInfoList extends ResourceList {
Text
- Number of tokens
- Number of sentences
- Number of unique words
- Number of unique lemmas
- Number of unique pos
- Number of unique simple pos
+ Tokens
+ Sentences
+ Unique words
+ Unique lemmas
+ Unique pos
+ Unique simple pos
+ | Term | +Count | +Frequency | +
---|
of texts within the corpus
- -within the texts of the 5 most frequent words in the corpus
- - Wordarrow_drop_down - equalizer - show_chart - bubble_chart - settings +