Skip to content

Commit

Permalink
feat(graphs): Add a graph about proportion of explicit dataset mentio…
Browse files Browse the repository at this point in the history
…ns by scientific fields
  • Loading branch information
annelhote committed Oct 2, 2024
1 parent b01f344 commit 1efbe55
Show file tree
Hide file tree
Showing 8 changed files with 317 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import Highcharts from 'highcharts';
import HCExportingData from 'highcharts/modules/export-data';
import HCExporting from 'highcharts/modules/exporting';
import HighchartsReact from 'highcharts-react-official';
import PropTypes from 'prop-types';
import React, { useEffect, useRef, useState } from 'react';
import { useIntl } from 'react-intl';

import customComments from '../../../../../utils/chartComments';
import { chartOptions } from '../../../../../utils/chartOptions';
import { domains, graphIds } from '../../../../../utils/constants';
import {
capitalize,
cleanNumber,
getObservationLabel,
withDomain,
} from '../../../../../utils/helpers';
import useGlobals from '../../../../../utils/Hooks/useGetGlobals';
import WrapperChart from '../../../../WrapperChart';
import GraphComments from '../../../graph-comments';
import useGetData from './get-data';

HCExporting(Highcharts);
HCExportingData(Highcharts);

const Chart = ({ domain, hasComments, hasFooter, id }) => {
const chartRef = useRef();
const intl = useIntl();
const [chartComments, setChartComments] = useState('');
const [dataTitle, setDataTitle] = useState({});
const idWithDomain = withDomain(id, domain);
const { beforeLastObservationSnap, lastObservationSnap } = useGlobals();
const { allData, isError, isLoading } = useGetData(
beforeLastObservationSnap,
lastObservationSnap,
domain,
);
const { categories, dataGraph } = allData;

useEffect(() => {
setDataTitle({
publicationYear: getObservationLabel(beforeLastObservationSnap, intl),
});
}, [beforeLastObservationSnap, intl]);

const categoriesLabel = categories?.map((item) => capitalize(intl.formatMessage({ id: `app.discipline.${item.key}` }))
.concat('<br>(')
.concat(intl.formatMessage({ id: 'app.effectif' }))
.concat(' = ')
.concat(cleanNumber(item.staff))
.concat(')')) || [];
const optionsGraph = chartOptions[id].getOptions(
idWithDomain,
intl,
categoriesLabel,
dataGraph,
dataTitle,
);
const hasBeta = true;

useEffect(() => {
setChartComments(customComments(allData, idWithDomain, intl));
}, [allData, idWithDomain, intl]);

return (
<WrapperChart
chartRef={chartRef}
dataTitle={dataTitle}
domain={domain}
hasBeta={hasBeta}
hasComments={false}
hasFooter={hasFooter}
id={id}
isError={isError}
isLoading={isLoading || !dataGraph || !categories}
>
<HighchartsReact
highcharts={Highcharts}
id={idWithDomain}
options={optionsGraph}
ref={chartRef}
/>
{hasComments && chartComments && (
<GraphComments comments={chartComments} hasFooter={hasFooter} />
)}
</WrapperChart>
);
};

Chart.defaultProps = {
domain: '',
hasComments: true,
hasFooter: true,
id: 'data.disciplines.mentions.datasets-with-at-least-one-explicit-mention',
};
Chart.propTypes = {
domain: PropTypes.oneOf(domains),
hasComments: PropTypes.bool,
hasFooter: PropTypes.bool,
id: PropTypes.oneOf(graphIds),
};

export default Chart;
124 changes: 124 additions & 0 deletions src/components/Charts/data/disciplines/mentions/get-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import Axios from 'axios';
import { useCallback, useEffect, useState } from 'react';
import { useIntl } from 'react-intl';

import { ES_API_URL, HEADERS } from '../../../../../config/config';
import getFetchOptions from '../../../../../utils/chartFetchOptions';
import {
capitalize,
getCSSValue,
getObservationLabel,
getPublicationYearFromObservationSnap,
} from '../../../../../utils/helpers';

