Commit 92b61f61 authored by Taylor Hanayik's avatar Taylor Hanayik
Browse files

update ui

parent f761c8e7
node_modules node_modules
package-lock.json package-lock.json
dist
\ No newline at end of file
...@@ -5,5 +5,5 @@ example usage: ...@@ -5,5 +5,5 @@ example usage:
``` ```
node index.js /path/to/ct/folder node index.js /path/to/ct/folder
# e.g. node index.js /Volumes/passport/taylor/Nele/Subject_data_Atrophy # e.g. ./dist/nifti-rater /Volumes/passport/taylor/Nele/Subject_data_Atrophy
``` ```
\ No newline at end of file
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# frontend
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@niivue/niivue": "^0.8.1",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vuetify": "^2.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"sass": "~1.32.0",
"sass-loader": "^10.0.0",
"vue-cli-plugin-vuetify": "~2.4.2",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.7.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!-- <link rel="icon" href="<%= BASE_URL %>favicon.ico"> -->
<title>NIFTI-rater</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<v-app>
<v-app-bar app color="" elevation="0">
<div class="d-flex align-center">
<h2>NIFTI-rater</h2>
</div>
<v-spacer></v-spacer>
<!-- <v-btn
text
@click="showSettings=!showSettings"
disabled
>
<v-icon>mdi-cog</v-icon>
</v-btn>
<v-btn
href="https://github.com/niivue"
target="_blank"
text
>
<v-icon>mdi-github</v-icon>
</v-btn> -->
</v-app-bar>
<v-main>
<v-container fluid>
<v-row no-gutters align-content="space-between" justify="space-between">
<image-list v-on:visibilityChange="visibilityChange" :images=volumeList>
</image-list>
<!-- <v-spacer></v-spacer> -->
<v-col cols="12" sm="12" md="9" lg="9" class="my-2">
<div style="width: 100%">
<canvas id="gl" height="480" width="640"> </canvas>
</div>
</v-col>
</v-row>
<v-row>
<v-col class="justify-center">
<v-btn @click="next">next</v-btn>
</v-col>
<v-col cols="12" sm="12" md="9" lg="9" class="my-2">
<v-slider
v-model="rating"
step="1"
min='1'
max='10'
thumb-label
ticks
:tick-labels="tickLabels"
hint="rate the quality of the CSF segmentation represented by the red overlay"
></v-slider>
</v-col>
</v-row>
</v-container>
<settings v-on:close-settings="showSettings=!showSettings" :show=showSettings></settings>
</v-main>
</v-app>
</template>
<script>
import imageList from '@/components/imageList.vue'
import settings from '@/components/settings.vue'
import { Niivue } from "@niivue/niivue";
const nv = new Niivue(); // init a new niivue instance
export default {
name: "App",
components: {
imageList,
settings
},
data: () => ({
showSettings: false,
settings: {
mmPrecision: 2, // how many decimal places to round to
},
rating: 5,
tickLabels:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
vols: [],
nv: nv, // the niivue instance on this page
mm: [0, 0, 0], // array of length 3 for millimeter coordinates.
vox: [0, 0, 0], // array of length 3 for voxel coordinates
// volume list is an array of any length with image objects
// to load.
// volumeList: [
// {
// url: "./mni152.nii.gz",
// volume: { hdr: null, img: null },
// colorMap: "gray",
// opacity: 100,
// visible: true,
// },
// {
// url: "./hippo.nii.gz",
// volume: { hdr: null, img: null },
// colorMap: "winter",
// opacity: 100,
// visible: true,
// },
// ],
}),
watch: {
},
computed: {
volumeList: function() {
return this.vols
}
},
methods: {
visibilityChange: function (index, visible) {
this.nv.setOpacity(index, visible)
// this.volumeList[index].visible = visible
// this.nv.updateGLVolume()
},
next: function () {
fetch('/next')
.then(res => res.json())
.then((data) => {
this.vols = [
{
url: '/image/' + data.base,
volume: {hdr:null, img:null},
colorMap: 'ct_brain',
opacity: 100,
visible:true
},
{
url: '/image/' + data.overlay,
volume: {hdr:null, img:null},
colorMap: "red",
opacity: 80,
visible:true
}
]
// this.nv = new Niivue()
nv.attachTo('gl')
nv.loadVolumes(this.volumeList)
})
}
},
mounted() {
// runs when the vue instance is ready and attached to the #app element
this.nv.attachTo("gl"); // attach the niivue instance to the canvas with id 'gl'
this.nv.loadVolumes(this.volumeList); // load the volume list and render in the canvas
},
};
</script>
<style>
</style>
<template>
<v-row align="center" justify="center">
<v-btn icon @click="toggleVisible">
<v-icon>{{visibleIcon}}</v-icon>
</v-btn>
<v-btn text small class="text-none">
{{ displayName }}
</v-btn>
<v-spacer></v-spacer>
</v-row>
</template>
<script>
export default {
name: 'imageItem',
props: {
image: Object,
index: Number
},
data() {
return {
}
},
computed: {
displayName: function () {
let parts = this.image.url.split('/')
console.log(parts)
let fileNamePart = parts.slice(-1)[0]
console.log(fileNamePart)
return fileNamePart
},
visibleIcon: function () {
return this.image.visible ? 'mdi-eye' : 'mdi-eye-off'
}
},
methods: {
toggleVisible: function() {
this.image.visible = !this.image.visible
this.$emit('visibilityChange', this.index, this.image.visible)
}
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<v-col class="mx-5 my-2">
<image-item v-on:visibilityChange="visibilityChange" v-for="(image, index) in images" :key="index" :image=image :index=index>
</image-item>
</v-col>
</template>
<script>
import imageItem from '@/components/imageItem.vue'
export default {
name: 'imageList',
components: {
imageItem
},
props: {
images: Array
},
data () {
return {
}
},
methods: {
visibilityChange: function(index, visible) {
this.$emit('visibilityChange', index, visible)
}
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<v-row justify="center">
<v-dialog v-on:keydown="$emit('close-settings')" overlay-opacity="0" overlay-color="blue" v-model="show" fullscreen hide-overlay transition="dialog-top-transition">
<v-card>
</v-card>
</v-dialog>
</v-row>
</template>
<script>
export default {
name: 'settings',
props: {
show: Boolean
}
}
</script>
<style>
</style>
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
Vue.config.productionTip = false
new Vue({
vuetify,
render: h => h(App)
}).$mount('#app')
import Vue from 'vue';
import Vuetify from 'vuetify/lib/framework';
Vue.use(Vuetify);
export default new Vuetify({
});
module.exports = {
transpileDependencies: [
'vuetify'
]
}
const express = require('express') const express = require('express')
const open = require('open');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const app = express() const app = express()
...@@ -26,26 +27,40 @@ const getFilesRecursively = (directory) => { ...@@ -26,26 +27,40 @@ const getFilesRecursively = (directory) => {
getFilesRecursively(dir) getFilesRecursively(dir)
fileIdx = -1 fileIdx = -1
//process.exit()
app.use('/', express.static(__dirname)) app.use('/', express.static(path.join(__dirname, './frontend/dist')))
// app.get('/', (req, res) => {
// res.sendFile('index.html', {root: '.'})
// })
app.get('/base/:index', (req, res) => { app.get('/image/:name', (req, res) => {
res.sendFile(files[req.params.index]) console.log(req.params.name)
}) let imageFile = ''
for (let i=0; i<files.length; i++) {
app.get('/overlay/:index', (req, res) => { let fnameBase = files[i]
res.sendFile(files[req.params.index].replace('_CT','_thrbinCSF')) let fnameOverlay = files[i].replace('_CT','_thrbinCSF')
if (fnameBase.indexOf(req.params.name) != -1){
imageFile = fnameBase
} else if (fnameOverlay.indexOf(req.params.name) != -1){
imageFile = fnameOverlay
}
}
res.sendFile(imageFile)
}) })
app.get('/next', (req, res) => { app.get('/next', (req, res) => {
fileIdx = fileIdx+1 fileIdx = fileIdx+1
res.json({index: fileIdx}) let baseFile = files[fileIdx].split('/').splice(-1)
let overlayFile = files[fileIdx].replace('_CT','_thrbinCSF').split('/').splice(-1)
let j = {
base: baseFile ,
overlay: overlayFile
}
console.log(j)
res.json(j)
}) })
app.listen(port, () => { app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`) console.log(`Example app listening at http://localhost:${port}`)
}) })
open(`http://localhost:${port}`);
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -4,12 +4,23 @@ ...@@ -4,12 +4,23 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build":"cd frontend && npm run build && cd .. && npx pkg package.json",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"bin": "./index.js",
"pkg": {
"scripts": "index.js",
"assets": "frontend/dist/**/*",
"targets": [
"node14-macos-x64"
],
"outputPath": "dist"
},
"author": "Taylor Hanayik", "author": "Taylor Hanayik",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"express": "^4.17.1" "express": "^4.17.1",
"open": "^8.2.1"
}, },
"devDependencies": { "devDependencies": {
"pkg": "^5.3.1" "pkg": "^5.3.1"
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment