Skip to content

Commit

Permalink
Merge pull request #837 from neuroscout/oct_small_fixes
Browse files Browse the repository at this point in the history
Various UI improvements + Pybids 0.12.3
  • Loading branch information
adelavega committed Oct 26, 2020
2 parents a846313 + 7adfb03 commit 4948699
Show file tree
Hide file tree
Showing 28 changed files with 208 additions and 89 deletions.
5 changes: 3 additions & 2 deletions celery_worker/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ sklearn
networkx==1.9
celery
hashids==1.2.0
marshmallow==2.19.1
marshmallow==3.7.1
psycopg2==2.8.3
redis
pandas==0.23
Expand All @@ -22,6 +22,7 @@ duecredit==0.6.1
SQLAlchemy==1.3.0
Flask-Caching==1.3.3
flask_jwt
shortuuid==1.0.1
sentry-sdk==0.13.0
pybids==0.10.1
pybids==0.12.3
Werkzeug==0.15.3
1 change: 1 addition & 0 deletions neuroscout/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ RUN npm install -g yarn
COPY requirements.txt /usr/src/app/
COPY optional_requirements.txt /usr/src/app
RUN pip install setuptools==45
RUN pip uninstall -y enum34
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install --no-cache-dir -r optional_requirements.txt
RUN python -m pliers.support.download
Expand Down
4 changes: 3 additions & 1 deletion neuroscout/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@
('UserPredictorListResource', 'user/predictors'),
('UserPredictorCollectionResource', 'user/collections'),
('TaskResource', 'tasks/<int:task_id>'),
('TaskListResource', 'tasks')
('TaskPredictorsResource', 'tasks/<int:task_id>/predictors'),
('TaskListResource', 'tasks'),
('ImageVersionResource', 'image_version')
])


