Skip to content
This repository was archived by the owner on Dec 27, 2022. It is now read-only.

Commit cc5750c

Browse files
committed
wip/enh/brk: updated dockerfile. added a cli for data. updated the workflow to save outlier indices in report. updated viewer to show outliers on line chart. brk: updated viewer to have brainsprites, but they are kind of broken right now
1 parent b4e589a commit cc5750c

File tree

11 files changed

+82
-62
lines changed

11 files changed

+82
-62
lines changed

Dockerfile-dmriprep

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ FROM dmriprep:dev
22

33
ADD . /dmriprep
44
WORKDIR /dmriprep
5-
RUN /neurodocker/startup.sh python /dmriprep/setup.py install
5+
RUN /neurodocker/startup.sh python setup.py install
6+
WORKDIR /

dmriprep/cli.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import click
66
from . import run
77
from . import io
8+
from .data import get_dataset
89
import os
910

1011

@@ -50,6 +51,13 @@ def main(participant_label, bids_dir, output_dir, analysis_level="participant"):
5051

5152
return 0
5253

54+
@click.command()
55+
@click.argument('output_dir',
56+
)
57+
def data(output_dir):
58+
get_dataset(os.path.abspath(output_dir))
59+
print('done')
60+
5361

5462
if __name__ == "__main__":
5563
sys.exit(main()) # pragma: no cover

dmriprep/qc.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ def createB0_ColorFA_Mask_Sprites(b0_file, colorFA_file, mask_file):
212212

213213
def create_report_json(dwi_corrected_file, eddy_rms, eddy_report,
214214
color_fa_file, anat_mask_file,
215+
outlier_indices,
215216
outpath=op.abspath('./report.json')):
216217

217218
report = {}
@@ -223,6 +224,7 @@ def create_report_json(dwi_corrected_file, eddy_rms, eddy_report,
223224
report['b0'] = b0
224225
report['colorFA'] = colorFA
225226
report['anat_mask'] = mask
227+
report['outlier_volumes'] = outlier_indices.tolist()
226228

227229
with open(eddy_report, 'r') as f:
228230
report['eddy_report'] = f.readlines()

dmriprep/run.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ def drop_outliers_fn(in_file, in_bval, in_bvec, drop_scans):
379379
import nibabel as nib
380380
import numpy as np
381381
import os.path as op
382+
from nipype.utils.filemanip import fname_presuffix
382383

383384
img = nib.load(op.abspath(in_file))
384385
img_data = img.get_fdata()
@@ -387,17 +388,17 @@ def drop_outliers_fn(in_file, in_bval, in_bvec, drop_scans):
387388

388389
root, ext1 = op.splitext(in_file)
389390
root, ext0 = op.splitext(root)
390-
out_file = ''.join([root + "_thinned", ext0, ext1])
391+
out_file = fname_presuffix(in_file, suffix="_thinned", newpath=op.abspath('.')) #''.join([root + "_thinned", ext0, ext1])
391392
nib.save(img_thinned, op.abspath(out_file))
392393

393394
bval = np.loadtxt(in_bval)
394395
bval_thinned = np.delete(bval, drop_scans, axis=0)
395-
out_bval = '_thinned'.join(op.splitext(in_bval))
396+
out_bval = fname_presuffix(in_bval, suffix="_thinned", newpath=op.abspath('.'))
396397
np.savetxt(out_bval, bval_thinned)
397398

398399
bvec = np.loadtxt(in_bvec)
399400
bvec_thinned = np.delete(bvec, drop_scans, axis=1)
400-
out_bvec = '_thinned'.join(op.splitext(in_bvec))
401+
out_bvec = fname_presuffix(in_bvec, suffix="_thinned", newpath=op.abspath('.'))
401402
np.savetxt(out_bvec, bvec_thinned)
402403

403404
return out_file, out_bval, out_bvec
@@ -546,24 +547,25 @@ def get_orig(subjects_dir, sub):
546547
wf.connect(convert1, "out_file", datasink, "dmriprep.anat.@anat")
547548

548549
def reportNodeFunc(dwi_corrected_file, eddy_rms, eddy_report,
549-
color_fa_file, anat_mask_file):
550+
color_fa_file, anat_mask_file, outlier_indices):
550551
from dmriprep.qc import create_report_json
551552

552553
report = create_report_json(dwi_corrected_file, eddy_rms, eddy_report,
553-
color_fa_file, anat_mask_file)
554+
color_fa_file, anat_mask_file, outlier_indices)
554555
return report
555556

