Token list first implementation+ query builder fix

This commit is contained in:
Inga Kirschnick
2023-07-18 16:01:31 +02:00
parent 6c744fc3ba
commit 691d4757ff
8 changed files with 322 additions and 474 deletions

View File

@@ -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();

View File

@@ -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]]}<br>${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]]}<br>${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} <br>%{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);
}
}