Skip to content

Commit

Permalink
Merge pull request #68 from bhklab/mb-development
Browse files Browse the repository at this point in the history
Added radiomics dataset tab and search functionality, adjusted footer
  • Loading branch information
mattbocc authored Oct 10, 2023
2 parents df00336 + c266ea6 commit 8d6a7f1
Show file tree
Hide file tree
Showing 15 changed files with 407 additions and 4 deletions.
Binary file modified client/public/images/icons/radiomics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/public/images/icons/radiomicset(1).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added client/public/images/icons/radiomicset.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions client/src/components/Footer/Footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const StyledFooter = styled.div`
bottom: 0%;
width: 100%;
background-color: rgb(255,255,255, 0.7);
height: 200px;
height: 220px;
font-size: calc(0.7em + 0.2vw);
padding: 10px 0;
display: flex;
Expand Down Expand Up @@ -77,7 +77,8 @@ const Footer = () => {
<NavLink exact to={`/${dataTypes.xenographic}`} onClick={() => {path.setDatatype(dataTypes.xenographic)}}>Xenographic Pharmacogenomics Data</NavLink>
<NavLink exact to={`/${dataTypes.clinicalgenomics}`} onClick={() => {path.setDatatype(dataTypes.clinicalgenomics)}}>Clinical Genomics Data</NavLink>
<NavLink exact to={`/${dataTypes.icb}`} onClick={() => {path.setDatatype(dataTypes.icb)}}>Immune Checkpoint Blockade Data</NavLink>
<div>Radiogenomics Data (Coming soon)</div>
<NavLink exact to={`/${dataTypes.radiogenomics}`} onClick={() => {path.setDatatype(dataTypes.radiogenomics)}}>Radiogenomics Data</NavLink>
<NavLink exact to={`/${dataTypes.radiomics}`} onClick={() => {path.setDatatype(dataTypes.radiomics)}}>Radiomics Data</NavLink>
</React.Fragment>
:
<React.Fragment>
Expand Down
2 changes: 2 additions & 0 deletions client/src/components/Main/DatasetMain.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ToxicoSetSearch from '../SearchRequest/ToxicoSet/ToxicoSetSearch';
import XevaSetSearch from '../SearchRequest/XevaSet/XevaSetSearch';
import ClinGenSearch from '../SearchRequest/ClinicalGenomics/ClinGenSetSearch';
import RadioSetSearch from '../SearchRequest/RadioSet/RadioSetSearch';
import RadiomicSetSearch from '../SearchRequest/RadiomicSet/RadiomicSetSearch';

const DatasetMain = (props) => {
return(
Expand All @@ -17,6 +18,7 @@ const DatasetMain = (props) => {
{props.match.params.datatype === dataTypes.clinicalgenomics && <ClinGenSearch datasetType={dataTypes.clinicalgenomics} />}
{props.match.params.datatype === dataTypes.radiogenomics && <RadioSetSearch />}
{props.match.params.datatype === dataTypes.icb && <ClinGenSearch datasetType={dataTypes.icb} />}
{props.match.params.datatype === dataTypes.radiomics && <RadiomicSetSearch datasetType={dataTypes.radiomics} />}
</React.Fragment>
);
}
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Main/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ const Main = (props) => {
<DatatypeBox title='Immune Checkpoint Blockade Data' datatype={dataTypes.icb} text='Go' imgWidth='45%'/>
</MainStyle.Row>
<MainStyle.Row>
<DatatypeBox title='Radiomics Data' datatype={dataTypes.radiomics} text='Coming soon' imgWidth='45%' disabled/>
<DatatypeBox title='Radiomics Data' datatype={dataTypes.radiomics} text='Go' imgWidth='45%'/>
</MainStyle.Row>
</MainStyle.Wrapper>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, {useState, useEffect, useContext} from 'react';
import SearchReqContext from '../SearchReqContext';
import axios from 'axios';
import {Filter} from '../SearchReqStyle';
import FilterInputSwitch from '../../Shared/FilterInputSwitch';
import CustomSelect from '../../Shared/CustomSelect';
import {dataTypes} from '../../Shared/Enums';

const RadiomicSetFilter = () => {
const context = useContext(SearchReqContext);

const [datasetSelect, setDatasetSelect] = useState({selected: [], options: [], hidden: false});
const [ready, setReady] = useState(false);

useEffect(() => {
const initialize = async () => {
const res = await axios.get('/api/view/data-object-filter', {params: {datasetType: dataTypes.radiomics}});
setDatasetSelect({...datasetSelect, options: res.data.dataset});
setReady(true);
}
initialize();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return(
<React.Fragment>
{
ready&&
<Filter>
<h2>Radiomic Set Parameters</h2>
<FilterInputSwitch
label='Request Radiomic Set:'
checked={context.isRequest}
tooltip='Currently unavailable'
disabled={true}
/>
<CustomSelect
id='dataset'
hidden={false}
label='Dataset:'
selectOne={context.isRequest}
options={datasetSelect.options}
selected={datasetSelect.selected}
onChange={(e) => {
setDatasetSelect({...datasetSelect, selected: e.value});
context.setParameters(prev => ({...prev, dataset: e.value, search: true}));
}}
/>
</Filter>
}
</React.Fragment>
);
}

export default RadiomicSetFilter;
118 changes: 118 additions & 0 deletions client/src/components/SearchRequest/RadiomicSet/RadiomicSetSearch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React, {useState, useEffect, useContext} from 'react';
import {Messages} from 'primereact/messages';
import { AuthContext } from '../../../hooks/Context';
import useDatasetSearch from '../../../hooks/useDatasetSearch';
import SearchReqContext from '../SearchReqContext';
import SaveDatasetButton from '../../Shared/Buttons/SaveDatasetButton';

import { SearchReqWrapper, MainPanel, SearchReqPanel } from '../SearchReqStyle';
import SearchTableLoader from '../SearchTableLoader';
import SearchSummary from '../SearchSummary';
import RadiomicSetFilter from './RadiomicSetFilter';
import RadiomicSetTable from './RadiomicSetTable';
import {dataTypes} from '../../Shared/Enums';
import StyledPage from '../../../styles/StyledPage';

const RadiomicSetSearch = () => {

const auth = useContext(AuthContext);
const { searchAll, search } = useDatasetSearch(dataTypes.radiomics);

const [datasets, setDatasets] = useState([]);
const [selectedDatasets, setSelectedDatasets] = useState([]);
const [isRequest, setIsRequest] = useState(false);

const [parameters, setParameters] = useState({
dataset: [],
search: false
});

const [ready, setReady] = useState(false);

useEffect(() => {
const initializeView = async () => {
const res = await search({...parameters, status: 'complete', private: false});
console.log(res)
setDatasets(res);
setReady(true);
}
initializeView();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
async function searchRadiomicSet() {
console.log(parameters);
let copy = JSON.parse(JSON.stringify(parameters));
copy.dataset = copy.dataset.map(item => item.name);
const result = await search({...copy, status: 'complete', private: false});
setDatasets(result);
}

if(parameters.search){
searchRadiomicSet();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [parameters]);

const showMessage = (status, data) => {
let severity = status ? 'success' : 'error';
RadiomicSetSearch.messages.show({severity: severity, summary: data.summary, detail: data.message, sticky: true});
setSelectedDatasets([]);
}

return(
<SearchReqContext.Provider
value={{
parameters: parameters,
setParameters: setParameters,
isRequest: isRequest,
setIsRequest: setIsRequest
}}
>
<StyledPage>
<div className='page-title'>ORCESTRA for Radiomics</div>
<SearchReqWrapper>
<RadiomicSetFilter />
<MainPanel>
<Messages ref={(el) => RadiomicSetSearch.messages = el} />
<SearchReqPanel>
<div>
<SearchSummary
title='Explore multimodal Radiomic Datasets (Radiomic Sets)'
searchAll={searchAll}
matchNum={datasets.length}
/>
{
auth.user ?
<SaveDatasetButton
selectedDatasets={selectedDatasets}
disabled={selectedDatasets.length > 0 ? false : true}
onSaveComplete={showMessage}
/>
:
'*Login or register to save existing Radiomic Sets to your profile.'
}
</div>
</SearchReqPanel>
{
ready ?
<RadiomicSetTable
datasets={datasets}
selectedDatasets={selectedDatasets}
updateDatasetSelection={(e) => {setSelectedDatasets(e.value)}}
scrollHeight='600px'
authenticated={auth.user ? true : false}
download={true}
/>
:
<SearchTableLoader />
}
</MainPanel>
</SearchReqWrapper>
</StyledPage>
</SearchReqContext.Provider>
);
}

export default RadiomicSetSearch;
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, {useState, useEffect} from 'react';
import {DataTable} from 'primereact/datatable';
import {Column} from 'primereact/column';
import {dataTypes} from '../../Shared/Enums';
import useDataTable from '../../../hooks/useDataTable';

const RadiomicSetTable = (props) => {

const [state, setState] = useState({
rows: 10,
first: 0,
start: 0,
end: 10,
totalRecords: 0,
loading: true
});

const {
nameColumnTemplate,
downloadTemplate,
canonicalTemplate,
dataTypeTemplate,
} = useDataTable(dataTypes.radiomics);

useEffect(()=>{
setState({...state, loading: false});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return(
<DataTable
value={props.datasets}
selection={props.selectedDatasets}
onSelectionChange={props.updateDatasetSelection}
paginator={props.datasets.length > 10} rows={state.rows}
resizableColumns={true} columnResizeMode="fit"
scrollable={true} scrollHeight={props.scrollHeight }
>
{props.authenticated && <Column selectionMode="multiple" style={{width: '30px', textAlign: 'center'}} />}
<Column className='textField' field='name' header='Name' style={{width:'150px'}} body={nameColumnTemplate} sortable={true} />
<Column className='textField' field='dataset.name' header='Dataset' style={{width:'100px'}} sortable={true} />
<Column field='availableDatatypes' body={dataTypeTemplate} style={{width:'100px'}} header='Image Modality' />
<Column field='canonical' body={canonicalTemplate} style={{width:'90px', textAlign: 'center'}} header='Canonical' />
<Column field='info.numDownload' style={{width:'100px', textAlign: 'center'}} header='Number of Downloads' sortable={true} />
{props.download && <Column field='downloadLink' body={downloadTemplate} style={{width:'60px', textAlign: 'center'}} header='Download' /> }
</DataTable>
);

}

export default RadiomicSetTable;
2 changes: 1 addition & 1 deletion client/src/components/Shared/Enums.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ export const dataTypes = {
xenographic: 'xevaset',
clinicalgenomics: 'clinicalgenomics',
radiogenomics: 'radioset',
radiomics: 'radiomics',
radiomics: 'radiomicset',
icb: 'clinical_icb'
}
31 changes: 31 additions & 0 deletions client/src/components/SingleDataset/RadiomicSet/RadiomicSet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import { TabView,TabPanel } from 'primereact/tabview';
import DisclaimerTabContent from '../PSet/TabContents/DisclaimerTabContent';
import DatasetTabContent from './TabContents/DatasetTabContent';
import SnakemakePipelineTabContent from "../SubComponents/SnakemakePipelineTabContent";
import ReleaseNoteTabContent from './TabContents/ReleaseNoteTabContent';
import { TabContainer } from '../SingleDatasetStyle';

const RadiomicSet = (props) => {
const { dataset } = props;
return(
<React.Fragment>
<TabContainer>
<TabView renderActiveOnly={false}>
{
dataset.tabData.map(td => (
<TabPanel key={Math.random()} header={td.header}>
{td.header === 'Disclaimer' && <DisclaimerTabContent notes={td.data} />}
{td.header === 'Dataset' && <DatasetTabContent metadata={td.data} />}
{td.header === 'Pipeline' && <SnakemakePipelineTabContent data={td.data} />}
{td.header === 'Release Notes' && <ReleaseNoteTabContent data={td.data} />}
</TabPanel>
))
}
</TabView>
</TabContainer>
</React.Fragment>
);
}

export default RadiomicSet;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import { TabHeader, TabContent, TabContentSection} from '../../SingleDatasetStyle';

const DatasetTabContent = (props) => {
const { metadata } = props;
const publication = (
<div>
{metadata.dataset.publications.length ?
metadata.dataset.publications.map((item) =>
<li key={item.link} className='pubList'>
<div className='subContent'>{item.citation}</div>
<br />
<div className='subContent'><a href={item.link}>{item.link}</a></div>
</li>
)
:
<div className="subContent">
Not available.
</div>
}
</div>
);

return(
<React.Fragment>
<TabHeader>Dataset: {metadata.dataset.label}</TabHeader>
<TabContent>
<TabContentSection>
<h3>Imaging Data</h3>
<h4 className='subContent'>{'Source: '}
{
metadata.dataset.sensitivity ?
<a href={metadata.dataset.sensitivity.source}>{metadata.dataset.sensitivity.source}</a>
: 'Not available'
}
</h4>
<h4 className='subContent'>Version: {metadata.dataset.sensitivity.version}</h4>
</TabContentSection>

<TabContentSection>
<h3>Publication: </h3>
<ul>
{publication}
</ul>
</TabContentSection>

<TabContentSection>

</TabContentSection>
</TabContent>
</React.Fragment>
);
}

export default DatasetTabContent;
Loading

0 comments on commit 8d6a7f1

Please sign in to comment.