From 1266dc6739c19af437f267eb7deb913307bb1640 Mon Sep 17 00:00:00 2001 From: jesscall Date: Fri, 12 Nov 2021 11:56:42 -0500 Subject: [PATCH 1/7] [EEG Browser] Add front-end support of annotations in event panel & overlaid in signal viewer --- .../jsx/electrophysiologySessionView.js | 12 +++-- .../src/eeglab/EEGLabSeriesProvider.tsx | 53 ++++++++++++++----- .../src/series/store/types.tsx | 6 +++ .../php/sessions.class.inc | 21 ++------ 4 files changed, 61 insertions(+), 31 deletions(-) diff --git a/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js b/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js index 6bffcb9f60f..d96e36ec1ac 100644 --- a/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js +++ b/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js @@ -192,10 +192,11 @@ class ElectrophysiologySessionView extends Component { } return resp.json(); }) - .then((data) => { + .then((data) => { + console.log(data); const database = data.database.map((dbEntry) => ({ ...dbEntry, - // EEG Visualisation urls + // EEG Visualisation parameters chunksURLs: dbEntry && dbEntry.file.chunks_urls.map( @@ -219,6 +220,9 @@ class ElectrophysiologySessionView extends Component { + '/electrophysiology_browser/file_reader/?file=' + group.links[1].file ), + annotations: + dbEntry + && dbEntry.file.annotations, })); this.setState({ @@ -318,6 +322,7 @@ class ElectrophysiologySessionView extends Component { chunksURLs, epochsURL, electrodesURL, + annotations, } = this.state.database[i]; const file = this.state.database[i].file; const splitPagination = []; @@ -346,7 +351,8 @@ class ElectrophysiologySessionView extends Component { chunksURLs?.[file.splitData?.splitIndex] || chunksURLs } epochsURL={epochsURL} - electrodesURL={electrodesURL} + electrodesURL={electrodesURL} + annotations={annotations} > { this.store = createStore( rootReducer, - applyMiddleware(thunk, epicMiddleware) + composeWithDevTools(applyMiddleware(thunk, epicMiddleware)) ); this.state = { @@ -67,6 +70,7 @@ class EEGLabSeriesProvider extends Component { chunksURL, epochsURL, electrodesURL, + annotations, limit, } = props; @@ -106,20 +110,45 @@ class EEGLabSeriesProvider extends Component { this.store.dispatch(setInterval(timeInterval)); } } - ).then(() => Promise.race(racers(fetchText, epochsURL)).then((text) => { + ).then(() => Promise.race(racers(fetchText, epochsURL)) + .then((text) => { if (!(typeof text.json === 'string' || text.json instanceof String)) return; + return tsvParse( + text.json.replace('trial_type', 'label')) + .map(({ onset, duration, label }, i) => ({ + onset: parseFloat(onset), + duration: parseFloat(duration), + type: 'Event', + label: label, + comment: null, + channels: 'all', + })); + }).then(events => { + let epochs = events; + annotations.instances.map(instance => { + const label = annotations.labels + .find(label => + label.AnnotationLabelID == instance.AnnotationLabelID + ).LabelDescription; + epochs.push({ + onset: parseFloat(instance.Onset), + duration: parseFloat(instance.Duration), + type: 'Annotation', + label: label, + comment: null, + channels: 'all', + }); + }); + return epochs; + }).then(epochs => { this.store.dispatch( - setEpochs(tsvParse( - text.json.replace('trial_type', 'label')) - .map(({onset, duration, label}, i) => ({ - onset: parseFloat(onset), - duration: parseFloat(duration), - type: 'Event', - label: label, - comment: null, - channels: 'all', - })) + setEpochs( + epochs + .flat() + .sort(function(a, b) { + return a.onset - b.onset; + }) ) ); this.store.dispatch(updateFilteredEpochs()); diff --git a/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/series/store/types.tsx b/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/series/store/types.tsx index 2c378859f57..8d2f33de2c9 100644 --- a/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/series/store/types.tsx +++ b/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/series/store/types.tsx @@ -32,6 +32,12 @@ export type Epoch = { channels: number[] | "all", }; +export type Annotation = { + instances: any[], + labels: any[], + metadata: any[] +} + export type RightPanel = 'annotationForm' | 'epochList' | null; export type Electrode = { diff --git a/modules/electrophysiology_browser/php/sessions.class.inc b/modules/electrophysiology_browser/php/sessions.class.inc index 24f4595be41..c8d71064917 100644 --- a/modules/electrophysiology_browser/php/sessions.class.inc +++ b/modules/electrophysiology_browser/php/sessions.class.inc @@ -468,24 +468,13 @@ class Sessions extends \NDB_Page ['physioFileID' => $physioFileID] ); - $fileOutput = $db->pselectone( - 'SELECT pot.OutputTypeName - FROM physiological_output_type pot - INNER JOIN physiological_file AS pf - ON pf.PhysiologicalFileID=:PFID - AND pf.PhysiologicalOutputTypeID=pot.PhysiologicalOutputTypeID', - ['PFID' => $physioFileID] - ); - //Get the annotation data if the output type is derivative - //Get the annotation data if the output type is derivative - if (strcmp($fileOutput, 'derivative') == 0) { - $annotations = new ElectrophysioAnnotations( - intval($physioFileID) - ); - $fileSummary['annotations'] = $annotations->getData(); - } + //Get the annotation data + $annotations = new ElectrophysioAnnotations( + intval($physioFileID) + ); + $fileSummary['annotations'] = $annotations->getData(); $fileSummary['output_type'] = $fileOutput; $fileSummary['splitData'] = $physioFileObj->getSplitData(0); From c075c244214b93a970481d82f15e0902fefa1618 Mon Sep 17 00:00:00 2001 From: jesscall Date: Fri, 12 Nov 2021 12:53:32 -0500 Subject: [PATCH 2/7] cleanup types and rm debuging statements --- .../jsx/electrophysiologySessionView.js | 1 - .../src/eeglab/EEGLabSeriesProvider.tsx | 7 +++---- .../react-series-data-viewer/src/series/store/types.tsx | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js b/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js index d96e36ec1ac..5158f6ba9d2 100644 --- a/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js +++ b/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js @@ -193,7 +193,6 @@ class ElectrophysiologySessionView extends Component { return resp.json(); }) .then((data) => { - console.log(data); const database = data.database.map((dbEntry) => ({ ...dbEntry, // EEG Visualisation parameters diff --git a/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/eeglab/EEGLabSeriesProvider.tsx b/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/eeglab/EEGLabSeriesProvider.tsx index c93a216cf1e..f9a4671dd6f 100644 --- a/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/eeglab/EEGLabSeriesProvider.tsx +++ b/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/eeglab/EEGLabSeriesProvider.tsx @@ -17,8 +17,7 @@ import {setDomain, setInterval} from '../series/store/state/bounds'; import {updateFilteredEpochs} from '../series/store/logic/filterEpochs'; import {setElectrodes} from '../series/store/state/montage'; import {Channel} from '../series/store/types'; -import {Annotation} from '../series/store/types'; -import {composeWithDevTools} from 'redux-devtools-extension'; +import {AnnotationMetadata} from '../series/store/types'; declare global { interface Window { @@ -30,7 +29,7 @@ type CProps = { chunksURL: string, epochsURL: string, electrodesURL: string, - annotations: Annotation, + annotations: AnnotationMetadata, limit: number, }; @@ -53,7 +52,7 @@ class EEGLabSeriesProvider extends Component { this.store = createStore( rootReducer, - composeWithDevTools(applyMiddleware(thunk, epicMiddleware)) + applyMiddleware(thunk, epicMiddleware) ); this.state = { diff --git a/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/series/store/types.tsx b/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/series/store/types.tsx index 8d2f33de2c9..2559c96bccf 100644 --- a/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/series/store/types.tsx +++ b/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/series/store/types.tsx @@ -32,7 +32,7 @@ export type Epoch = { channels: number[] | "all", }; -export type Annotation = { +export type AnnotationMetadata = { instances: any[], labels: any[], metadata: any[] From 2bcb2e8d6f5f0a3c074c577ef863568a5b57a332 Mon Sep 17 00:00:00 2001 From: jesscall Date: Fri, 12 Nov 2021 13:28:00 -0500 Subject: [PATCH 3/7] make checkstatic --- modules/electrophysiology_browser/php/sessions.class.inc | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/electrophysiology_browser/php/sessions.class.inc b/modules/electrophysiology_browser/php/sessions.class.inc index c8d71064917..1ffd1c15f70 100644 --- a/modules/electrophysiology_browser/php/sessions.class.inc +++ b/modules/electrophysiology_browser/php/sessions.class.inc @@ -468,7 +468,6 @@ class Sessions extends \NDB_Page ['physioFileID' => $physioFileID] ); - //Get the annotation data $annotations = new ElectrophysioAnnotations( intval($physioFileID) From 174342076c183b0864d90afde029c86001259f3c Mon Sep 17 00:00:00 2001 From: Laetitia Fesselier Date: Tue, 22 Nov 2022 14:56:14 -0500 Subject: [PATCH 4/7] Phan fix --- modules/electrophysiology_browser/php/sessions.class.inc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/electrophysiology_browser/php/sessions.class.inc b/modules/electrophysiology_browser/php/sessions.class.inc index 1ffd1c15f70..7af498a0106 100644 --- a/modules/electrophysiology_browser/php/sessions.class.inc +++ b/modules/electrophysiology_browser/php/sessions.class.inc @@ -468,6 +468,15 @@ class Sessions extends \NDB_Page ['physioFileID' => $physioFileID] ); + $fileOutput = $db->pselectone( + 'SELECT pot.OutputTypeName + FROM physiological_output_type pot + INNER JOIN physiological_file AS pf + ON pf.PhysiologicalFileID=:PFID + AND pf.PhysiologicalOutputTypeID=pot.PhysiologicalOutputTypeID', + ['PFID' => $physioFileID] + ); + //Get the annotation data $annotations = new ElectrophysioAnnotations( intval($physioFileID) From 98c85ec1ad5185acb7985db21b52646d2e461c3e Mon Sep 17 00:00:00 2001 From: Laetitia Fesselier Date: Tue, 22 Nov 2022 15:34:09 -0500 Subject: [PATCH 5/7] Typo fix --- .../jsx/electrophysiologySessionView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js b/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js index 5158f6ba9d2..d3f7bd41155 100644 --- a/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js +++ b/modules/electrophysiology_browser/jsx/electrophysiologySessionView.js @@ -195,7 +195,7 @@ class ElectrophysiologySessionView extends Component { .then((data) => { const database = data.database.map((dbEntry) => ({ ...dbEntry, - // EEG Visualisation parameters + // EEG Visualization parameters chunksURLs: dbEntry && dbEntry.file.chunks_urls.map( From a0b5be5dbf4714dd730739e8f95468978f629404 Mon Sep 17 00:00:00 2001 From: laemtl Date: Wed, 23 Nov 2022 18:20:43 +0000 Subject: [PATCH 6/7] Integration test fix --- .../php/models/electrophysioannotations.class.inc | 2 +- .../test/electrophysiologyBrowserTest.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/modules/electrophysiology_browser/php/models/electrophysioannotations.class.inc b/modules/electrophysiology_browser/php/models/electrophysioannotations.class.inc index 551fa1a6616..c405687aafe 100644 --- a/modules/electrophysiology_browser/php/models/electrophysioannotations.class.inc +++ b/modules/electrophysiology_browser/php/models/electrophysioannotations.class.inc @@ -48,7 +48,7 @@ class ElectrophysioAnnotations $annotationLabels = $db->pselect( 'SELECT * FROM physiological_annotation_label', - ['PFID' => $this->_physioFileID] + [] ); $this->_data = [ diff --git a/modules/electrophysiology_browser/test/electrophysiologyBrowserTest.php b/modules/electrophysiology_browser/test/electrophysiologyBrowserTest.php index 6c7364443d1..07a3c64a9a9 100644 --- a/modules/electrophysiology_browser/test/electrophysiologyBrowserTest.php +++ b/modules/electrophysiology_browser/test/electrophysiologyBrowserTest.php @@ -120,6 +120,8 @@ function setUp(): void [ 'SessionID' => '999999', 'PhysiologicalOutputTypeID' => 22, + 'InsertedByUser' => 'Unit Tester', + 'FilePath' => '/path/to/test/file', 'FileType' => 'testType' ] ); @@ -128,6 +130,8 @@ function setUp(): void [ 'SessionID' => '999997', 'PhysiologicalOutputTypeID' => 23, + 'InsertedByUser' => 'Unit Tester', + 'FilePath' => '/path/to/test/file2', 'FileType' => 'testType2' ] ); From 8ae83fbd5d142575a757f91aeafc4195bc7eb7d0 Mon Sep 17 00:00:00 2001 From: Laetitia Fesselier Date: Thu, 24 Nov 2022 13:41:25 -0500 Subject: [PATCH 7/7] Extra spaces removal --- .../src/eeglab/EEGLabSeriesProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/eeglab/EEGLabSeriesProvider.tsx b/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/eeglab/EEGLabSeriesProvider.tsx index f9a4671dd6f..e3ba64388b2 100644 --- a/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/eeglab/EEGLabSeriesProvider.tsx +++ b/modules/electrophysiology_browser/jsx/react-series-data-viewer/src/eeglab/EEGLabSeriesProvider.tsx @@ -115,7 +115,7 @@ class EEGLabSeriesProvider extends Component { || text.json instanceof String)) return; return tsvParse( text.json.replace('trial_type', 'label')) - .map(({ onset, duration, label }, i) => ({ + .map(({onset, duration, label}, i) => ({ onset: parseFloat(onset), duration: parseFloat(duration), type: 'Event',