Skip to content

Commit f427144

Browse files
authored
[EEG Browser] Annotations: Add new and HED tags (#8236)
This fills in some gaps in the code relating to EEG annotations. It connects the front-end architecture from #7433 to the annotation form that was added in #7387. The result is that a user can now add new annotations from the EEG Browser. Based on @jesscall's work in PR #7829
1 parent 64926ed commit f427144

File tree

17 files changed

+1424
-348
lines changed

17 files changed

+1424
-348
lines changed

modules/electrophysiology_browser/css/electrophysiology_browser.css

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,43 @@ svg {
4242
user-select: none;
4343
}
4444

45-
.annotation.list-group-item {
45+
.list-group-item {
46+
position: relative;
47+
display: flex;
48+
flex-direction: row;
49+
justify-content: space-between;
50+
align-items: center;
51+
}
52+
53+
.annotation {
4654
background: #fffae6;
4755
border-left: 5px solid #ff6600;
4856
}
4957

58+
.epoch-details {
59+
padding-right: 100px;
60+
}
61+
62+
.epoch-action {
63+
display: flex;
64+
flex-direction: row;
65+
justify-content: center;
66+
align-items: center;
67+
position: absolute;
68+
right: 0;
69+
}
70+
71+
.epoch-tag {
72+
padding: 5px;
73+
background: #e7e4e4;
74+
border-left: 5px solid #797878;
75+
}
76+
77+
.epoch-tag p {
78+
word-wrap: break-word;
79+
width: 95%;
80+
}
81+
5082
.event-list .btn.btn-primary {
5183
color: #555;
5284
border: 1px solid #555;

modules/electrophysiology_browser/jsx/components/DownloadPanel.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class DownloadPanel extends Component {
9191
>Not Available</a>
9292
: <a
9393
className='btn btn-primary download col-xs-6'
94-
href={this.state.outputType == 'derivative' &&
94+
href={
9595
(download.type ==
9696
'physiological_annotation_files' ||
9797
download.type == 'all_files') ?

modules/electrophysiology_browser/jsx/electrophysiologySessionView.js

Lines changed: 149 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ class ElectrophysiologySessionView extends Component {
145145
chunksURL: null,
146146
epochsURL: null,
147147
electrodesURL: null,
148+
events: null,
149+
annotations: null,
148150
splitData: null,
149151
},
150152
],
@@ -192,10 +194,10 @@ class ElectrophysiologySessionView extends Component {
192194
}
193195
return resp.json();
194196
})
195-
.then((data) => {
197+
.then((data) => {
196198
const database = data.database.map((dbEntry) => ({
197199
...dbEntry,
198-
// EEG Visualization parameters
200+
// EEG Visualization urls
199201
chunksURLs:
200202
dbEntry
201203
&& dbEntry.file.chunks_urls.map(
@@ -218,7 +220,10 @@ class ElectrophysiologySessionView extends Component {
218220
&& loris.BaseURL
219221
+ '/electrophysiology_browser/file_reader/?file='
220222
+ group.links[1].file
221-
),
223+
),
224+
events:
225+
dbEntry
226+
&& dbEntry.file.events,
222227
annotations:
223228
dbEntry
224229
&& dbEntry.file.annotations,
@@ -305,13 +310,13 @@ class ElectrophysiologySessionView extends Component {
305310
render() {
306311
if (!this.state.isLoaded) {
307312
return (
308-
<button className='btn-info has-spinner'>
313+
<button className='btn-info has-spinner'>
309314
Loading
310315
<span
311-
className='glyphicon glyphicon-refresh glyphicon-refresh-animate'>
316+
className='glyphicon glyphicon-refresh glyphicon-refresh-animate'>
312317
</span>
313-
</button>
314-
);
318+
</button>
319+
);
315320
}
316321

317322
if (this.state.isLoaded) {
@@ -320,153 +325,158 @@ class ElectrophysiologySessionView extends Component {
320325
const {
321326
chunksURLs,
322327
epochsURL,
323-
electrodesURL,
328+
events,
324329
annotations,
330+
electrodesURL,
325331
} = this.state.database[i];
326332
const file = this.state.database[i].file;
327333
const splitPagination = [];
328334
for (const j of Array(file.splitData?.splitCount).keys()) {
329335
splitPagination.push(
330-
<a
331-
key={j}
332-
className={
333-
'btn btn-xs btn-primary split-nav'
334-
+ (file.splitData?.splitIndex === j ? ' active' : '')
335-
}
336-
onClick={() => this.getSplitData(file.id, i, j)}
337-
>{j+1}</a>
338-
);
336+
<a
337+
key={j}
338+
className={
339+
'btn btn-xs btn-primary split-nav'
340+
+ (file.splitData?.splitIndex === j ? ' active' : '')
341+
}
342+
onClick={() => this.getSplitData(file.id, i, j)}
343+
>{j+1}</a>
344+
);
339345
}
340346
database.push(
341-
<div key={i}>
347+
<div key={i}>
342348
<FilePanel
343-
id={'filename_panel_' + i}
344-
title={this.state.database[i].file.name}
345-
data={this.state.database[i].file.details}
349+
id={'filename_panel_' + i}
350+
title={this.state.database[i].file.name}
351+
data={this.state.database[i].file.details}
346352
>
347-
<div className="react-series-data-viewer-scoped col-xs-12">
348-
<EEGLabSeriesProvider
349-
chunksURL={
350-
chunksURLs?.[file.splitData?.splitIndex] || chunksURLs
351-
}
352-
epochsURL={epochsURL}
353-
electrodesURL={electrodesURL}
353+
<div className="react-series-data-viewer-scoped col-xs-12">
354+
<EEGLabSeriesProvider
355+
chunksURL={
356+
chunksURLs?.[file.splitData?.splitIndex] || chunksURLs
357+
}
358+
epochsURL={epochsURL}
359+
events={events}
354360
annotations={annotations}
355-
>
356-
<Panel
357-
id='channel-viewer'
358-
title={
359-
'Signal Viewer' + (file.splitData
360-
? ' [split '+(file.splitData?.splitIndex+1)+']'
361-
: ''
362-
)
363-
}
364-
>
365-
{file.splitData &&
366-
<>
367-
<span
368-
style={{
369-
color: '#064785',
370-
fontWeight: 'bold',
371-
fontSize: '14px',
372-
paddingRight: '15px',
373-
}}
374-
>
375-
Viewing signal split file:
376-
</span>
377-
<a
378-
className={
379-
'btn btn-xs btn-default split-nav'
380-
+ (file.splitData.splitIndex === 0
381-
? ' disabled'
382-
: '')
383-
}
384-
onClick={() => this.getSplitData(
385-
file.id,
386-
i,
387-
file.splitData.splitIndex-1
388-
)}
389-
>
390-
{'<'}
391-
</a>
392-
{splitPagination}
393-
<a
394-
className={
395-
'btn btn-xs btn-default split-nav'
396-
+ (file.splitData.splitIndex
397-
=== (file.splitData.splitCount-1)
398-
? ' disabled'
399-
: '')
400-
}
401-
onClick={
402-
() => this.getSplitData(
403-
file.id,
404-
i,
405-
file.splitData.splitIndex+1
406-
)
407-
}
408-
>
409-
{'>'}
410-
</a>
411-
</>
412-
}
413-
<SeriesRenderer />
414-
</Panel>
415-
<div className='row'>
416-
<div className='col-md-6 col-lg-4'>
417-
<SummaryPanel
418-
id={'filename_summary_' + i}
419-
data={this.state.database[i].file.summary}
420-
/>
421-
</div>
422-
<EEGMontage />
423-
<div className='col-md-6 col-lg-4'>
424-
<DownloadPanel
425-
id={'file_download_' + i}
426-
downloads={this.state.database[i].file.downloads}
427-
physioFileID={this.state.database[i].file.id}
428-
outputType={this.state.database[i].file.output_type}
429-
/>
430-
</div>
431-
</div>
432-
</EEGLabSeriesProvider>
433-
</div>
434-
</FilePanel>
435-
</div>
436-
);
361+
electrodesURL={electrodesURL}
362+
>
363+
<Panel
364+
id='channel-viewer'
365+
title={
366+
'Signal Viewer' + (file.splitData
367+
? ' [split '+(file.splitData?.splitIndex+1)+']'
368+
: ''
369+
)
370+
}
371+
>
372+
{file.splitData &&
373+
<>
374+
<span
375+
style={{
376+
color: '#064785',
377+
fontWeight: 'bold',
378+
fontSize: '14px',
379+
paddingRight: '15px',
380+
}}
381+
>
382+
Viewing signal split file:
383+
</span>
384+
<a
385+
className={
386+
'btn btn-xs btn-default split-nav'
387+
+ (file.splitData.splitIndex === 0
388+
? ' disabled'
389+
: '')
390+
}
391+
onClick={() => this.getSplitData(
392+
file.id,
393+
i,
394+
file.splitData.splitIndex-1
395+
)}
396+
>
397+
{'<'}
398+
</a>
399+
{splitPagination}
400+
<a
401+
className={
402+
'btn btn-xs btn-default split-nav'
403+
+ (file.splitData.splitIndex
404+
=== (file.splitData.splitCount-1)
405+
? ' disabled'
406+
: '')
407+
}
408+
onClick={
409+
() => this.getSplitData(
410+
file.id,
411+
i,
412+
file.splitData.splitIndex+1
413+
)
414+
}
415+
>
416+
{'>'}
417+
</a>
418+
</>
419+
}
420+
<SeriesRenderer
421+
physioFileID={this.state.database[i].file.id}
422+
annotationMetadata={annotations}
423+
/>
424+
</Panel>
425+
<div className='row'>
426+
<div className='col-md-6 col-lg-4'>
427+
<SummaryPanel
428+
id={'filename_summary_' + i}
429+
data={this.state.database[i].file.summary}
430+
/>
431+
</div>
432+
<EEGMontage />
433+
<div className='col-md-6 col-lg-4'>
434+
<DownloadPanel
435+
id={'file_download_' + i}
436+
downloads={this.state.database[i].file.downloads}
437+
physioFileID={this.state.database[i].file.id}
438+
outputType={this.state.database[i].file.output_type}
439+
/>
440+
</div>
441+
</div>
442+
</EEGLabSeriesProvider>
443+
</div>
444+
</FilePanel>
445+
</div>
446+
);
437447
}
438448

439449
return (
440-
<div id='lorisworkspace'>
450+
<div id='lorisworkspace'>
441451
<StaticDataTable
442-
Headers={[
443-
'PSCID',
444-
'DCCID',
445-
'Visit Label',
446-
'Site',
447-
'DOB',
448-
'Sex',
449-
'Output Type',
450-
'Cohort',
451-
]}
452-
Data={[
453-
[
454-
this.state.patient.info.pscid,
455-
this.state.patient.info.dccid,
456-
this.state.patient.info.visit_label,
457-
this.state.patient.info.site,
458-
this.state.patient.info.dob,
459-
this.state.patient.info.sex,
460-
this.state.patient.info.output_type,
461-
this.state.patient.info.cohort,
462-
],
463-
]}
464-
freezeColumn='PSCID'
465-
Hide={{rowsPerPage: true, downloadCSV: true, defaultColumn: true}}
466-
/>
467-
{database}
468-
</div>
469-
);
452+
Headers={[
453+
'PSCID',
454+
'DCCID',
455+
'Visit Label',
456+
'Site',
457+
'DOB',
458+
'Sex',
459+
'Output Type',
460+
'Cohort',
461+
]}
462+
Data={[
463+
[
464+
this.state.patient.info.pscid,
465+
this.state.patient.info.dccid,
466+
this.state.patient.info.visit_label,
467+
this.state.patient.info.site,
468+
this.state.patient.info.dob,
469+
this.state.patient.info.sex,
470+
this.state.patient.info.output_type,
471+
this.state.patient.info.cohort,
472+
],
473+
]}
474+
freezeColumn='PSCID'
475+
Hide={{rowsPerPage: true, downloadCSV: true, defaultColumn: true}}
476+
/>
477+
{database}
478+
</div>
479+
);
470480
}
471481
}
472482
}

0 commit comments

Comments
 (0)