Skip to content

Commit

Permalink
feat(graphs): Add new graph about part of publications with implicit …
Browse files Browse the repository at this point in the history
…datasets mentions only, see #314
  • Loading branch information
annelhote committed Sep 19, 2024
1 parent 7b582a1 commit 2764940
Show file tree
Hide file tree
Showing 9 changed files with 303 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
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 { 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 { beforeLastObservationSnap, lastObservationSnap } = useGlobals();
const { allData, isError, isLoading } = useGetData(
beforeLastObservationSnap,
lastObservationSnap,
domain,
);
const { categories, dataGraph } = allData;
const dataTitle = {
observationYear: getObservationLabel(lastObservationSnap, intl),
};
const idWithDomain = withDomain(id, domain);
const optionsGraph = chartOptions[id].getOptions(
idWithDomain,
intl,
categories,
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.general.mentions.datasets-with-implicit-mentions-only',
};
Chart.propTypes = {
domain: PropTypes.oneOf(domains),
hasComments: PropTypes.bool,
hasFooter: PropTypes.bool,
id: PropTypes.oneOf(graphIds),
};

export default Chart;
106 changes: 106 additions & 0 deletions src/components/Charts/data/general/mentions/get-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
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,
} 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) => {
const query = getFetchOptions({
key: 'datasetsWithImplicitMentionsOnly',
domain,
parameters: [lastObservationSnap],
objectType: ['publications'],
});
const res = await Axios.post(ES_API_URL, query, HEADERS);
const data = res.data.aggregations.by_publication_year.buckets.sort(
(a, b) => a.key - b.key,
);
const bsoDomain = intl.formatMessage({ id: `app.bsoDomain.${domain}` });
const years = [];
const shared = [];
const noOutline = {
style: {
textOutline: 'none',
},
};
data
.filter(
(el) => el.key > 2012
&& lastObservationSnap.length
&& parseInt(el.key, 10)
< parseInt(lastObservationSnap?.substring(0, 4), 10),
)
.forEach((el) => {
years.push(el.key);
const numberOfDatasetsWithImplicitMentionsOnly = el.is_implicit.buckets.find((item) => item.key === 1)?.doc_count
|| 0;
const numberOfDatasetsWithMixedMentions = el.is_implicit.buckets.find((item) => item.key === 0)?.doc_count
|| 0;
const numberOfDatasets = numberOfDatasetsWithImplicitMentionsOnly
+ numberOfDatasetsWithMixedMentions;
shared.push({
y:
(numberOfDatasetsWithImplicitMentionsOnly / numberOfDatasets)
* 100,
y_abs: numberOfDatasetsWithImplicitMentionsOnly,
y_tot: numberOfDatasets,
x: el.key,
bsoDomain,
});
});

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

return {
categories: years,
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;
1 change: 1 addition & 0 deletions src/components/SubmissionForm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ const SubmissionForm = () => {
);
})
.catch((e) => {
// eslint-disable-next-line no-console
console.error(e);
setIsError(true);
setMessage(
Expand Down
35 changes: 22 additions & 13 deletions src/pages/BaroNational/NationalResearchData/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import QuestionSection from '../../../components/question-section';
import ScrollTop from '../../../components/ScrollTop';
import GlossaryEntries from '../../../translations/glossary.json';
import { mobileButtonLabel } from '../../../utils/constants';
import { getCSSValue } from '../../../utils/helpers';
import { getCSSValue, isInProduction } from '../../../utils/helpers';
import useLang from '../../../utils/Hooks/useLang';

export default function NationalResearchData() {
Expand Down Expand Up @@ -128,38 +128,47 @@ export default function NationalResearchData() {
>
<GraphContent>
<QuestionSection
intlKey='app.national-data.general.partage'
glossaryKeys={['embargo', 'barriere-mobile']}
backgroundColor={blueSoft50}
anchorId='general.partage'
backgroundColor={blueSoft50}
glossaryKeys={['embargo', 'barriere-mobile']}
intlKey='app.national-data.general.partage'
>
<BSOChart id='data.general.voies-ouverture.chart-data-shared' />
<BSOChart id='data.general.voies-ouverture.chart-data-shared-among-all' />
</QuestionSection>
<QuestionSection
intlKey='app.national-data.general.utilisation'
glossaryKeys={['archive-ouverte']}
backgroundColor={blueSoft50}
anchorId='general.utilisation'
backgroundColor={blueSoft25}
glossaryKeys={['archive-ouverte']}
intlKey='app.national-data.general.utilisation'
>
<BSOChart id='data.general.voies-ouverture.chart-data-used' />
</QuestionSection>
<QuestionSection
intlKey='app.national-data.general.creation'
glossaryKeys={['embargo', 'barriere-mobile']}
backgroundColor={blueSoft25}
anchorId='general.creation'
backgroundColor={blueSoft50}
glossaryKeys={['embargo', 'barriere-mobile']}
intlKey='app.national-data.general.creation'
>
<BSOChart id='data.general.voies-ouverture.chart-data-created' />
</QuestionSection>
<QuestionSection
intlKey='app.national-data.general.statement'
glossaryKeys={['archive-ouverte']}
backgroundColor={blueSoft25}
anchorId='general.statement'
backgroundColor={blueSoft25}
glossaryKeys={['archive-ouverte']}
intlKey='app.national-data.general.statement'
>
<BSOChart id='data.general.voies-ouverture.chart-availibility' />
</QuestionSection>
<QuestionSection
anchorId='general.mentions'
backgroundColor={blueSoft50}
glossaryKeys={['archive-ouverte']}
intlKey='app.national-data.general.mentions'
isDisplayed={!isInProduction()}
>
<BSOChart id='data.general.mentions.datasets-with-implicit-mentions-only' />
</QuestionSection>
</GraphContent>
</GraphItem>

Expand Down
4 changes: 4 additions & 0 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,9 @@
"app.national-data.general.voies-ouverture.chart-availibility.title": "Proportion of publications {commentsName} that include a \"Data Availability Statement\" section by publication year",
"app.national-data.general.voies-ouverture.chart-availibility.tooltip": "<b>Publication year {point.x}</b><br>{point.y:.2f}% of publications ((commentsName)) have a Data Availability Statement<br>({point.y_abs} / {point.y_tot} analysed publications)",
"app.national-data.general.voies-ouverture.chart-availibility.comments": "This graph shows the proportion of publications that report making data available (mention of a Data Availability Statement identified), by publication year. The presence of a Data Availability Statement in the body of the publication does not mean that the authors of the publication actually share their data when requested. This detection is achieved through an automatic analysis of the full text by the GROBID tool.",
"app.national-data.general.mentions.title": "Are the datasets mentioned by name?",
"app.national-data.general.mentions.datasets-with-implicit-mentions-only.title": "Proportion of publications containing only implicit references to datasets",
"app.national-data.general.mentions.datasets-with-implicit-mentions-only.tooltip": "{point.y:.2f}% of French publications published in <b>{point.x}</b> and mentioning datasets<br />mention them <b>implicitly only</b><br />({point.y_abs} / {point.y_tot} publications mentioning datasets)",
"app.national-data.disciplines.utilisation.title": "What is the level of data usage by discipline?",
"app.national-data.disciplines.creation.title": "What is the level of data production by discipline?",
"app.national-data.disciplines.partage.title": "What is the level of data sharing by discipline?",
Expand Down Expand Up @@ -1385,6 +1388,7 @@
"app.national-thesis.general.dynamique-ouverture.description": "The open access rate of French PhD theses shows a clear trend towards more and more openness. A small half of the theses defended in 2010 are open, while about ¾ of the theses defended at the end of the 2010s are open. The embargo periods temporarily show a slight decrease of the opening rate for the most recent years of defences.<linebreak></linebreak>The majority of doctoral theses are available in open access on the Internet, sometimes after a period of restriction. The temporal restrictions in the diffusion are of two kinds, embargo or confidentiality, and depend on the type of diffusion, free or restricted, chosen by the author:<linebreak></linebreak>- the embargo applies only to theses intended to be disseminated on the Internet. During the embargo period, the thesis must be disseminated in restricted access, in the French academic community.<linebreak></linebreak>- the confidentiality can apply as well to the theses intended to be diffused in free access on internet as to the theses intended to be diffused in restricted access within the premises of the institution of defense or of the French university community. During the period of confidentiality, no one can have access to the thesis. For the most recent years, the opening rate appears slightly lower, notably because of the embargo periods of one year on average.",
"app.national-thesis.general.dynamique-ouverture.title": "What are the trends of the opening of doctoral theses in France?",
"app.publications.local": "publications {commentsName}",
"app.implicit-mentions-only": "Proportion of publications containing only implicit references to datasets",
"app.created-data": "Proportion of publications mentionning a production of data",
"app.shared-data": "Proportion of publications mentionning a share of data",
"app.created-software": "Proportion of publications mentionning a code or software creation",
Expand Down
4 changes: 4 additions & 0 deletions src/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@
"app.national-data.general.voies-ouverture.chart-availibility.title": "Proportion de publications {commentsName} qui incluent une section \"Data Availability Statement\" (déclaration sur la mise à disposition des données) par année de publication",
"app.national-data.general.voies-ouverture.chart-availibility.tooltip": "<b>Année de publication {point.x}</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.general.voies-ouverture.chart-availibility.comments": "Ce graphique montre la proportion de publications qui déclarent rendre disponibles les données (mention d'un Data Availability Statement identifiée), par année de publication. La présence d'un Data Availability Statement dans le corps de la publication ne signifie pas pour autant que les auteurs de la publication partagent effectivement leurs données quand la demande leur en est faite. Cette détection est réalisée grâce à une analyse automatique du texte intégral par l'outil GROBID.",
"app.national-data.general.mentions.title": "Les jeux de données mentionnés le sont-ils nommément ?",
"app.national-data.general.mentions.datasets-with-implicit-mentions-only.title": "Proportion de publications comportant exclusivement des mentions implicites de jeux de données",
"app.national-data.general.mentions.datasets-with-implicit-mentions-only.tooltip": "{point.y:.2f} % des publications françaises parues en <b>{point.x}</b> et mentionnant des jeux de données<br />ne les mentionnent qu'<b>implicitement uniquement</b><br />({point.y_abs} / {point.y_tot} publications mentionnant des jeux de données)",
"app.national-data.disciplines.utilisation.title": "Quel est le niveau d'utilisation de données par discipline ?",
"app.national-data.disciplines.creation.title": "Quel est le niveau de production de données par discipline ?",
"app.national-data.disciplines.partage.title": "Quel est le niveau de partage de données par discipline ?",
Expand Down Expand Up @@ -1276,6 +1279,7 @@
"app.publications.global": "publications françaises (tous domaines)",
"app.publications.health": "publications françaises en santé",
"app.publications.local": "publications {commentsName}",
"app.implicit-mentions-only": "Proportion des publications comportant exclusivement des mentions implicites de jeux de données",
"app.publishers": "éditeurs et plateformes",
"app.publishers-filter-label": "Sélectionner un éditeur",
"app.publishers.apc-gold": "APC Gold",
Expand Down
7 changes: 7 additions & 0 deletions src/utils/chartComponents.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ const ChartSoftwareSharedAmongAllDiscipline = lazy(() => import(
const ChartSoftwareSharedOa = lazy(() => import(
'../components/Charts/software/oa/voies-ouverture/chart-software-shared'
));
const DatasetsWithImplicitMentionsOnly = lazy(() => import(
'../components/Charts/data/general/mentions/datasets-with-implicit-mentions-only'
));

// Orcid
const OrcidEvolution = lazy(() => import('../components/Charts/orcid/general/chart-evolution'));
Expand Down Expand Up @@ -429,6 +432,7 @@ const chartComponents = {
ChartTauxOuvertureThesis,
'thesis.disciplines.voies-ouverture.chart-repartition-thesis':
ChartRepartitionThesis,
// Code
'software.general.voies-ouverture.chart-software-used': ChartSoftwareUsed,
'software.general.voies-ouverture.chart-software-created':
ChartSoftwareCreated,
Expand All @@ -444,6 +448,7 @@ const chartComponents = {
'software.disciplines.voies-ouverture.chart-software-shared-among-all':
ChartSoftwareSharedAmongAllDiscipline,
'software.oa.voies-ouverture.chart-software-shared': ChartSoftwareSharedOa,
// Data
'data.general.voies-ouverture.chart-data-used': ChartDataUsed,
'data.general.voies-ouverture.chart-data-created': ChartDataCreated,
'data.general.voies-ouverture.chart-data-shared': ChartDataShared,
Expand All @@ -461,6 +466,8 @@ const chartComponents = {
ChartDataAvailibilityDiscipline,
'data.editeurs.voies-ouverture.chart-availibility':
ChartDataAvailibilityEditeur,
'data.general.mentions.datasets-with-implicit-mentions-only':
DatasetsWithImplicitMentionsOnly,
// Orcid
'orcid.general.chart-evolution': OrcidEvolution,
'orcid.general.creation-by-year': OrcidCreationByYear,
Expand Down
44 changes: 44 additions & 0 deletions src/utils/chartFetchOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2489,6 +2489,50 @@ export default function getFetchOptions({
},
},
}),
datasetsWithImplicitMentionsOnly: ([
lastObservationSnap,
minPublicationDate = 2013,
]) => ({
size: 0,
query: {
bool: {
filter: [
{
range: {
year: {
gte: minPublicationDate,
lte: getPublicationYearFromObservationSnap(
lastObservationSnap,
),
},
},
},
{
range: {
'datastet_details.nb_mentions': {
gt: 0,
},
},
},
],
},
},
aggs: {
by_publication_year: {
terms: {
field: 'year',
size: 10,
},
aggs: {
is_implicit: {
terms: {
field: 'datastet_details.is_implicit_only',
},
},
},
},
},
}),
};
const queryResponse = allOptions[key](parameters) || {};
if (!queryResponse.query?.bool?.filter) {
Expand Down
Loading

0 comments on commit 2764940

Please sign in to comment.