Commit 392eebdd authored by r03ert0's avatar r03ert0

Revert "Merge branch 'OpenNeuroLab/master'"

This reverts commit 4e3ba6d7, reversing
changes made to 5b5deb36.
parent aa252076
machine:
node:
version: 6.3.1
hosts:
localhost: 127.0.0.1
jobs:
build:
docker:
- image: circleci/node:6.10.3
- image: circleci/mongo:3.4.4
steps:
- checkout
- run: npm install
- run:
name: Instantiate github-keys.json
command: 'echo "{ \"clientID\": \"$GITHUB_CLIENT_ID\", \"clientSecret\": \"$GITHUB_CLIENT_SECRET\", \"callbackURL\": \"$GITHUB_CALLBACK_URL\"}">github-keys.json'
- run:
name: Instantiate blacklist
command: 'mv blacklist.json.example blacklist.json'
- run:
name: Instantiate whitelist
command: 'echo "{}" > whitelist.json'
- run:
name: Run server in background
command: 'npm start'
background: true
- run: sleep 5
......@@ -19,9 +19,6 @@ js/sample-001.nii.gz
js/sample-002.mgz
js/sample-002.nii.gz
public/.DS_Store
public/doc2/*
public/nihpd-plane/*
.DS_Store
package-lock.json
js/.DS_Store
Come to our [**dolphin brain**](http://brainbox.pasteur.fr/mri?url=http://braincatalogue.org/data/Bottlenose_dolphin/MRI-n4.nii.gz) , (log in with your GitHub account) and select the Cerebrum from the Braincatalogue project and **join our segmentation sprint!**
<img width="769" alt="screen shot 2017-06-01 at 11 08 34" src="https://cloud.githubusercontent.com/assets/6297454/26672835/f7892d80-46ba-11e7-8be8-51adbee9288d.png">
When you have done 1 slice,
* add your name or github handle to our BRAINMAPPERS.md file
* add the slice number where you have been working (currently, 111 & 112 are done, you could continue with 113++)
* add "length:..." and
* "volume:..." from the upper left corner of the BrainBox viewer into the file (just for the fun!! :D)
* and make a pull request!
The best devices for drawing over the brain are tablets with pens. With a computer mouse or trackpad it is a bit more tedious but works very fine as well 😃 Looking forward to seeing you!
Just say hi in the BrainBox chat and we will guide you to the view where we are currently working.
We will work in an axial slice (113++) and erase all the parts of the mask that cover the sulci of the brain. You see the impressively folded structure of the dolphin brain. The sulci, which are the valleys of the folds, appear darker. We erase them from the mask to being able to reconstruct the 3D surface preserving the folding.
**It's fun! Join us! :)** Careful! It's addictive! <3 😄
![gyrus_sulcus](https://cloud.githubusercontent.com/assets/6297454/26672808/de7c347c-46ba-11e7-9f19-01fef1da9295.png)
We are the brain mappers! /
Here, we are segmenting an amazingly folded [**dolphin brain**](http://brainbox.pasteur.fr/mri?url=http://braincatalogue.org/data/Bottlenose_dolphin/MRI-n4.nii.gz). Once you clicked the link, you will find our work in 'Cerebrum' annotation layer from the Braincatalogue project. You can **join our segmentation sprint any time!** You can also choose a different species to work on, if you prefer! Any contributions are featured below.
<img width="769" alt="screen shot 2017-06-01 at 11 08 34" src="https://cloud.githubusercontent.com/assets/6297454/26672835/f7892d80-46ba-11e7-8be8-51adbee9288d.png">
**Our BrainMapper team**
current Volume segmented: **509 491 mm3** (please update! :D)
Name: ** **
GitHub:
Species:
Slice numbers:
Length: mm
Volume: mm3
Name: **katja**
GitHub: katjaq
Species: Bottlenose dolphin
Slice numbers: axial 112
Length: mm
Volume: 509491 mm3
## Hi! Thank you for getting back to us! <3
### Is this a feature request or a bug report?
* Please choose one of the labels on the right side and tag your issue :)
### What is the current behaviour?
* If this is a bug, please explain how to reproduce the problem
* Which tools did you use in which sequence?
* Is the error concerning a text or a volume annotation?
* Which label set has been used for the volume annotation (if applicable)?
* What is the type and resolution of your data? (Can you provide a link to your data?)
* Do not include sensitive information.
* Upload the browser error message if you are familiar with web developer tools.
### What is the expected or desired behaviour?
### Version information (for bug reports)
* **Browser + version**:
* **Your OS and version**:
* Paste the output of these commands:
```
node --version && npm --version
```
<!-- Thank you so much for your contribution to BrainBox! <3 -->
<!-- Please find a short title for your pull request and describe your changes on the following line: -->
---
<!-- Please go through our check list and check the functionalities which might be affected by your code changes. Replace each `[ ]` by `[X]` when the step is complete.-->
- [ ] These changes fix #__ (github issue number if applicable).
- [ ] All BrainBox tools behave as expected:
* **KEYS**
* right and left arrow keys
- [ ] jump to next or previous slice within one brain, respectively
- [ ] update the slider accordingly
- [ ] update the slice number accordingly (upper left corner of the viewer window)
* down and up arrow keys
- [ ] jump to the next or previous brain within one project, respectively
- [ ] update the selected subject in the annotation table
* **TOOL BUTTONS**
* minus
- [ ] jumps to the previous slice within one brain
- [ ] updates the slider accordingly
- [ ] updates the slice number accordingly (upper left corner of the viewer window)
* plus
- [ ] jumps to the next slice within one brain
- [ ] updates the slider accordingly
- [ ] updates the slice number accordingly (upper left corner of the viewer window)
* slider
- [ ] updates slice view and slice number on the fly
* sag / cor / axi buttons
- [ ] switch view between the three orthogonal planes
* show tool
- [ ] when you click and drag in your browser window, this tool displays a cirlce at the position of your mouse click & drag as well as the user name in all browser windows connected to the same brain
* the numbers at the bottom of the tool panel
- [ ] change pencil size and eraser size accordingly
* pencil tool
- [ ] draws a line in the colour displayed in the color field
- [ ] in combination with bucket tool filles a complete area with the chosen colour (be sure to have closed the contour line ;) Otherwise, the undo button will be your friend ;)
- [ ] updates length and volume information (of what has been segmented) in the upper left corner of the viewer
* erase tool
- [ ] erases upon click drag from the annotation
- [ ] in combination with the bucket tool erases the complete area of the color where you click
* fill bucket tool
* in combination with pencil tool
- [ ] fills a complete area with the colour displayed in the colour field
* in combination with erase tool
- [ ] erases the complete area that is filled by the colour of where you click
* colour field
- [ ] displays the currently chosen colour to draw and fill
- [ ] on click opens the set of colours available within the chosen label set where a new colour can be selected upon click
* ruler tool
- [ ] measures the distance between start and end of your defined path
- [ ] points of mouse click appear and stay visible until you hit return key (this functionality is currently broken!) (you can click as many points as you wish to define the path you are interested in)
- [ ] on return key, BrainBox will print the distance into the chat field (the ruler tool seems to be currently broken!!!)
* adjust tool
- [ ] slide opacity of overlaid annotation from 0 to 100%
- [ ] increase or decrease brightness of the underlying MRI data
- [ ] increase or decrease the contrast of the underlying MRI data
* eyedropper tool
- [ ] updates the colour field in the tool panel
- [ ] displays/updates the region name in the upper left corner of the viewer
* undo tool
- [ ] undoes the user's actions in reverse chronological order and currently has the bug that it even undoes actions in slices you are currently not seeing! and there is currently no redo...
* save button
- [ ] saves the annotation of the data set into the data base
- [ ] displays a message that user needs to login in case they are not (CHECK!)
- [ ] display a message `Atlas saved Wed Oct 18 2017 12:49:12 GMT+0200 (CEST)`
<!-- Either or. Please replace `__` with appropriate data: -->
- [ ] I implemented tests for these changes OR
- [ ] These changes do not require tests because _____
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
<!-- Again, many many thanks for your work! \ö/ -->
[![CircleCI](https://circleci.com/gh/OpenNeuroLab/BrainBox/tree/master.svg?style=shield)](https://circleci.com/gh/OpenNeuroLab/BrainBox/tree/master) [![Join the chat at https://gitter.im/OpenNeuroLab/BrainBox](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/OpenNeuroLab/BrainBox?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# BrainBox - An application from the [Open Neuroimaging Laboratory](http://openneu.ro/)
BrainBox is a web application that lets you annotate and segment 3D brain
imaging data in real time, collaboratively. You can try it
BrainBox is a web application that lets you annotate and segment 3D brain
imaging data in real time, collaboratively. You can try it
at http://brainbox.pasteur.fr.
BrainBox is a web application to share, visualise and annotate MRI brain
data collaboratively. BrainBox will provide the means to create a
layer of collaborative annotation over all the available MRI data without
having to rely on a centralised data repository or the necessity of
data collaboratively. BrainBox will provide the means to create a
layer of collaborative annotation over all the available MRI data without
having to rely on a centralised data repository or the necessity of
having to install software.
You can try it at http://brainbox.pasteur.fr. Log in with your github
account and enter the URL to an MRI file you want to visualise, annotate
You can try it at http://brainbox.pasteur.fr. Log in with your github
account and enter the URL to an MRI file you want to visualise, annotate
and edit. You can also click one of the examples.
......@@ -25,9 +23,10 @@ If you want to work on BrainBox's code, you'll need a local installation:
## Using Docker to install and run BrainBox
1. `git clone` this repository or download it
2. `mv BrainBox brainbox` to rename the directory
2. `mv BrainBox brainbox` to rename the directory
3. `cd` to brainbox
4. [create a new OAuth application](https://github.com/settings/applications/new) for your local brainbox url (http://localhost:3000 by default)
4. get Github developer keys for your local brainbox url
(http://localhost:3000 by default)
5. paste the keys into the github-keys.json.example file, change the `callbackURL` to `"http://localhost:3000/auth/github/callback"` and drop the .example
6. drop the `.example` from `blacklist.json.example`
7. drop the `.example` from `whitelist.json.example`
......@@ -40,11 +39,10 @@ If you want to work on BrainBox's code, you'll need a local installation:
1. install and start `mongo` database
2. clone the repo and `cd` to the brainbox directory
3. `mkdir public/data`
4. [create a new OAuth application](https://github.com/settings/applications/new) for your local brainbox url (http://localhost:3000 by default)
4. get Github developer keys for your local brainbox url
(http://localhost:3000 by default)
5. paste the keys into the github-keys.json.example file, and drop the .example
6. drop the `.example` from `blacklist.json.example`
7. drop the `.example` from `whitelist.json.example`
8. `npm install`
9. `npm start`
10. To lint your files use `npm test`, you can use `xo --fix` to fix common mistakes, before committing,
to do that install `xo` globally using `npm i -g xo`
6. `npm install`
7. `npm start`
This diff is collapsed.
#!/usr/bin/env node
const debug = require('debug')('xt');
const app = require('../app');
var debug = require('debug')('xt');
var app = require('../app');
app.set('port', process.env.PORT || 3000);
const server = app.listen(app.get('port'), () => {
debug('Express server listening on port ' + server.address().port);
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
{
"1.2.3.4": true,
"2.3.4.5": true
"1.2.3.4": true,
"2.3.4.5": true
}
const express = require('express');
const multer = require('multer');
const router = express.Router();
var express = require('express');
var controller = require('./mri.controller');
var upload_controller = require('./upload.controller');
const controller = require('./mri.controller');
const uploadController = require('./upload.controller');
var multer = require('multer');
var router = express.Router();
router.get('', controller.validator, controller.mri);
router.get('/json', controller.validator, tokenAuthentication, controller.api_mri_get);
router.post('/json', controller.validator_post, tokenAuthentication, controller.api_mri_post);
router.get('/upload', uploadController.token);
router.get('/upload', upload_controller.token);
router.post('/upload',
multer({dest: './tmp/'}).array('atlas'),
uploadController.validator,
uploadController.other_validations,
uploadController.upload);
multer({ dest: './tmp/'}).array('atlas'),
upload_controller.validator,
upload_controller.other_validations,
upload_controller.upload);
router.get('/reset', controller.reset);
module.exports = router;
module.exports = router;
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
const express = require('express');
const controller = require('./project.controller');
var express = require('express');
var controller = require('./project.controller');
const router = express.Router();
var router = express.Router();
//
router.get('/new', controller.newProject);
router.get('/json', tokenAuthentication, controller.api_projectAll);
router.get('/json/:projectName', controller.validator, tokenAuthentication, controller.api_project);
router.get('/json/:projectName/files', controller.validator, tokenAuthentication, controller.api_projectFiles);
router.get('/json/:projectName', controller.validator , tokenAuthentication, controller.api_project);
router.get('/json/:projectName/files', controller.validator , tokenAuthentication, controller.api_projectFiles);
router.post('/json/:projectName', controller.validator, tokenAuthentication, controller.post_project);
router.delete('/json/:projectName', controller.validator, tokenAuthentication, controller.delete_project);
router.get('/:projectName', controller.validator, controller.project);
router.get('/:projectName/settings', controller.validator, controller.settings);
module.exports = router;
module.exports = router;
\ No newline at end of file
This diff is collapsed.
const express = require('express');
const controller = require('./user.controller');
var express = require('express');
var controller = require('./user.controller');
const router = new express.Router();
var router = express.Router();
router.get('/json', controller.api_userAll);
router.get('/json/:userName', controller.validator, controller.api_user);
router.get('/json/:userName/files', controller.validator, controller.api_userFiles);
router.get('/json/:userName/atlas', controller.validator, controller.api_userAtlas);
router.get('/json/:userName/projects', controller.validator, controller.api_userProjects);
router.get('/:userName', controller.validator, controller.user);
router.get('/json/:userName', controller.validator , controller.api_user);
router.get('/json/:userName/files', controller.validator , controller.api_userFiles);
router.get('/json/:userName/atlas', controller.validator , controller.api_userAtlas);
router.get('/json/:userName/projects', controller.validator , controller.api_userProjects);
router.get('/:userName', controller.validator , controller.user);
module.exports = router;
module.exports = router;
\ No newline at end of file
const async = require('async');
const dateFormat = require('dateformat');
const checkAccess = require('../../js/checkAccess.js');
const dataSlices = require('../../js/dataSlices.js');
var async = require("async");
var dateFormat = require("dateformat");
var checkAccess = require("../../js/checkAccess.js");
var dataSlices = require("../../js/dataSlices.js");
const validator = function (req, res, next) {
// UserName can be an ip address (for anonymous users)
var validator = function(req, res, next) {
// userName can be an ip address (for anonymous users)
/*
req.checkParams('userName', 'incorrect user name').isAlphanumeric();
var errors = req.validationErrors();
console.log(errors);
if (errors) {
res.send(errors).status(403).end();
} else {
return next();
}
*/
next();
}
/*
req.checkParams('userName', 'incorrect user name').isAlphanumeric();
var errors = req.validationErrors();
console.log(errors);
if (errors) {
res.send(errors).status(403).end();
} else {
return next();
}
*/
next();
};
const user = function (req, res) {
const login = (req.isAuthenticated()) ?
('<a href=\'/user/' + req.user.username + '\'>' + req.user.username + '</a> (<a href=\'/logout\'>Log Out</a>)') :
('<a href=\'/auth/github\'>Log in with GitHub</a>');
const requestedUser = req.params.userName;
var user = function(req, res) {
var login = (req.isAuthenticated()) ?
("<a href='/user/" + req.user.username + "'>" + req.user.username + "</a> (<a href='/logout'>Log Out</a>)")
: ("<a href='/auth/github'>Log in with GitHub</a>");
var requestedUser = req.params.userName;
// Store return path in case of login
// store return path in case of login
req.session.returnTo = req.originalUrl;
req.db.get('user').findOne({nickname: requestedUser}, '-_id')
.then(json => {
if (json) {
const context = {
req.db.get('user').findOne({nickname: requestedUser}, "-_id")
.then(function (json) {
if(json) {
var context = {
username: json.name,
nickname: json.nickname,
joined: dateFormat(json.joined, 'dddd d mmm yyyy, HH:MM'),
joined: dateFormat(json.joined, "dddd d mmm yyyy, HH:MM"),
avatar: json.avatarURL,
title: requestedUser,
userInfo: JSON.stringify(json),
tab: req.query.tab || 'mri',
login
tab: req.query.tab||"mri",
login: login
};
res.render('user', context);
res.render('user',context);
} else {
res.status(404).send('User Not Found');
res.status(404).send("User Not Found");
}
})
.catch(err => {
console.log('ERROR:', err);
res.status(400).send('Error');
.catch(function(err) {
console.log("ERROR:",err);
res.status(400).send("Error");
});
};
const api_user = function (req, res) {
req.db.get('user').findOne({nickname: req.params.userName, backup: {$exists: false}}, '-_id')
.then(json => {
var api_user = function(req, res) {
req.db.get('user').findOne({nickname: req.params.userName, backup: {$exists: false}}, "-_id")
.then(function (json) {
if (json) {
if (req.query.var) {
let i,
arr = req.query.var.split('/');
var i, arr = req.query.var.split("/");
for (i in arr) {
json = json[arr[i]];
}
......@@ -70,19 +70,19 @@ const api_user = function (req, res) {
});
};
const api_userAll = function (req, res) {
console.log('api_userAll');
if (!req.query.page) {
res.json({error: 'The \'pages\' parameter has to be specified'});
var api_userAll = function(req, res) {
console.log("api_userAll");
if(!req.query.page) {
res.json({error:"The 'pages' parameter has to be specified"});
return;
}
const page = parseInt(req.query.page);
const nItemsPerPage = 20;
req.db.get('user').find({backup: {$exists: false}}, {skip: page * nItemsPerPage, limit: nItemsPerPage, fields: {_id: 0}})
.then(json => {
res.send(json.map(o => {
var page = parseInt(req.query.page);
var nItemsPerPage = 20;
req.db.get('user').find({backup: {$exists: false}}, {skip: page*nItemsPerPage, limit: nItemsPerPage, fields:{_id:0}})
.then(function (json) {
res.send(json.map(function(o) {
return o.nickname;
}));
});
......@@ -94,19 +94,19 @@ const api_userAll = function (req, res) {
/**
* @todo Check access rights for this route
*/
const api_userFiles = function (req, res) {
const userName = req.params.userName;
const start = parseInt(req.query.start);
const length = parseInt(req.query.length);
console.log('userName:', userName, 'start:', start, 'length:', length);
dataSlices.getUserFilesSlice(req, userName, start, length)
.then(result => {
res.send(result);
var api_userFiles = function(req, res) {
var userName = req.params.userName;
var start = parseInt(req.query.start);
var length = parseInt(req.query.length);
console.log("userName:",userName, "start:",start, "length:",length);
dataSlices.getUserFilesSlice(req,userName, start, length)
.then(function(result) {
res.send(result);
})
.catch(err => {
console.log('ERROR:', err);
res.send({success: false, list: []});
.catch(function(err) {
console.log("ERROR:",err);
res.send({success:false,list:[]});
});
};
/**
......@@ -115,51 +115,51 @@ const api_userFiles = function (req, res) {
/**
* @todo Check access rights for this route
*/
const api_userAtlas = function (req, res) {
const userName = req.params.userName;
const start = parseInt(req.query.start);
const length = parseInt(req.query.length);
console.log('userName:', userName, 'start:', start, 'length:', length);
dataSlices.getUserAtlasSlice(req, userName, start, length)
.then(result => {
res.send(result);
var api_userAtlas = function(req, res) {
var userName = req.params.userName;
var start = parseInt(req.query.start);
var length = parseInt(req.query.length);
console.log("userName:",userName, "start:",start, "length:",length);
dataSlices.getUserAtlasSlice(req,userName, start, length)
.then(function(result) {
res.send(result);
})
.catch(err => {
console.log('ERROR:', err);
res.send({success: false, list: []});
.catch(function(err) {
console.log("ERROR:",err);
res.send({success:false,list:[]});
});
};
}
/**
* @function api_userProjects
*/
/**
* @todo Check access rights for this route
*/
const api_userProjects = function (req, res) {
const userName = req.params.userName;
const start = parseInt(req.query.start);
const length = parseInt(req.query.length);
console.log('userName:', userName, 'start:', start, 'length:', length);
dataSlices.getUserProjectsSlice(req, userName, start, length)
.then(result => {
res.send(result);
var api_userProjects = function(req, res) {
var userName = req.params.userName;
var start = parseInt(req.query.start);
var length = parseInt(req.query.length);
console.log("userName:",userName, "start:",start, "length:",length);
dataSlices.getUserProjectsSlice(req,userName, start, length)
.then(function(result) {
res.send(result);
})
.catch(err => {
console.log('ERROR:', err);
res.send({success: false, list: []});
.catch(function(err) {
console.log("ERROR:",err);
res.send({success:false, list:[]});
});
};
}
const userController = function () {
this.validator = validator;
this.api_user = api_user;
this.api_userAll = api_userAll;
this.api_userFiles = api_userFiles;
this.api_userAtlas = api_userAtlas;
this.api_userProjects = api_userProjects;
this.user = user;
};
var userController = function(){
this.validator = validator;
this.api_user = api_user;
this.api_userAll = api_userAll;
this.api_userFiles = api_userFiles;
this.api_userAtlas = api_userAtlas;
this.api_userProjects = api_userProjects;
this.user = user;
}
module.exports = new userController();
module.exports = new userController();
\ No newline at end of file
{
"clientID": "GET YOURS AT https://github.com/settings/applications/new",
"clientSecret": "GET YOURS AT https://github.com/settings/applications/new",
"callbackURL": "http://brainbox.dev/auth/github/callback"
"clientID": "GET YOURS AT https://github.com/settings/applications/new",
"clientSecret": "GET YOURS AT https://github.com/settings/applications/new",
"callbackURL": "http://brainbox.dev/auth/github/callback"
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -3,8 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"start": "node ./bin/www",
"test": "xo"
"start": "node ./bin/www"
},
"dependencies": {
"async": "^2.0.1",
......@@ -15,7 +14,7 @@
"debug": "~2.0.0",
"dompurify": "^0.8.3",
"express": "~4.9.0",
"express-session": "^1.15.6",
"express-session": "^1.14.0",
"express-validator": "^2.20.8",
"fast-json-patch": "^1.1.1",
"file-type": "^3.8.0",
......@@ -25,7 +24,7 @@
"jsdom": "^9.5.0",
"keypress": "^0.2.1",
"merge": "^1.2.0",
"mongodb": "^2.2.33",
"mongodb": "^2.2.5",
"monk": "^3.1.1",
"morgan": "~1.3.0",
"multer": "^1.2.0",
......@@ -33,23 +32,15 @@
"passport": "^0.3.2",
"passport-github": "^1.1.0",
"passport-local": "^1.0.0",
"request": "^2.83.0",
"request": "^2.74.0",
"serve-favicon": "~2.1.3",
"struct": "0.0.11",
"url": "^0.11.0",
"validator": "^6.0.0",
"webpage": "^0.3.0",
"ws": "^1.1.1"
},
"devDependencies": {
"devDependencies" : {
"connect-livereload": "^0.5.3",
"livereload": "^0.4.0",
"xo": "^0.18.2"
},
"xo": {
"space": 4,