556557
reportNode = pe.Node(niu.Function(
557558
input_names=['dwi_corrected_file', 'eddy_rms',
558559
'eddy_report', 'color_fa_file',
559-
'anat_mask_file'],
560+
'anat_mask_file', 'outlier_indices'],
560561
output_names=['report'],
561562
function=reportNodeFunc
562563
), name="reportJSON")
563564

564565
wf.connect(prep, "outputnode.out_file", reportNode, 'dwi_corrected_file')
565566
wf.connect(prep, "fsl_eddy.out_movement_rms", reportNode, 'eddy_rms')
566567
wf.connect(prep, "fsl_eddy.out_outlier_report", reportNode, 'eddy_report')
568+
wf.connect(id_outliers_node, 'drop_scans', reportNode, 'outlier_indices')
567569
wf.connect(threshold2, "binary_file", reportNode, 'anat_mask_file')
568570
wf.connect(get_tensor, "color_fa_file", reportNode, 'color_fa_file')
569571

@@ -574,5 +576,5 @@ def reportNodeFunc(dwi_corrected_file, eddy_rms, eddy_report,
574576
wf.run()
575577

576578
copyfile(bval_file, op.join(
577-
out_dir, "dmriprep", "dwi", op.split(bval_file)[1]
579+
op.abspath(out_dir), "dmriprep", "dwi", op.split(bval_file)[1]
578580
))

dmriprepViewer/package-lock.json

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dmriprepViewer/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"dependencies": {
1717
"axios": "^0.18.0",
1818
"bootstrap-vue": "^2.0.0-rc.11",
19+
"brainsprite.js": "git+https://[email protected]/SIMEXP/brainsprite.js.git",
1920
"d3": "^5.7.0",
2021
"vue": "^2.5.2",
2122
"vue-router": "^3.0.1",

dmriprepViewer/src/App.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<script>
88
import Vue from 'vue';
99
import BootstrapVue from 'bootstrap-vue';
10+
// eslint-disable-next-line
1011
import 'bootstrap/dist/css/bootstrap.css';
1112
import 'bootstrap-vue/dist/bootstrap-vue.css';
1213

dmriprepViewer/src/components/HelloWorld.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
</b-input-group-append>
1818
</b-input-group>
1919

20-
<report v-if="report.b0" :report="report"></report>
20+
<report v-if="report.b0" :reportProp="report"></report>
2121
</b-container>
2222
</template>
2323

@@ -27,6 +27,7 @@ import sprite4d from './Sprite4D';
2727
import lineChart from './LineChart';
2828
import report from './Report';
2929
30+
3031
export default {
3132
name: 'HelloWorld',
3233
components: {

dmriprepViewer/src/components/LineChart.vue

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,17 @@ export default {
153153
.attr('stroke-width', 1.5)
154154
.attr('d', line2);
155155
156+
this.g.selectAll('.outlier')
157+
.data(this.outlier_indices)
158+
.enter()
159+
.append('rect')
160+
.attr('class', 'outlier')
161+
.attr('x', i => self.x(i) - 1.5)
162+
.attr('y', () => self.y(maxY))
163+
.attr('width', '3px')
164+
.attr('height', () => `${self.height}px`)
165+
.attr('fill', 'black');
166+
156167
157168
this.svg.on('mousemove', () => {
158169
// const x0 = self.x.invert(d3.mouse(this)[0]);
@@ -168,7 +179,7 @@ export default {
168179
this.initAx();
169180
this.plotData();
170181
},
171-
props: ['ylabel', 'xlabel', 'data', 'id', 'highlightIdx'],
182+
props: ['ylabel', 'xlabel', 'data', 'id', 'highlightIdx', 'outlier_indices'],
172183
};
173184
</script>
174185

dmriprepViewer/src/components/Report.vue

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
<div style="height: 200px; width: 100%; display: inline-flex;">
3535
<line-chart id="motion_params"
3636
:data="report.eddy_params"
37+
:outlier_indices="report.outlier_volumes"
3738
xlabel="TR"
3839
ylabel="RMS"
3940
:highlightIdx="time"
@@ -44,59 +45,31 @@
4445
<h2 class="mt-3 pt-3">Registration + Brain Mask</h2>
4546
<p class="lead">Brain mask computed on T1w, and mapped to B0</p>
4647

47-
<sprite4d
48-
:key="'bmask'+2"
49-
:M="report.b0.M"
50-
:N="report.b0.N"
51-
:num_slices="report.b0.num_slices"
52-
id="b0_mask"
53-
:pix="report.b0.pix"
54-
:time="spriteSlice"
55-
:img="report.b0.img"
56-
opacity="1"
57-
></sprite4d>
58-
<sprite4d
59-
:key="'anat_mask'+1"
60-
:M="report.anat_mask.M"
61-
:N="report.anat_mask.N"
62-
:num_slices="report.anat_mask.num_slices"
63-
id="anat_mask"
64-
:pix="report.anat_mask.pix"
65-
:time="spriteSlice"
66-
:img="report.anat_mask.img"
67-
:overlayMode="true"
68-
opacity="1"
69-
></sprite4d>
70-
<vue-slider ref="timeSlider"
71-
v-model="spriteSlice" :min="0"
72-
:max="report.b0.num_slices-1"></vue-slider>
48+
<BrainSprite
49+
id="brainMaskSprite"
50+
ref="brainMaskSprite"
51+
:base_dim_x="report.b0.pix"
52+
:base_dim_y="report.b0.pix"
53+
:overlay_dim_x="report.anat_mask.pix"
54+
:overlay_dim_y="report.anat_mask.pix"
55+
:base="report.b0.img"
56+
:overlay="report.anat_mask.img"
57+
/>
7358

7459
<h2 class="mt-3 pt-3">DTI: ColorFA</h2>
7560
<p class="lead">Color FA mapped on B0</p>
7661

77-
<sprite4d
78-
key="bmask1"
79-
:M="report.b0.M"
80-
:N="report.b0.N"
81-
:num_slices="report.b0.num_slices"
82-
id="b0_mask"
83-
:pix="report.b0.pix"
84-
:time="spriteSlice"
85-
:img="report.b0.img"
86-
opacity="1"
87-
></sprite4d>
88-
<sprite4d
89-
key="colorfa_mask"
90-
:M="report.colorFA.M"
91-
:N="report.colorFA.N"
92-
:num_slices="report.colorFA.num_slices"
93-
id="colorfa_mask"
94-
:pix="report.colorFA.pix"
95-
:time="spriteSlice"
96-
:img="report.colorFA.img"
97-
:overlayMode="true"
98-
opacity="0.5"
99-
></sprite4d>
62+
<BrainSprite
63+
id="colorFASprite"
64+
ref="colorFASprite"
65+
:base_dim_x="report.b0.pix"
66+
:base_dim_y="report.b0.pix"
67+
:overlay_dim_x="report.colorFA.pix"
68+
:overlay_dim_y="report.colorFA.pix"
69+
:base="report.b0.img"
70+
:overlay="report.colorFA.img"
71+
/>
72+
10073
</div>
10174
</div>
10275
</template>
@@ -106,18 +79,21 @@ import axios from 'axios';
10679
import vueSlider from 'vue-slider-component';
10780
import sprite4d from './Sprite4D';
10881
import lineChart from './LineChart';
82+
import BrainSprite from './BrainSprite.vue';
10983
11084
export default {
11185
name: 'report',
11286
components: {
11387
sprite4d,
11488
vueSlider,
11589
lineChart,
90+
BrainSprite,
11691
},
11792
data() {
11893
return {
11994
time: 0,
12095
spriteSlice: 0,
96+
report: null,
12197
};
12298
},
12399
methods: {
@@ -139,11 +115,23 @@ export default {
139115
}
140116
},
141117
mounted() {
142-
if (this.report) {
143-
this.spriteSlice = this.get_mid_slice();
118+
if (this.reportProp) {
119+
this.report = this.reportProp;
144120
}
121+
this.$nextTick(() => {
122+
if (this.report) {
123+
this.spriteSlice = this.get_mid_slice();
124+
// this.$refs.brainMaskSprite.initBrainSprite();
125+
// this.$refs.colorFASprite.initBrainSprite();
126+
}
127+
});
145128
},
146129
watch: {
130+
reportProp() {
131+
if (this.reportProp) {
132+
this.report = this.reportProp;
133+
}
134+
},
147135
report() {
148136
if (this.report) {
149137
this.spriteSlice = this.get_mid_slice();
@@ -163,7 +151,7 @@ export default {
163151
},
164152
},
165153
props: {
166-
report: Object,
154+
reportProp: Object,
167155
},
168156
};
169157
</script>

0 commit comments

Comments
 (0)