Expand Down
2 changes: 1 addition & 1 deletion neuroscout/frontend/src/AnalysisList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class AnalysisListTable extends React.Component<AnalysisListProps> {
title: 'Name',
render: (text, record: AppAnalysis) => (
<Link to={`/builder/${record.id}`}>
<div className="recordName">{record.name}</div>
<div className="recordName">{record.name ? record.name : 'Untitled'}</div>
</Link>
),
sorter: (a, b) => a.name.localeCompare(b.name)
Expand Down
19 changes: 15 additions & 4 deletions neuroscout/frontend/src/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
Home component for the homepage
*/
import * as React from 'react';
import { Divider, Row, Col, Button, Card, Alert } from 'antd';
import { Divider, Row, Col, Button, Card } from 'antd';
import { MainCol } from './HelperComponents';
import { UserStore } from './user';

const titleStyle: any = {
textAlign: ('center' as React.CSSProperties),
fontSize: '20px',
padding: '0px 0px 0px 0px'
};

class Home extends React.Component<{}, {}> {
class Home extends React.Component<UserStore, {}> {
render() {
return (

Expand All @@ -24,9 +25,19 @@ class Home extends React.Component<{}, {}> {
<div className="splashText">A platform for fast and flexible re-analysis of (naturalistic) fMRI studies</div>
<br/><br/>
<div className="splashButtonParent">
<Button size="large" className="splashButton" type="primary" href="/public">
<Button size="large" className="splashButton" type="default" href="/public">
Browse public analyses
</Button>
</Button> <br/>
{this.props.loggedIn === false &&
<Button
size="large"
className="splashButton"
type="primary"
onClick={e => this.props.update({ openSignup: true })}
>
Sign up to get started!
</Button>
}
</div>
</div>
<br/>
Expand Down
4 changes: 2 additions & 2 deletions neuroscout/frontend/src/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default class Routes extends React.Component<AppState, {}> {
exact={true}
path="/"
render={props =>
<Home />
<Home {...this.props.user} />
}
/>
<Route
Expand Down Expand Up @@ -123,7 +123,7 @@ export default class Routes extends React.Component<AppState, {}> {
<Route
path="/profile/:user_name"
render={props => {
return (<PublicProfile
return (<PublicProfile
user_name={props.match.params.user_name}
datasets={this.props.datasets}
cloneAnalysis={this.props.cloneAnalysis}
Expand Down
23 changes: 10 additions & 13 deletions neuroscout/frontend/src/analysis_builder/Builder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,11 @@ class EditDetails extends React.Component<editDetailsProps, editDetailsState> {
}

init(props: editDetailsProps) {
return {newName: props.name, newDescription: props.description, visible: []};
return {
newName: props.name,
newDescription: props.description,
visible: props.name ? [] : ['1']
};
}

update() {
Expand All @@ -162,11 +166,11 @@ class EditDetails extends React.Component<editDetailsProps, editDetailsState> {

render() {
return (
<div>
<div className="editDetails">
<Collapse bordered={false} activeKey={this.state.visible} onChange={this.onChange}>
<Panel header="Edit Analysis Details" key="1">
<Form layout="vertical">
<FormItem label="Name" required={true}>
<FormItem label="Name">
<Input
placeholder="Name your analysis"
value={this.state.newName}
Expand Down Expand Up @@ -410,11 +414,6 @@ export default class AnalysisBuilder extends React.Component<BuilderProps & Rout
return new Promise(() => {return false; });
}

if (!analysis.name) {
displayError(Error('Analysis cannot be saved without a name'));
return new Promise(() => {return false; });
}

const apiAnalysis: ApiAnalysis = {
name: analysis.name,
description: analysis.description,
Expand Down Expand Up @@ -616,9 +615,6 @@ export default class AnalysisBuilder extends React.Component<BuilderProps & Rout
update[nextTab + 'Active' ] = true;
if (this.state.activeTab === 'overview') {
// need name and runids
if (this.state.analysis.name.length < 1) {
// how
}
if (this.state.analysis.runIds.length < 1) {
}
} else if (!this.preTabChange(nextTab as TabName)) {
Expand Down Expand Up @@ -1133,7 +1129,7 @@ export default class AnalysisBuilder extends React.Component<BuilderProps & Rout
updateSelectedTaskId={this.updateState('selectedTaskId')}
/>
{this.navButtons(
!(!!this.state.analysis.name && this.state.analysis.runIds.length > 0 && selectedTaskId !== null),
!(this.state.analysis.runIds.length > 0 && selectedTaskId !== null),
false
)}
<br/>
Expand Down Expand Up @@ -1284,14 +1280,15 @@ export default class AnalysisBuilder extends React.Component<BuilderProps & Rout
<h2>Finalize and Run</h2>
<StatusTab
status={analysis.status}
name={analysis.name}
analysisId={analysis.analysisId}
confirmSubmission={this.confirmSubmission}
private={analysis.private || false}
updateAnalysis={this.updateAnalysis}
userOwns={this.props.userOwns}
modified_at={analysis.modified_at}
>
{this.props.userOwns && !isDraft &&
{this.props.userOwns &&
<EditDetails
name={analysis.name}
description={analysis.description}
Expand Down
1 change: 0 additions & 1 deletion neuroscout/frontend/src/analysis_builder/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ export class OverviewTab extends React.Component<OverviewTabProps, OverviewTabSt
placeholder="You can change this later"
value={analysis.name}
onChange={this.updateAnalysisFromEvent('name')}
required={true}
min={1}
/>
</Col>
Expand Down
2 changes: 1 addition & 1 deletion neuroscout/frontend/src/analysis_builder/Review.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export class Review extends React.Component<ReviewProps, {}> {

return (
<Card
title={'Overview of ' + (Name ? Name : 'No Name')}
title={'Overview of ' + (Name ? Name : 'Untitled')}
>
Author: <Link to={`/profile/${this.props.user_name}`}> {this.props.user_name} </Link>
<p>{Description ? Description : 'No description.'}</p>
Expand Down
28 changes: 23 additions & 5 deletions neuroscout/frontend/src/analysis_builder/Status.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class PubAccess extends React.Component<PubAccessProps, {}> {
type submitProps = {
status?: string,
analysisId?: string,
name?: string,
modified_at?: string;
confirmSubmission: (build: boolean) => void,
private: boolean,
Expand Down Expand Up @@ -99,6 +100,12 @@ export class Submit extends React.Component<submitProps, {tosAgree: boolean, val
let validateChange = this.validateChange.bind(this);
return(
<div>
{!this.props.name &&
<span>
<br/><Alert message="Analysis needs name to be generated" type="warning" showIcon={true} closable={true} />
</span>
}
<br/>
<h3>Terms for analysis generation:</h3>
<ul>
<li>I agree that once I submit my analysis, I will not be able to delete or edit it.</li>
Expand Down Expand Up @@ -131,7 +138,7 @@ export class Submit extends React.Component<submitProps, {tosAgree: boolean, val
hidden={!this.props.analysisId}
onClick={this.props.confirmSubmission.bind(this, this.state.validate)}
type={'primary'}
disabled={!this.state.tosAgree || !['DRAFT', 'FAILED'].includes(status)}
disabled={!this.state.tosAgree || !['DRAFT', 'FAILED'].includes(status) || !this.props.name}
>
Generate
</Button>
Expand All @@ -142,15 +149,20 @@ export class Submit extends React.Component<submitProps, {tosAgree: boolean, val

type statusTabState = {
compileTraceback: string,
nvUploads?: any
nvUploads?: any,
imageVersion: string
};

export class StatusTab extends React.Component<submitProps, statusTabState> {
constructor(props) {
super(props);
this.state = {
compileTraceback: '',
imageVersion: ''
};
}

componentDidMount() {
if ((this.props.analysisId !== undefined)) {
this.getTraceback(this.props.analysisId);
api.getNVUploads(this.props.analysisId).then(nvUploads => {
Expand All @@ -159,6 +171,11 @@ export class StatusTab extends React.Component<submitProps, statusTabState> {
}
});
}
api.getImageVersion().then((version) => {
if (!!version) {
this.setState({imageVersion: `:${version}`});
}
});
}

getTraceback(id) {
Expand Down Expand Up @@ -260,19 +277,20 @@ export class StatusTab extends React.Component<submitProps, statusTabState> {
<DateTag modified_at={this.props.modified_at} />
<StatusTag status={this.props.status} analysisId={this.props.analysisId} />
</div>
{this.props.children}
{(this.props.status === 'PASSED') &&
<div>
<h3>Analysis Passed</h3>
<p>
{this.props.userOwns && 'Congratulations, your analysis has been compiled!'}
Run the analysis with this this command, replacing '/local/outputdirectory' with a local directory.
See the <a href="https://github.com/neuroscout/neuroscout-cli">neuroscout-cli documentation </a>
See the <a href="https://neuroscout.github.io/neuroscout/cli/">neuroscout-cli documentation </a>
for more information.
</p>
<pre>
<code>
docker run --rm -it -v /local/outputdirectory:/out
neuroscout/neuroscout-cli run /out {this.props.analysisId}
{` neuroscout/neuroscout-cli${this.state.imageVersion}`} run /out {this.props.analysisId}
</code>
</pre>
<Card size="small" title="System Requirements" style={{ width: 400 }}>
Expand All @@ -286,6 +304,7 @@ export class StatusTab extends React.Component<submitProps, statusTabState> {
{(this.props.status === 'DRAFT' || this.props.status === 'FAILED') &&
<Submit
status={this.props.status}
name={this.props.name}
analysisId={this.props.analysisId}
confirmSubmission={this.props.confirmSubmission}
private={this.props.private}
Expand All @@ -308,7 +327,6 @@ export class StatusTab extends React.Component<submitProps, statusTabState> {
</div>
}
{this.state.nvUploads && this.nvStatus(this.state.nvUploads)}
{this.props.children}
</div>
);
}
Expand Down
2 changes: 1 addition & 1 deletion neuroscout/frontend/src/analysis_builder/transforms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const transformDefinitions: Transformation[] = [
Name: 'Scale',
Demean: true,
Rescale: true,
ReplaceNA: 'None' as ReplaceNA
ReplaceNA: 'after' as ReplaceNA
},
{
Name: 'Orthogonalize',
Expand Down
8 changes: 8 additions & 0 deletions neuroscout/frontend/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,5 +236,13 @@ export const api = {
},
getPublicProfile: (user_name: string): Promise<ApiUser & {statusCode: number}> => {
return jwtFetch(`${domainRoot}/api/user/${user_name}`);
},
getImageVersion: (): Promise<string> => {
return jwtFetch(`${domainRoot}/api/image_version`).then((res) => {
if (res.version) {
return res.version;
}
return '';
});
}
};
5 changes: 5 additions & 0 deletions neuroscout/frontend/src/css/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,8 @@ pre {
.profileName {
margin: 0 0 0 10px;
}

.editDetails .ant-collapse-borderless {
background-color: #fff;
border: 0px;
}
2 changes: 1 addition & 1 deletion neuroscout/models/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Analysis(db.Model):
id = db.Column(db.Integer, primary_key=True)
hash_id = db.Column(db.Text, unique=True)

name = db.Column(db.Text, nullable=False)
name = db.Column(db.Text)
description = db.Column(db.Text)
predictions = db.Column(db.Text, default='')
private = db.Column(db.Boolean, default=True)
Expand Down
3 changes: 2 additions & 1 deletion neuroscout/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dataclasses==0.7
decorator==4.0.11
docopt==0.6.2
duecredit==0.6.1
pybids==0.10.1
pybids==0.12.3
pynv==0.2
Flask==1.1.1
flask-apispec==0.10.0
Expand Down Expand Up @@ -66,6 +66,7 @@ sentry-sdk[flask]==0.13
soundfile
pytesseract
SQLAlchemy==1.3.0
shortuuid==1.0.1
tqdm==4.11.2
webargs==6.1.1
Werkzeug==0.15.3
Expand Down
5 changes: 4 additions & 1 deletion neuroscout/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
AnalysisBundleResource, AnalysisFullResource,
AnalysisResourcesResource, ReportResource,
AnalysisFillResource, AnalysisUploadResource,
BibliographyResource)
BibliographyResource, ImageVersionResource)
from .dataset import DatasetResource, DatasetListResource
from .predictor import (PredictorListResource, PredictorResource,
PredictorCollectionCreateResource,
TaskPredictorsResource,
PredictorCollectionResource, prepare_upload,
PredictorEventListResource)
from .run import RunResource, RunListResource
Expand Down Expand Up @@ -51,6 +52,8 @@
'UserPredictorCollectionResource',
'UserListResource',
'TaskResource',
'TaskPredictorsResource',
'TaskListResource',
'ImageVersionResource',
'prepare_upload'
]
6 changes: 4 additions & 2 deletions neuroscout/resources/analysis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from .endpoints import (AnalysisResource, AnalysisRootResource,
AnalysisBundleResource, CloneAnalysisResource,
AnalysisFullResource, AnalysisResourcesResource,
AnalysisFillResource, BibliographyResource)
AnalysisFillResource, BibliographyResource,
ImageVersionResource)
from .reports import (CompileAnalysisResource, ReportResource,
AnalysisUploadResource)

Expand All @@ -18,5 +19,6 @@
'BibliographyResource',
'CloneAnalysisResource',
'CompileAnalysisResource',
'ReportResource'
'ReportResource',
'ImageVersionResource'
]

0 comments on commit 4948699

Please sign in to comment.