Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion api/controllers/datalad.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ router.post('/import/:dataset_id', common.jwt(), (req, res, next)=>{
if(project.members.includes(req.user.sub)) canedit = true;
if(!canedit) return next("you can't import to this project");

if(dataset.phenotypes) {
console.log("importing phenotype_files-----------------------------------------------------");
project.phenotypes = dataset.phenotypes;
}

//update participants info
let participants = new db.Participants({
project,
Expand All @@ -82,7 +87,7 @@ router.post('/import/:dataset_id', common.jwt(), (req, res, next)=>{
subjects: dataset.participants,
columns: dataset.participants_info, //might be missing
});
common.publish("participant.create."+req.user.sub+"."+project._id, participants); //too much data?
// common.publish("participant.create."+req.user.sub+"."+project._id, participants); //too much data?
participants.save();

db.DLDatasets.updateOne({_id: dataset._id}, {$inc: {import_count: 1} }).then(err=>{
Expand Down
25 changes: 24 additions & 1 deletion api/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ var projectSchema = mongoose.Schema({

avatar: String, //url for avatar

phenotypes: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Phenotype'
}],

//access control
//* private - only the project member can access
//* public - accessible by anyone
Expand Down Expand Up @@ -805,6 +810,20 @@ ruleSchema.pre('save', function(next) {
});
exports.Rules = mongoose.model('Rules', ruleSchema);

const phenotypeSchema = mongoose.Schema({
name: String,
file: String,
sidecar: String,
columns: Object,
data: Array,
dldataset: {
type: mongoose.Schema.Types.ObjectId,
ref: 'DLDataset'
}
});

exports.Phenotype = mongoose.model('Phenotype', phenotypeSchema);

//////////////////////////////////////////////////////////////
//
// datalad collections
Expand Down Expand Up @@ -840,6 +859,11 @@ var dlDatasetSchema = mongoose.Schema({
],
participants_info: mongoose.Schema.Types.Mixed, //metadata for participants info

phenotypes: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Phenotype'
}],

stats: {
subjects: Number,
sessions: Number,
Expand Down Expand Up @@ -881,4 +905,3 @@ var commentSchema = mongoose.Schema({
});

exports.Comments = mongoose.model('Comments', commentSchema);

39 changes: 33 additions & 6 deletions bin/importdatalad.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ const child_process = require('child_process');
const cli = require('brainlife');
const axios = require('axios');

process.chdir('/mnt/datalad');

if(config.dataladDirectory) process.chdir(config.dataladDirectory);
else {
console.error("config.dataladDirectory is not set");
process.exit(1);
}
console.log("connecting");

db.init(async err=>{
if(err) throw err;
await load_datatypes();
Expand All @@ -28,8 +32,8 @@ db.init(async err=>{
*/

console.log("loading dataset_description.json");
//let datasets = child_process.execSync("find ./ -name dataset_description.json", {encoding: "utf8"}).split("\n").filter(dataset=>{
const datasets = fs.readFileSync(process.argv[2], "utf8").split("\n").filter(dataset=>{
let datasets = child_process.execSync("find ./ -name dataset_description.json", {encoding: "utf8"}).split("\n").filter(dataset=>{
// const datasets = fs.readFileSync(process.argv[2], "utf8").split("\n").filter(dataset=>{
//ignore some datasets
if(dataset.startsWith("datasets.datalad.org/openneuro")) return false;
if(dataset.startsWith("datasets.datalad.org/openfmri")) return false;
Expand Down Expand Up @@ -108,7 +112,7 @@ async function load_datatypes() {
function handle_bids(key, bids, cb) {

//upsert dl-dataset record
db.DLDatasets.findOne(key, (err, dldataset)=>{
db.DLDatasets.findOne(key, async (err, dldataset)=>{
if(err) return cb(err);
if(!bids.dataset_description) return cb();

Expand All @@ -123,7 +127,31 @@ function handle_bids(key, bids, cb) {
if(bids.dataset_description) dldataset.dataset_description = bids.dataset_description;
if(bids.participants) dldataset.participants = bids.participants;
if(bids.participants_json) dldataset.participants_info = bids.participants_json;
if(bids.phenotypes) {
let phenotypeIds = [];
for (let phenotypeData of bids.phenotypes) {
// create a new Phenotype object with the current phenotype data
const phenotype = new db.Phenotype({
name: phenotypeData.name,
file: phenotypeData.file,
sidecar: phenotypeData.sidecar,
columns: phenotypeData.columns,
data: phenotypeData.data,
dldataset: dldataset._id
});

// console.log(phenotype.data);
// process.exit(1);

// save the Phenotype object
const savedPhenotype = await phenotype.save();
phenotypeIds.push(savedPhenotype._id);

}
dldataset.phenotypes = phenotypeIds;
}

console.log("phenotypes added");
//count
let unique_subjects = [];
let unique_sessions = [];
Expand Down Expand Up @@ -154,7 +182,6 @@ function handle_bids(key, bids, cb) {

dldataset.save(err=>{
if(err) throw err;

//handle each items
async.eachSeries(bids.datasets, (item, next_dataset)=>{
item.dataset.datatype = datatype_ids[item.dataset.datatype];
Expand Down
62 changes: 57 additions & 5 deletions ui/src/project.vue
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,15 @@
</template>
</b-tab>

<b-tab>
<template v-slot:title>
<b-badge v-if="!project.publishParticipantsInfo"
variant="secondary" title="May contains sensitive information. Please do not share!"><icon name="lock" scale="0.8"/></b-badge>
Phenotypes
<small v-if="project.phenotypes">{{ project.phenotypes.length }}</small>
</template>
</b-tab>

<b-tab>
<template v-slot:title>
App/Resource Usage
Expand All @@ -274,6 +283,7 @@
<small v-if="project.stats.comments">{{project.stats.comments}}</small>
</template>
</b-tab>

</b-tabs>

<!--readme-->
Expand All @@ -295,9 +305,19 @@
style="overflow: auto; max-height: 500px;"/>

</div>
<!--phenotypes-->
<div v-if="detailTab == 2">
<b-list-group v-for="file in filteredPhenotypes">

<b-list-group-item class="d-flex justify-content-between align-items-center" href="#" >{{ file.tsv }} </b-list-group-item>
<b-list-group-item class="d-flex justify-content-between align-items-center" variant="info" href="#" >{{ file.json }}
<b-button size="sm" variant="outline-primary" @click="showJson(file.jsonContent)"><icon name="eye" scale="1.25"/></b-button>
</b-list-group-item>
</b-list-group>
</div>

<!--app info-->
<div v-if="detailTab == 2">
<div v-if="detailTab == 3">

<div v-if="project.stats.apps && project.stats.apps.length > 0">
<span class="form-header">App Usage</span>
Expand Down Expand Up @@ -348,7 +368,7 @@
</div>

<!--related papers-->
<div v-if="detailTab == 3">
<div v-if="detailTab == 4">
<div v-if="project.relatedPapers && project.relatedPapers.length > 0">
<p>
<small>We found the following journals/articles related to this project based on name/description</small>
Expand All @@ -357,7 +377,7 @@
</div>
</div>

<div v-if="detailTab == 4">
<div v-if="detailTab == 5">
<b-alert show variant="secondary" v-if="!config.user"> Please login to Comments.</b-alert>
<div v-else-if="comments && comments.length">
<div v-for="comment in comments" :key="comment._id" class="commentbox">
Expand Down Expand Up @@ -389,6 +409,7 @@
</div>
<br>
</div>

</div><!-- main content-->
</div><!--project header-->
<div v-if="config.debug">
Expand Down Expand Up @@ -437,13 +458,19 @@

<newtask-modal/>
<datatypeselecter-modal/>

<b-modal id="jsonData">
<editor v-model="json" @init="editorInit" lang="json"
height="500"/>
</b-modal>
</div>
</div>
</template>

<script>

import Vue from 'vue'
const lib = require('@/lib')
import Router from 'vue-router'
import VueMarkdown from 'vue-markdown'
import pageheader from '@/components/pageheader'
Expand Down Expand Up @@ -515,6 +542,7 @@ export default {
stateprogress,
citation,
emojimart: Picker,
editor : require('vue2-ace-editor'),
},

data() {
Expand Down Expand Up @@ -558,7 +586,8 @@ export default {
customToolbar: [
["bold", "italic", "underline"],
[{ list: "ordered" }, { list: "bullet" }],
]
],
json: null,

}
},
Expand Down Expand Up @@ -600,6 +629,19 @@ export default {
sortedPapers : function() {
return this.project.relatedPapers.sort((a,b)=> b.citationCount - a.citationCount );
},
filteredPhenotypes: function() {
let filtered = [];
this.project.phenotypes.forEach(phenotype => {
filtered.push(
{
tsv : phenotype.file.replace("phenotype/", ""),
json : phenotype.sidecar.replace("phenotype/", ""),
jsonContent: phenotype.columns
}
);
});
return filtered;
},
},

mounted() {
Expand All @@ -618,6 +660,11 @@ export default {
this.comment += emoji.native;
this.showMart = false;
},
editorInit(editor) {
lib.editorInit(editor, ()=>{
//nothing to add..
});
},
toggleEmojiMart() {
if(this.showMart) this.showMart = false;
else this.showMart = true;
Expand Down Expand Up @@ -737,7 +784,7 @@ export default {
find: JSON.stringify({
_id: projectId,
}),
populate: "stats.apps.app",
populate: "stats.apps.app phenotypes",
}}).then(res=>{
if(res.data.projects.length == 0) {
this.error = "You don't have access to the project, or the project ID is invalid. Please contact the project owner and ask to add you to the member/guest of the project.";
Expand Down Expand Up @@ -929,6 +976,11 @@ export default {
console.dir(res);
});
},

showJson(content) {
this.json = JSON.stringify(content, null, 4);
this.$bvModal.show('jsonData');
},
},
}
</script>
Expand Down