function useGetData(beforeLastObservationSnap, observationSnap, domain) {
const intl = useIntl();
const [allData, setData] = useState({});
const [isError, setError] = useState(false);
const [isLoading, setLoading] = useState(true);

const getDataForLastObservationSnap = useCallback(
async (lastObservationSnap) => {
console.log(lastObservationSnap);
const query = getFetchOptions({
key: 'datasetsWithAtLeastOneExplicitMentionByDiscipline',
domain,
parameters: [lastObservationSnap],
objectType: ['publications'],
});
const res = await Axios.post(ES_API_URL, query, HEADERS);
const data = res.data.aggregations.by_discipline.buckets;
const bsoDomain = intl.formatMessage({ id: `app.bsoDomain.${domain}` });
const categories = [];
const categoriesComments = [];
const publications = [];
const noOutline = {
style: {
textOutline: 'none',
},
};
data
.filter((item) => item.key !== 'unknown')
.forEach((item, catIndex) => {
const numberOfDatasetsWithImplicitMentionsOnly = item.is_implicit.buckets.find((item2) => item2.key === 1)
?.doc_count || 0;
const numberOfDatasetsWithAtLeastOneExplicitMention = item.is_implicit.buckets.find((item2) => item2.key === 0)
?.doc_count || 0;
const numberOfDatasets = numberOfDatasetsWithImplicitMentionsOnly
+ numberOfDatasetsWithAtLeastOneExplicitMention;
const nameClean = item.key.replace(/\n/g, '').replace(' ', ' ');
categories.push({
key: nameClean,
staff: numberOfDatasets,
percent:
(numberOfDatasetsWithAtLeastOneExplicitMention
/ numberOfDatasets)
* 100,
});
categoriesComments.push(
capitalize(
intl.formatMessage({ id: `app.discipline.${nameClean}` }),
),
);
publications.push({
bsoDomain,
discipline: categoriesComments[catIndex],
publicationDate:
getPublicationYearFromObservationSnap(lastObservationSnap),
x: catIndex,
y_abs: numberOfDatasetsWithAtLeastOneExplicitMention,
y_tot: numberOfDatasets,
y:
(numberOfDatasetsWithAtLeastOneExplicitMention
/ numberOfDatasets)
* 100,
});
});

const dataGraph = [
{
name: capitalize(
intl.formatMessage({
id: 'app.publication',
}),
),
data: publications,
color: getCSSValue('--orange-soft-100'),
dataLabels: noOutline,
},
];

const comments = {
publicationYear: getObservationLabel(beforeLastObservationSnap, intl),
};

return {
categories,
comments,
dataGraph,
};
},
[domain, intl],
);

useEffect(() => {
async function getData() {
try {
const dataGraph = await getDataForLastObservationSnap(observationSnap);
setData(dataGraph);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
setError(true);
} finally {
setLoading(false);
}
}
getData();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [observationSnap]);

return { allData, isError, isLoading };
}

export default useGetData;
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ const Chart = ({ domain, hasComments, hasFooter, id }) => {
'datastet_details.has_used',
);
const { categories, dataGraph } = allData;
const hasBeta = true;

useEffect(() => {
setDataTitle({
publicationYear: getObservationLabel(beforeLastObservationSnap, intl),
});
}, [beforeLastObservationSnap, intl]);
const hasBeta = true;

useEffect(() => {
let sortKey;
if (sort === 'sort-staff') {
Expand Down
5 changes: 4 additions & 1 deletion src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1344,11 +1344,14 @@
"app.national-data.disciplines.voies-ouverture.chart-data-shared.tooltip": "<b>{point.discipline} (publications released in {point.publicationDate})</b><br>{point.y:.2f}% of publications ((commentsName)) mention the sharing of their data<br>({point.y_abs} / {point.y_tot} publications producing data)",
"app.national-data.disciplines.voies-ouverture.chart-data-shared.comments": "This graph shows, by discipline, for the latest available publication year, the proportion of publications for which a mention of data sharing was detected, among the publications that produce data. This detection is achieved through an automatic analysis of the full text by the DataStet tool.",
"app.national-data.disciplines.voies-ouverture.chart-data-shared-among-all.title": "Proportion of publications {commentsName} published in {publicationYear} that mention the sharing of their data by discipline among the analysed publications",
"app.national-data.disciplines.voies-ouverture.chart-data-shared-among-all.tooltip": "<b>{point.discipline} (publications released in {point.publicationDate})</b><br>{point.y:.2f}% of publications ((commentsName)) mention a data sharing<br>({point.y_abs} / {point.y_tot} publications qui ont pu être analysées)",
"app.national-data.disciplines.voies-ouverture.chart-data-shared-among-all.tooltip": "<b>{point.discipline} (publications released in {point.publicationDate})</b><br>{point.y:.2f}% of publications ((commentsName)) mention a data sharing<br>({point.y_abs} / {point.y_tot} publications that have been analysed)",
"app.national-data.disciplines.voies-ouverture.chart-data-shared-among-all.comments": "This graph shows, by discipline, for the latest available publication year, the proportion of publications for which a mention of data sharing was detected, among the analysed publications. This detection is achieved through an automatic analysis of the full text by the DataStet tool.",
"app.national-data.disciplines.voies-ouverture.chart-availibility.title": "Proportion of publications {commentsName} published in {publicationYear} that include a \"Data Availability Statement\" section by discipline",
"app.national-data.disciplines.voies-ouverture.chart-availibility.tooltip": "<b>{point.discipline} (publications released in {point.publicationDate})</b><br>{point.y:.2f}% of publications ((commentsName)) have a Data Availability Statement<br>({point.y_abs} / {point.y_tot} publications analysed)",
"app.national-data.disciplines.voies-ouverture.chart-availibility.comments": "This graph shows the proportion of publications in which a Data Availability Statement was identified, by discipline, for the last publication year. The presence of a Data Availability Statement in the body of the publication does not mean that the publication shares its data. This detection is achieved through an automatic analysis of the full text by the GROBID tool.",
"app.national-data.disciplines.mentions.datasets-with-at-least-one-explicit-mention.title": "Proportion of publications {commentsName} published in {publicationYear} with at least one explicit mention of a dataset by discipline",
"app.national-data.disciplines.mentions.datasets-with-at-least-one-explicit-mention.tooltip": "<b>{point.discipline} (publications published in {point.publicationDate})</b><br>{point.y:.2f} % of publications ((commentsName)) mention explicitly at least one dataset<br>({point.y_abs} / {point.y_tot} publications that have been analysed)",
"app.national-data.disciplines.mentions.datasets-with-at-least-one-explicit-mention.comments": "This graph shows, by discipline, for the latest available publication year, the proportion of publications in which at least one explicit mention of a dataset was detected among the publications analysed. This detection is achieved through an automatic analysis of the full text by the DataStet tool.",
"app.national-data.editeurs.statement.title": "Which publishers favor the presence of a Data Availability Statement?",
"app.national-data.editeurs.voies-ouverture.chart-availibility.title": "Proportion of publications {commentsName} published in {publicationYear} that include a \"Data Availability Statement\" section by publisher",
"app.national-data.editeurs.voies-ouverture.chart-availibility.tooltip": "<b>{point.publisher} (publications released in {point.publicationDate})</b><br>{point.y:.2f}% of publications ((commentsName)) have a Data Availability Statement<br>({point.y_abs} / {point.y_tot} publications analysed)",
Expand Down
3 changes: 3 additions & 0 deletions src/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@
"app.national-data.disciplines.voies-ouverture.chart-availibility.title": "Proportion de publications {commentsName} parues en {publicationYear} qui incluent une section \"Data Availability Statement\" par discipline",
"app.national-data.disciplines.voies-ouverture.chart-availibility.tooltip": "<b>{point.discipline} (publications parues en {point.publicationDate})</b><br>{point.y:.2f} % des publications ((commentsName)) présentent un Data Availability Statement<br>({point.y_abs} / {point.y_tot} publications analysées)",
"app.national-data.disciplines.voies-ouverture.chart-availibility.comments": "Ce graphique montre la proportion de publications dans lesquelles un Data Availability Statement a été identifié, par discipline, pour la dernière année de publication. La présence d'un Data Availability Statement dans le corps de la publication ne signifie pas pour autant que la publication partage ses données. La détection se fait par l'analyse automatique du texte intégral de la publication avec l'outil GROBID.",
"app.national-data.disciplines.mentions.datasets-with-at-least-one-explicit-mention.title": "Proportion de publications {commentsName} parues en {publicationYear} avec au moins une mention explicite à un jeu de données par discipline",
"app.national-data.disciplines.mentions.datasets-with-at-least-one-explicit-mention.tooltip": "<b>{point.discipline} (publications parues en {point.publicationDate})</b><br>{point.y:.2f} % des publications ((commentsName)) mentionnent explicitement au moins un jeu de données<br>({point.y_abs} / {point.y_tot} publications qui ont pu être analysées)",
"app.national-data.disciplines.mentions.datasets-with-at-least-one-explicit-mention.comments": "Ce graphique montre, par discipline, pour la dernière année de publication disponible, la proportion de publications pour lesquelles au moins une mention explicite à un jeu de données a été détectée parmi les publications analysées. Cette détection est réalisée grâce à une analyse automatique du texte intégral par l'outil DataStet.",
"app.national-data.editeurs.statement.title": "Quels éditeurs favorisent la présence d'un Data Availability Statement ?",
"app.national-data.editeurs.voies-ouverture.chart-availibility.title": "Proportion de publications {commentsName} parues en {publicationYear} qui incluent une section \"Data Availability Statement\" par éditeur",
"app.national-data.editeurs.voies-ouverture.chart-availibility.tooltip": "<b>{point.publisher} (publications parues en {point.publicationDate})</b><br>{point.y:.2f} % des publications ((commentsName)) présentent un Data Availability Statement<br>({point.y_abs} / {point.y_tot} publications analysées)",
Expand Down
5 changes: 5 additions & 0 deletions src/utils/chartComponents.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ const chartComponents = {
'../components/Charts/data/general/mentions/datasets-with-at-least-one-explicit-mention'
),
),
'data.disciplines.mentions.datasets-with-at-least-one-explicit-mention': lazy(
() => import(
'../components/Charts/data/disciplines/mentions/datasets-with-at-least-one-explicit-mention'
),
),
// Orcid
'orcid.general.chart-evolution': lazy(() => import('../components/Charts/orcid/general/chart-evolution')),
'orcid.general.creation-by-year': lazy(() => import('../components/Charts/orcid/general/creation-by-year')),
Expand Down
40 changes: 40 additions & 0 deletions src/utils/chartFetchOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2533,6 +2533,46 @@ export default function getFetchOptions({
},
},
}),
datasetsWithAtLeastOneExplicitMentionByDiscipline: ([
lastObservationSnap,
]) => ({
size: 0,
query: {
bool: {
filter: [
{
term: {
year: getPublicationYearFromObservationSnap(
lastObservationSnap,
),
},
},
{
range: {
'datastet_details.nb_mentions': {
gt: 0,
},
},
},
],
},
},
aggs: {
by_discipline: {
terms: {
field: 'bso_classification.keyword',
size: 25,
},
aggs: {
is_implicit: {
terms: {
field: 'datastet_details.is_implicit_only',
},
},
},
},
},
}),
codeWithAtLeastOneExplicitMention: ([
lastObservationSnap,
minPublicationDate = 2013,
Expand Down
35 changes: 35 additions & 0 deletions src/utils/chartOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3603,6 +3603,41 @@ export const chartOptions = {
return options;
},
},
'data.disciplines.mentions.datasets-with-at-least-one-explicit-mention': {
getOptions: (id, intl, categories, data, dataTitle) => {
const options = getGraphOptions({ id, intl, dataTitle });
options.chart.type = 'bar';
options.chart.height = '700px';
options.xAxis = {
categories,
};
options.yAxis = getPercentageYAxis();
options.yAxis.title.text = intl.formatMessage({
id: 'app.national-data.general.mentions.datasets-with-at-least-one-explicit-mention.title',
});
options.legend.title.text = intl.formatMessage({
id: 'app.publi.type-hebergement',
});
options.legend.enabled = false;
options.plotOptions = {
series: {
stacking: 'normal',
dataLabels: {
style: {
textOutline: 'none',
},
enabled: false,
},
},
};
options.series = data;
options.exporting.csv = {
columnHeaderFormatter: (item) => (item.isXAxis ? 'field' : item.name),
};
options.exporting.chartOptions.legend.enabled = false;
return options;
},
},
'data.editeurs.voies-ouverture.chart-availibility': {
getOptions: (id, intl, categories, data, dataTitle, sortKey) => {
const options = getGraphOptions({ id, intl, dataTitle });
Expand Down

0 comments on commit 1efbe55

Please sign in to comment.