{t('There is no data yet.', {ns: 'statistics'})}
+ ), + + title: title('Recordings by Project'), + subtitle: t( + 'Total Recordings: {{count}}', + { + ns: 'statistics', + count: getTotalRecordings(), + } + ), + onToggleFilters: () => setShowFiltersBreakdown((prev) => !prev), + }, + { + content: + getTotalRecordings() > 0 ? ( +{t('There is no data yet.', {ns: 'statistics'})}
+ ), + title: title('Recordings by Site'), + subtitle: t( + 'Total Recordings: {{count}}', + { + ns: 'statistics', + count: getTotalRecordings(), + } + ), + onToggleFilters: () => setShowFiltersBreakdown((prev) => !prev), + }, + { + content: + getTotalEvents() > 0 ? ( +{t('There is no data yet.', {ns: 'statistics'})}
+ ), + title: title('Events by Project'), + subtitle: t( + 'Total Events: {{count}}', + { + ns: 'statistics', + count: getTotalEvents(), + } + ), + onToggleFilters: () => setShowFiltersBreakdown((prev) => !prev), + }, + ]} + /> + > + ); +}; +Electrophysiology.propTypes = { + data: PropTypes.object, + baseURL: PropTypes.string, + updateFilters: PropTypes.func, + showChart: PropTypes.func, +}; +Electrophysiology.defaultProps = { + data: {}, +}; + +export default Electrophysiology; diff --git a/modules/statistics/jsx/widgets/helpers/chartBuilder.js b/modules/statistics/jsx/widgets/helpers/chartBuilder.js index 65836ce520..2c479d97b5 100644 --- a/modules/statistics/jsx/widgets/helpers/chartBuilder.js +++ b/modules/statistics/jsx/widgets/helpers/chartBuilder.js @@ -296,6 +296,7 @@ const setupCharts = async (t, targetIsModal, chartDetails, totalLabel) => { let labels = []; let colours = []; if (chart.dataType === 'pie') { + console.log('charDetails', chartDetails); columns = formatPieData(chartData); colours = siteColours; // reformating the columns for a bar chart when it was originally pie data diff --git a/modules/statistics/jsx/widgets/studyprogression.js b/modules/statistics/jsx/widgets/studyprogression.js index 6bf4e9b39c..3e375a7579 100644 --- a/modules/statistics/jsx/widgets/studyprogression.js +++ b/modules/statistics/jsx/widgets/studyprogression.js @@ -8,6 +8,7 @@ import {setupCharts} from './helpers/chartBuilder'; import {useTranslation} from 'react-i18next'; import jaStrings from '../../locale/ja/LC_MESSAGES/statistics.json'; import frStrings from '../../locale/fr/LC_MESSAGES/statistics.json'; +import zhStrings from '../../locale/zh/LC_MESSAGES/statistics.json'; /** * StudyProgression - a widget containing statistics for study data. @@ -23,6 +24,7 @@ const StudyProgression = (props) => { useEffect( () => { i18n.addResourceBundle('ja', 'statistics', jaStrings); i18n.addResourceBundle('fr', 'statistics', frStrings); + i18n.addResourceBundle('zh', 'statistics', zhStrings); // Re-set default state that depended on the translation let newdetails = {...chartDetails}; @@ -30,6 +32,7 @@ const StudyProgression = (props) => { = t('Scan sessions per site', {ns: 'statistics'}); newdetails['total_recruitment']['siterecruitment_bymonth']['title'] = t('Recruitment per site', {ns: 'statistics'}); + newdetails['project_sizes']['size_byproject']['title'] = t('Dataset size breakdown by project', {ns: 'statistics'}); newdetails['project_sizes']['size_byproject']['label'] @@ -40,6 +43,11 @@ const StudyProgression = (props) => { = t('Size (GB)', {ns: 'statistics'}); newdetails['project_sizes']['size_byproject']['titlePrefix'] = t('Project', {ns: 'loris'}); + newdetails['project_sizes']['size_byproject']['title'] + = t('Dataset size breakdown by project', {ns: 'statistics'}); + + newdetails['project_sizes']['size_byproject']['label'] + = t('Size (GB)', {ns: 'statistics'}); setChartDetails(newdetails); }, []); diff --git a/modules/statistics/locale/fr/LC_MESSAGES/statistics.po b/modules/statistics/locale/fr/LC_MESSAGES/statistics.po index c74019580b..33637f9f28 100644 --- a/modules/statistics/locale/fr/LC_MESSAGES/statistics.po +++ b/modules/statistics/locale/fr/LC_MESSAGES/statistics.po @@ -166,6 +166,40 @@ msgstr "Circulaire" msgid "Bar" msgstr "Barre" +# EEG charts +msgid "EEG Recordings by project" +msgstr "Enregistrements EEG par project" + +msgid "EEG Recordings by site" +msgstr "Enregistrements EEG par site" + +msgid "EEG Recordings" +msgstr "Enregistrements EEG" + +msgid "EEG Events by project" +msgstr "Événements EEG par project" + +msgid "EEG Events" +msgstr "Événements EEG" + +msgid "EEG data" +msgstr "Donnés EEG" + +msgid "Recordings by Project" +msgstr "Enregistrements par project" + +msgid "Total Recordings: {{count}}" +msgstr "Enregistrements totaux: {{count}}" + +msgid "Recordings by Site" +msgstr "Enregistrements par site" + +msgid "Events by Project" +msgstr "Événements par projet" + +msgid "Total Events: {{count}}" +msgstr "Événements totaux: {{count}}" + msgid "General Description" msgstr "Description générale" diff --git a/modules/statistics/locale/statistics.pot b/modules/statistics/locale/statistics.pot index 2afa3bef30..8435aaf54a 100644 --- a/modules/statistics/locale/statistics.pot +++ b/modules/statistics/locale/statistics.pot @@ -163,6 +163,41 @@ msgstr "" msgid "Bar" msgstr "" + +# EEG charts +msgid "EEG Recordings by project" +msgstr "" + +msgid "EEG Recordings by site" +msgstr "" + +msgid "EEG Recordings" +msgstr "" + +msgid "EEG Events by project" +msgstr "" + +msgid "EEG Events" +msgstr "" + +msgid "EEG data" +msgstr "" + +msgid "Recordings by Project" +msgstr "" + +msgid "Total Recordings: {{count}}" +msgstr "" + +msgid "Recordings by Site" +msgstr "" + +msgid "Events by Project" +msgstr "" + +msgid "Total Events: {{count}}" +msgstr "" + msgid "General Description" msgstr "" diff --git a/modules/statistics/php/charts.class.inc b/modules/statistics/php/charts.class.inc index c9e3bed0a8..4f763883dd 100644 --- a/modules/statistics/php/charts.class.inc +++ b/modules/statistics/php/charts.class.inc @@ -109,6 +109,14 @@ class Charts extends \NDB_Page return $this->_handleAgeDistributionByProject($request); case 'size_byproject': return $this->_handleProjectSizeBreakdown(); + case 'eeg_recordings_by_site': + return $this->_handleSiteEEGRecordingsBreakdown($request); + case 'eeg_recordings_by_project': + return $this->_handleProjectEEGRecordingsBreakdown($request); + case 'eeg_events_by_project': + return $this->_handleProjectEEGEventsBreakdown($request); + case 'size_byproject': + return $this->_handleProjectSizeBreakdown(); default: return new \LORIS\Http\Response\JSON\NotFound(); } @@ -931,6 +939,191 @@ class Charts extends \NDB_Page } } } + return (new \LORIS\Http\Response\JsonResponse($projectData)); + } + + /** + * Handle an incoming request for EEG recordings by site breakdown. + * + * @param ServerRequestInterface $request The incoming PSR7 request + * + * @return ResponseInterface + */ + private function _handleSiteEEGRecordingsBreakdown( + ServerRequestInterface $request + ) { + $DB = \NDB_Factory::singleton()->database(); + $user = \NDB_Factory::singleton()->user(); + $sites = $user->getSites(); + + $conditions = $this->_buildQueryConditions($request); + + $data = iterator_to_array( + $DB->pselect( + "SELECT + s.CenterID, + psc.Name, + COUNT(distinct s.ID) as count + FROM physiological_file pf + JOIN session s ON (s.ID=pf.SessionID) + JOIN candidate c ON (c.ID=s.CandidateID) + JOIN psc USING (CenterID) + {$conditions['participantStatusJoin']} + WHERE 1 = 1 + {$conditions['projectQuery']} + {$conditions['cohortQuery']} + {$conditions['visitQuery']} + {$conditions['siteQuery']} + {$conditions['participantStatusQuery']} + GROUP BY s.CenterID + ORDER BY s.CenterID", + $conditions['params'] + ) + ); + + $processedData = []; + foreach ($data as $row) { + $processedData[$row['CenterID']] = [ + 'CenterID' => $row['CenterID'], + 'Name' => $row['Name'], + 'count' => intval($row['count']), + ]; + } + + $siteData = []; + foreach ($sites as $siteID => $site) { + if (in_array($siteID, array_keys($processedData))) { + $siteData[] = [ + 'label' => $site->getCenterName(), + 'total' => $processedData[$siteID]['count'], + ]; + } + } + + return (new \LORIS\Http\Response\JsonResponse($siteData)); + } + + /** + * Handle an incoming request for EEG recordings by project breakdown. + * + * @param ServerRequestInterface $request The incoming PSR7 request + * + * @return ResponseInterface + */ + private function _handleProjectEEGRecordingsBreakdown( + ServerRequestInterface $request + ) { + $DB = \NDB_Factory::singleton()->database(); + $user = \NDB_Factory::singleton()->user(); + $projects = $user->getProjects(); + + $conditions = $this->_buildQueryConditions($request); + + $data = iterator_to_array( + $DB->pselect( + "SELECT + s.ProjectID, + p.Name, + COUNT(distinct s.ID) as count + FROM physiological_file pf + JOIN session s ON (s.ID=pf.SessionID) + JOIN Project p USING (ProjectID) + JOIN candidate c ON (c.ID=s.CandidateID) + JOIN psc ON (s.CenterID = psc.CenterID) + {$conditions['participantStatusJoin']} + WHERE 1 = 1 + {$conditions['projectQuery']} + {$conditions['cohortQuery']} + {$conditions['visitQuery']} + {$conditions['siteQuery']} + {$conditions['participantStatusQuery']} + GROUP BY s.CenterID + ORDER BY s.CenterID", + $conditions['params'] + ) + ); + + $processedData = []; + foreach ($data as $row) { + $processedData[$row['ProjectID']] = [ + 'ProjectID' => $row['ProjectID'], + 'Name' => $row['Name'], + 'count' => intval($row['count']), + ]; + } + + $projectData = []; + foreach ($projects as $projectID => $projectName) { + if (in_array($projectID, array_keys($processedData))) { + $projectData[] = [ + 'label' => $projectName, + 'total' => $processedData[$projectID]['count'], + ]; + } + } + + return (new \LORIS\Http\Response\JsonResponse($projectData)); + } + + /** + * Handle an incoming request for EEG events by project breakdown. + * + * @param ServerRequestInterface $request The incoming PSR7 request + * + * @return ResponseInterface + */ + private function _handleProjectEEGEventsBreakdown( + ServerRequestInterface $request + ) { + $DB = \NDB_Factory::singleton()->database(); + $user = \NDB_Factory::singleton()->user(); + $projects = $user->getProjects(); + + $conditions = $this->_buildQueryConditions($request); + + $data = iterator_to_array( + $DB->pselect( + "SELECT + s.ProjectID, + p.Name, + COUNT(pte.PhysiologicalTaskEventID) as count + FROM physiological_task_event pte + JOIN physiological_file pf USING (PhysiologicalFileID) + JOIN session s ON (s.ID=pf.SessionID) + JOIN Project p USING (ProjectID) + JOIN candidate c ON (c.ID=s.CandidateID) + JOIN psc ON (s.CenterID = psc.CenterID) + {$conditions['participantStatusJoin']} + WHERE 1 = 1 + {$conditions['projectQuery']} + {$conditions['cohortQuery']} + {$conditions['visitQuery']} + {$conditions['siteQuery']} + {$conditions['participantStatusQuery']} + GROUP BY s.CenterID + ORDER BY s.CenterID", + $conditions['params'] + ) + ); + + $processedData = []; + foreach ($data as $row) { + $processedData[$row['ProjectID']] = [ + 'ProjectID' => $row['ProjectID'], + 'Name' => $row['Name'], + 'count' => intval($row['count']), + ]; + } + + $projectData = []; + foreach ($projects as $projectID => $projectName) { + if (in_array($projectID, array_keys($processedData))) { + $projectData[] = [ + 'label' => $projectName, + 'total' => $processedData[$projectID]['count'], + ]; + } + } return (new \LORIS\Http\Response\JsonResponse($projectData)); } diff --git a/modules/statistics/php/widgets.class.inc b/modules/statistics/php/widgets.class.inc index e43b49aad1..4f46699245 100644 --- a/modules/statistics/php/widgets.class.inc +++ b/modules/statistics/php/widgets.class.inc @@ -211,6 +211,26 @@ class Widgets extends \NDB_Page implements ETagCalculator } } + $eeg_recordings = $db->pselectOneInt( + "SELECT COUNT(distinct s.ID) as total_recordings + FROM physiological_file pf + JOIN session s ON (s.ID=pf.SessionID) + WHERE s.ProjectID IN (" . + join(',', $user->getProjectIDs()) + . ")", + [] + ); + $eeg_events = $db->pselectOneInt( + "SELECT COUNT(pte.PhysiologicalTaskEventID) as total_events + FROM physiological_task_event pte + JOIN physiological_file pf USING (PhysiologicalFileID) + JOIN session s ON (s.ID=pf.SessionID) + WHERE s.ProjectID IN (" . + join(',', $user->getProjectIDs()) + . ")", + [] + ); + $participantStatusOptions = \Candidate::getParticipantStatusOptions(); @@ -236,6 +256,11 @@ class Widgets extends \NDB_Page implements ETagCalculator $values['size_byproject'] = $projectsSizes; + $values['eeg_data'] = [ + 'total_recordings' => $eeg_recordings, + 'total_events' => $eeg_events + ]; + $this->_cache = new \LORIS\Http\Response\JsonResponse($values); return $this->_cache;