cloudmr-ux 2.0.7 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -24
- package/dist/CmrComponents/CmrButton/CmrButton.css +0 -0
- package/dist/CmrComponents/CmrButton/CmrButton.d.ts +4 -0
- package/dist/CmrComponents/CmrButton/CmrButton.js +30 -0
- package/dist/CmrComponents/CmrButton/index.d.ts +1 -0
- package/dist/CmrComponents/CmrButton/index.js +1 -0
- package/dist/CmrComponents/CmrCheckbox/CmrCheckbox.css +29 -0
- package/dist/CmrComponents/CmrCheckbox/CmrCheckbox.d.ts +14 -0
- package/dist/CmrComponents/CmrCheckbox/CmrCheckbox.js +30 -0
- package/dist/CmrComponents/CmrCheckbox/index.d.ts +1 -0
- package/dist/CmrComponents/CmrCheckbox/index.js +1 -0
- package/dist/CmrComponents/CmrColorPicker/CmrColorPicker.d.ts +8 -0
- package/dist/CmrComponents/CmrColorPicker/CmrColorPicker.js +29 -0
- package/dist/CmrComponents/CmrColorPicker/CmrColorPicker.scss +27 -0
- package/dist/CmrComponents/CmrInput/CmrInput.css +27 -0
- package/dist/CmrComponents/CmrInput/CmrInput.d.ts +17 -0
- package/dist/CmrComponents/CmrInput/CmrInput.js +29 -0
- package/dist/CmrComponents/CmrInput/index.d.ts +1 -0
- package/dist/CmrComponents/CmrInput/index.js +1 -0
- package/dist/CmrComponents/CmrRadioGroup/CmrRadioGroup.css +25 -0
- package/dist/CmrComponents/CmrRadioGroup/CmrRadioGroup.d.ts +15 -0
- package/dist/CmrComponents/CmrRadioGroup/CmrRadioGroup.js +37 -0
- package/dist/CmrComponents/CmrRadioGroup/index.d.ts +1 -0
- package/dist/CmrComponents/CmrRadioGroup/index.js +1 -0
- package/dist/CmrComponents/CmrSelect/CmrSelect.css +1 -0
- package/dist/CmrComponents/CmrSelect/CmrSelect.d.ts +24 -0
- package/dist/CmrComponents/CmrSelect/CmrSelect.js +46 -0
- package/dist/CmrComponents/CmrSelect/index.d.ts +1 -0
- package/dist/CmrComponents/CmrSelect/index.js +1 -0
- package/dist/CmrComponents/checkbox/Checkbox.css +8 -0
- package/dist/CmrComponents/checkbox/Checkbox.d.ts +15 -0
- package/dist/CmrComponents/checkbox/Checkbox.js +25 -0
- package/dist/CmrComponents/collapse/Collapse.css +3 -0
- package/dist/CmrComponents/collapse/Collapse.d.ts +18 -0
- package/dist/CmrComponents/collapse/Collapse.js +87 -0
- package/dist/CmrComponents/dialogue/Confirmation.d.ts +20 -0
- package/dist/CmrComponents/dialogue/Confirmation.js +36 -0
- package/dist/CmrComponents/dialogue/DeletionDialog.d.ts +4 -0
- package/dist/CmrComponents/dialogue/DeletionDialog.js +39 -0
- package/dist/CmrComponents/dialogue/EditConfirmation.d.ts +13 -0
- package/dist/CmrComponents/dialogue/EditConfirmation.js +45 -0
- package/dist/CmrComponents/double-slider/DualSlider.d.ts +21 -0
- package/dist/CmrComponents/double-slider/DualSlider.js +152 -0
- package/dist/CmrComponents/double-slider/InvertibleDualSlider.d.ts +24 -0
- package/dist/CmrComponents/double-slider/InvertibleDualSlider.js +174 -0
- package/dist/CmrComponents/gui-slider/ControlledSlider.d.ts +9 -0
- package/dist/CmrComponents/gui-slider/ControlledSlider.js +96 -0
- package/dist/CmrComponents/gui-slider/Slider.d.ts +20 -0
- package/dist/CmrComponents/gui-slider/Slider.js +127 -0
- package/dist/CmrComponents/header/Header.d.ts +17 -0
- package/dist/CmrComponents/header/Header.js +90 -0
- package/dist/CmrComponents/header/Header.scss +32 -0
- package/dist/CmrComponents/input-number/InputNumber.css +0 -0
- package/dist/CmrComponents/input-number/InputNumber.d.ts +17 -0
- package/dist/CmrComponents/input-number/InputNumber.js +30 -0
- package/dist/CmrComponents/label/Label.css +13 -0
- package/dist/CmrComponents/label/Label.d.ts +9 -0
- package/dist/CmrComponents/label/Label.js +18 -0
- package/dist/CmrComponents/panel/Panel.css +5 -0
- package/dist/CmrComponents/panel/Panel.d.ts +12 -0
- package/dist/CmrComponents/panel/Panel.js +42 -0
- package/dist/CmrComponents/rename/edit.d.ts +7 -0
- package/dist/CmrComponents/rename/edit.js +117 -0
- package/dist/CmrComponents/select-upload/SelectUpload.css +26 -0
- package/dist/CmrComponents/select-upload/SelectUpload.d.ts +33 -0
- package/dist/CmrComponents/select-upload/SelectUpload.js +90 -0
- package/dist/CmrComponents/tk-dualrange/TKDualRange.d.ts +17 -0
- package/dist/CmrComponents/tk-dualrange/TKDualRange.js +65 -0
- package/dist/CmrComponents/tk-dualrange/tk-dual-range.css +140 -0
- package/dist/CmrComponents/tooltip/Tooltip.css +0 -0
- package/dist/CmrComponents/tooltip/Tooltip.d.ts +18 -0
- package/dist/CmrComponents/tooltip/Tooltip.js +30 -0
- package/dist/CmrComponents/upload/Upload.css +5 -0
- package/dist/CmrComponents/upload/Upload.d.ts +80 -0
- package/dist/CmrComponents/upload/Upload.js +185 -0
- package/dist/CmrComponents/upload/UploadWindow.d.ts +15 -0
- package/dist/CmrComponents/upload/UploadWindow.js +286 -0
- package/dist/CmrTable/CmrTable.css +26 -0
- package/dist/CmrTable/CmrTable.d.ts +13 -0
- package/dist/CmrTable/CmrTable.js +47 -0
- package/dist/CmrTabs/CmrTabs.d.ts +7 -0
- package/dist/CmrTabs/CmrTabs.js +64 -0
- package/dist/CmrTabs/tab.model.d.ts +12 -0
- package/dist/CmrTabs/tab.model.js +1 -0
- package/dist/core/app/main/Main.d.ts +6 -0
- package/dist/core/app/main/Main.js +18 -0
- package/dist/core/app/results/Logs.d.ts +1 -0
- package/dist/core/app/results/Logs.js +33 -0
- package/dist/core/app/results/PreprocessJob.d.ts +1 -0
- package/dist/core/app/results/PreprocessJob.js +100 -0
- package/dist/core/app/results/Results.d.ts +15 -0
- package/dist/core/app/results/Results.js +372 -0
- package/dist/core/app/results/Results.scss +92 -0
- package/dist/core/app/results/Rois.d.ts +11 -0
- package/dist/core/app/results/Rois.js +269 -0
- package/dist/core/app/settings/Settings.d.ts +1 -0
- package/dist/core/app/settings/Settings.js +109 -0
- package/dist/core/app/signin/ForgotPassword.d.ts +3 -0
- package/dist/core/app/signin/ForgotPassword.js +142 -0
- package/dist/core/app/signin/Register.d.ts +3 -0
- package/dist/core/app/signin/Register.js +126 -0
- package/dist/core/app/signin/Signin.d.ts +5 -0
- package/dist/core/app/signin/Signin.js +84 -0
- package/dist/core/app/signin/Signin.scss +86 -0
- package/dist/core/app/upload/Upload.d.ts +3 -0
- package/dist/core/app/upload/Upload.js +261 -0
- package/dist/core/app/upload/Upload.scss +0 -0
- package/dist/core/common/components/CmrColorPicker/CmrColorPicker.d.ts +8 -0
- package/dist/core/common/components/CmrColorPicker/CmrColorPicker.js +29 -0
- package/dist/core/common/components/CmrColorPicker/CmrColorPicker.scss +27 -0
- package/dist/core/common/components/NiivueTools/Niivue.css +8 -0
- package/dist/core/common/components/NiivueTools/Niivue.d.ts +14 -0
- package/dist/core/common/components/NiivueTools/Niivue.js +1270 -0
- package/dist/core/common/components/NiivueTools/NiivuePatcher.js +1875 -0
- package/dist/core/common/components/NiivueTools/components/ColorPicker.d.ts +5 -0
- package/dist/core/common/components/NiivueTools/components/ColorPicker.js +68 -0
- package/dist/core/common/components/NiivueTools/components/DrawPlatte.d.ts +10 -0
- package/dist/core/common/components/NiivueTools/components/DrawPlatte.js +88 -0
- package/dist/core/common/components/NiivueTools/components/DrawToolKit.d.ts +32 -0
- package/dist/core/common/components/NiivueTools/components/DrawToolKit.js +164 -0
- package/dist/core/common/components/NiivueTools/components/EraserPlatte.d.ts +10 -0
- package/dist/core/common/components/NiivueTools/components/EraserPlatte.js +43 -0
- package/dist/core/common/components/NiivueTools/components/Layer.d.ts +10 -0
- package/dist/core/common/components/NiivueTools/components/Layer.js +117 -0
- package/dist/core/common/components/NiivueTools/components/LayersPanel.d.ts +8 -0
- package/dist/core/common/components/NiivueTools/components/LayersPanel.js +108 -0
- package/dist/core/common/components/NiivueTools/components/LocationTable.d.ts +9 -0
- package/dist/core/common/components/NiivueTools/components/LocationTable.js +42 -0
- package/dist/core/common/components/NiivueTools/components/MaskPlatte.d.ts +10 -0
- package/dist/core/common/components/NiivueTools/components/MaskPlatte.js +123 -0
- package/dist/core/common/components/NiivueTools/components/NiivuePanel.d.ts +34 -0
- package/dist/core/common/components/NiivueTools/components/NiivuePanel.js +305 -0
- package/dist/core/common/components/NiivueTools/components/NumberPicker.d.ts +8 -0
- package/dist/core/common/components/NiivueTools/components/NumberPicker.js +40 -0
- package/dist/core/common/components/NiivueTools/components/SettingsPanel.d.ts +7 -0
- package/dist/core/common/components/NiivueTools/components/SettingsPanel.js +30 -0
- package/dist/core/common/components/NiivueTools/components/Switch.d.ts +5 -0
- package/dist/core/common/components/NiivueTools/components/Switch.js +26 -0
- package/dist/core/common/components/NiivueTools/components/Toolbar.d.ts +40 -0
- package/dist/core/common/components/NiivueTools/components/Toolbar.js +184 -0
- package/dist/core/common/components/NiivueTools/components/Toolbar.scss +39 -0
- package/dist/core/common/components/NiivueTools/components/stats.d.ts +2 -0
- package/dist/core/common/components/NiivueTools/components/stats.js +13 -0
- package/dist/core/common/components/NiivueTools/index.css +14 -0
- package/dist/core/common/components/NiivueTools/util.js +309 -0
- package/dist/core/common/components/footer/Footer.d.ts +3 -0
- package/dist/core/common/components/footer/Footer.js +20 -0
- package/dist/core/common/components/footer/Footer.scss +5 -0
- package/dist/core/common/utilities/AuthenticatedRequests.d.ts +16 -0
- package/dist/core/common/utilities/AuthenticatedRequests.js +158 -0
- package/dist/core/common/utilities/CalendarHelper.d.ts +5 -0
- package/dist/core/common/utilities/CalendarHelper.js +27 -0
- package/dist/core/common/utilities/DownloadFromText.d.ts +3 -0
- package/dist/core/common/utilities/DownloadFromText.js +20 -0
- package/dist/core/common/utilities/StoreToRequest.d.ts +1 -0
- package/dist/core/common/utilities/StoreToRequest.js +4 -0
- package/dist/core/common/utilities/SystemUtilities.d.ts +4 -0
- package/dist/core/common/utilities/SystemUtilities.js +79 -0
- package/dist/core/common/utilities/file-transformation/anonymize.d.ts +1 -0
- package/dist/core/common/utilities/file-transformation/anonymize.js +114 -0
- package/dist/core/common/utilities/file-transformation/utilities.d.ts +2 -0
- package/dist/core/common/utilities/file-transformation/utilities.js +23 -0
- package/dist/core/common/utilities/index.d.ts +25 -0
- package/dist/core/common/utilities/index.js +118 -0
- package/dist/core/common/utilities/parse-jwt.d.ts +1 -0
- package/dist/core/common/utilities/parse-jwt.js +14 -0
- package/dist/core/components/PasswordRequirements.d.ts +7 -0
- package/dist/core/components/PasswordRequirements.js +30 -0
- package/dist/core/config/AppConfig.d.ts +5 -0
- package/dist/core/config/AppConfig.js +42 -0
- package/dist/core/config/types.d.ts +40 -0
- package/dist/core/config/types.js +1 -0
- package/dist/core/features/authenticate/authenticateActionCreation.d.ts +46 -0
- package/dist/core/features/authenticate/authenticateActionCreation.js +326 -0
- package/dist/core/features/authenticate/authenticateSlice.d.ts +45 -0
- package/dist/core/features/authenticate/authenticateSlice.js +203 -0
- package/dist/core/features/data/dataActionCreation.d.ts +40 -0
- package/dist/core/features/data/dataActionCreation.js +340 -0
- package/dist/core/features/data/dataSlice.d.ts +37 -0
- package/dist/core/features/data/dataSlice.js +87 -0
- package/dist/core/features/jobs/jobActionCreation.d.ts +35 -0
- package/dist/core/features/jobs/jobActionCreation.js +242 -0
- package/dist/core/features/jobs/jobsSlice.d.ts +57 -0
- package/dist/core/features/jobs/jobsSlice.js +54 -0
- package/dist/core/features/rois/resultActionCreation.d.ts +21 -0
- package/dist/core/features/rois/resultActionCreation.js +114 -0
- package/dist/core/features/rois/resultSlice.d.ts +24 -0
- package/dist/core/features/rois/resultSlice.js +68 -0
- package/dist/core/features/rois/roiTypes.d.ts +44 -0
- package/dist/core/features/rois/roiTypes.js +1 -0
- package/dist/core/features/setup/setupActionCreation.d.ts +7 -0
- package/dist/core/features/setup/setupActionCreation.js +100 -0
- package/dist/core/index.d.ts +22 -0
- package/dist/core/index.js +27 -0
- package/dist/core/store/configureStore.d.ts +13 -0
- package/dist/core/store/configureStore.js +38 -0
- package/dist/core/store/hooks.d.ts +11 -0
- package/dist/core/store/hooks.js +5 -0
- package/dist/core/utils/passwordValidation.d.ts +25 -0
- package/dist/core/utils/passwordValidation.js +19 -0
- package/dist/index.d.ts +29 -329
- package/dist/index.js +26 -1402
- package/dist/style.css +47 -0
- package/package.json +309 -41
- package/dist/index.css +0 -170
- package/dist/index.mjs +0 -1354
|
@@ -0,0 +1,1270 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
23
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
49
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
50
|
+
if (ar || !(i in from)) {
|
|
51
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
52
|
+
ar[i] = from[i];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
56
|
+
};
|
|
57
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
58
|
+
import React, { useState } from "react";
|
|
59
|
+
import { Box, Button } from "@mui/material";
|
|
60
|
+
import { NVImage } from "@niivue/niivue";
|
|
61
|
+
import { SettingsPanel } from "./components/SettingsPanel";
|
|
62
|
+
import { NumberPicker } from "./components/NumberPicker";
|
|
63
|
+
import { ColorPicker } from "./components/ColorPicker";
|
|
64
|
+
import { LayersPanel } from "./components/LayersPanel";
|
|
65
|
+
import { NiivuePanel } from "./components/NiivuePanel";
|
|
66
|
+
import { Niivue } from "./NiivuePatcher";
|
|
67
|
+
import NVSwitch from "./components/Switch";
|
|
68
|
+
import Toolbar from "./components/Toolbar";
|
|
69
|
+
import Layer from "./components/Layer";
|
|
70
|
+
import "./Niivue.css";
|
|
71
|
+
import { CmrEditConfirmation } from "../../../../index";
|
|
72
|
+
import axios from "axios";
|
|
73
|
+
import { getEndpoints } from "../../../config/AppConfig";
|
|
74
|
+
import Confirmation from "../../../../CmrComponents/dialogue/Confirmation";
|
|
75
|
+
import Plotly from "plotly.js-dist-min";
|
|
76
|
+
import { calculateMean, calculateStandardDeviation } from "./components/stats";
|
|
77
|
+
import JSZip from "jszip";
|
|
78
|
+
import { getMax, getMin } from "../../utilities";
|
|
79
|
+
import { getPipelineROI } from "../../../features/rois/resultActionCreation";
|
|
80
|
+
import { useAppDispatch, useAppSelector } from "../../../store/hooks";
|
|
81
|
+
import { AuthenticatedHttpClient } from "../../utilities/AuthenticatedRequests";
|
|
82
|
+
export var nv = new Niivue({
|
|
83
|
+
loadingText: "",
|
|
84
|
+
isColorbar: true,
|
|
85
|
+
isRadiologicalConvention: true,
|
|
86
|
+
fontSizeScaling: 0.04,
|
|
87
|
+
fontMinPx: 8,
|
|
88
|
+
colorbarHeight: 0.02,
|
|
89
|
+
dragMode: "pan",
|
|
90
|
+
// crosshairColor: [0.098,0.453,0.824]
|
|
91
|
+
crosshairColor: [1, 1, 0],
|
|
92
|
+
fontColor: [0.0, 0.94, 0.37, 1],
|
|
93
|
+
isNearestInterpolation: true,
|
|
94
|
+
isFilledPen: true,
|
|
95
|
+
drawPen: 1
|
|
96
|
+
});
|
|
97
|
+
window.nv = nv;
|
|
98
|
+
// The NiiVue component wraps all other components in the UI.
|
|
99
|
+
// It is exported so that it can be used in other projects easily
|
|
100
|
+
export default function NiiVueport(props) {
|
|
101
|
+
var _this = this;
|
|
102
|
+
var selectedVolume = props.selectedVolume;
|
|
103
|
+
var setSelectedVolume = props.setSelectedVolume;
|
|
104
|
+
var setWarning = props.setWarning, setWarningOpen = props.setWarningOpen;
|
|
105
|
+
// const nv = props.nv;
|
|
106
|
+
var _a = React.useState(false), openSettings = _a[0], setOpenSettings = _a[1];
|
|
107
|
+
var _b = React.useState(false), openLayers = _b[0], setOpenLayers = _b[1];
|
|
108
|
+
var _c = React.useState(nv.opts.crosshairColor), crosshairColor = _c[0], setCrosshairColor = _c[1];
|
|
109
|
+
var _d = React.useState(nv.opts.selectionBoxColor), selectionBoxColor = _d[0], setSelectionBoxColor = _d[1];
|
|
110
|
+
var _e = React.useState(nv.opts.backColor), backColor = _e[0], setBackColor = _e[1];
|
|
111
|
+
var _f = React.useState(nv.opts.clipPlaneColor), clipPlaneColor = _f[0], setClipPlaneColor = _f[1];
|
|
112
|
+
var _g = React.useState(nv.volumes), layers = _g[0], setLayers = _g[1];
|
|
113
|
+
var _h = React.useState(false), cornerText = _h[0], setCornerText = _h[1];
|
|
114
|
+
var _j = React.useState(true), radiological = _j[0], setRadiological = _j[1];
|
|
115
|
+
var _k = React.useState(false), crosshair3D = _k[0], setCrosshair3D = _k[1];
|
|
116
|
+
var _l = React.useState(nv.opts.textHeight), textSize = _l[0], setTextSize = _l[1];
|
|
117
|
+
var _m = React.useState(nv.opts.isColorbar), colorBar = _m[0], setColorBar = _m[1];
|
|
118
|
+
var _o = React.useState(nv.opts.isSliceMM), worldSpace = _o[0], setWorldSpace = _o[1];
|
|
119
|
+
var _p = React.useState(nv.currentClipPlaneIndex > 0 ? true : false), clipPlane = _p[0], setClipPlane = _p[1];
|
|
120
|
+
// TODO: add crosshair size state and setter
|
|
121
|
+
var _q = React.useState(1.0), opacity = _q[0], setopacity = _q[1];
|
|
122
|
+
var _r = React.useState(nv.opts.drawingEnabled), drawingEnabled = _r[0], setDrawingEnabled = _r[1];
|
|
123
|
+
var _s = React.useState(nv.opts.drawPen), drawPen = _s[0], setDrawPen = _s[1];
|
|
124
|
+
var _t = React.useState(0.8), drawOpacity = _t[0], setDrawOpacity = _t[1];
|
|
125
|
+
var _u = React.useState(nv.opts.crosshairColor[3]), crosshairOpacity = _u[0], setCrosshairOpacity = _u[1];
|
|
126
|
+
var _v = React.useState(nv.opts.clipPlaneColor[3]), clipPlaneOpacity = _v[0], setClipPlaneOpacity = _v[1];
|
|
127
|
+
// Remembers the last crosshair position in millimeter space across volume switches
|
|
128
|
+
var lastMMRef = React.useRef(null);
|
|
129
|
+
var _w = React.useState(true), locationTableVisible = _w[0], setLocationTableVisible = _w[1];
|
|
130
|
+
var _x = React.useState([]), locationData = _x[0], setLocationData = _x[1];
|
|
131
|
+
var _y = React.useState(2), decimalPrecision = _y[0], setDecimalPrecision = _y[1];
|
|
132
|
+
var _z = React.useState(nv.opts.isOrientCube), orientCube = _z[0], setOrientCube = _z[1];
|
|
133
|
+
var _0 = React.useState(nv.opts.isRuler), ruler = _0[0], setRuler = _0[1];
|
|
134
|
+
var _1 = React.useState(nv.opts.multiplanarPadPixels), multiplanarPadPixels = _1[0], setMultiplanarPadPixels = _1[1];
|
|
135
|
+
var _2 = React.useState(nv.opts.maxDrawUndoBitmaps), maxDrawUndoBitmaps = _2[0], setMaxDrawUndoBitmaps = _2[1];
|
|
136
|
+
var _3 = React.useState(nv.opts.sagittalNoseLeft), sagittalNoseLeft = _3[0], setSagittalNoseLeft = _3[1];
|
|
137
|
+
var _4 = React.useState(nv.opts.rulerWidth), rulerWidth = _4[0], setRulerWidth = _4[1];
|
|
138
|
+
var _5 = React.useState(nv.opts.longTouchTimeout), longTouchTimeout = _5[0], setLongTouchTimeout = _5[1];
|
|
139
|
+
var _6 = React.useState(nv.opts.doubleTouchTimeout), doubleTouchTimeout = _6[0], setDoubleTouchTimeout = _6[1];
|
|
140
|
+
var _7 = React.useState(nv.opts.isDragShowsMeasurementTool), dragToMeasure = _7[0], setDragToMeasure = _7[1];
|
|
141
|
+
var _8 = React.useState(nv.opts.rulerColor), rulerColor = _8[0], setRulerColor = _8[1];
|
|
142
|
+
var _9 = React.useState(nv.opts.rulerColor[3]), rulerOpacity = _9[0], setRulerOpacity = _9[1];
|
|
143
|
+
var _10 = React.useState(false), highDPI = _10[0], setHighDPI = _10[1];
|
|
144
|
+
var histoRef = React.useRef(null);
|
|
145
|
+
var _11 = React.useState([]), rois = _11[0], setROIs = _11[1];
|
|
146
|
+
var _12 = React.useState(true), showCrosshair = _12[0], setShowCrosshair = _12[1];
|
|
147
|
+
var _13 = useState(1), brushSize = _13[0], setBrushSize = _13[1];
|
|
148
|
+
var _14 = useState("absolute"), complexMode = _14[0], setComplexMode = _14[1];
|
|
149
|
+
var _15 = useState(["absolute"]), complexOptions = _15[0], setComplexOptions = _15[1];
|
|
150
|
+
var _16 = useState(true), roiVisible = _16[0], setROIVisible = _16[1];
|
|
151
|
+
var _17 = useState(0.8), drawingOpacity = _17[0], setDrawingOpacity = _17[1];
|
|
152
|
+
var _18 = useState(0), min = _18[0], setMin = _18[1];
|
|
153
|
+
var _19 = useState(1), max = _19[0], setMax = _19[1];
|
|
154
|
+
var _20 = useState(false), textsVisible = _20[0], setTextsVisible = _20[1];
|
|
155
|
+
var _21 = useState({ a: 1, b: 0 }), transformFactors = _21[0], setTransformFactors = _21[1];
|
|
156
|
+
var _22 = useState(false), saving = _22[0], setSaving = _22[1];
|
|
157
|
+
// Gamma settings
|
|
158
|
+
var _23 = React.useState(1.0), gamma = _23[0], setGamma = _23[1];
|
|
159
|
+
var _24 = React.useState(0), gammaKey = _24[0], setGammaKey = _24[1];
|
|
160
|
+
// Niivue → React bridge so other places (Toolbar) can force the UI to reset
|
|
161
|
+
nv.onResetGamma = function () {
|
|
162
|
+
setGamma(1.0);
|
|
163
|
+
setGammaKey(function (k) { return k + 1; }); // re-mounts the slider to reflect the reset
|
|
164
|
+
};
|
|
165
|
+
React.useEffect(function () {
|
|
166
|
+
resampleImage();
|
|
167
|
+
// histogram.current?.addEventListener('resize',()=>props.resampleImage());
|
|
168
|
+
}, [histoRef]);
|
|
169
|
+
React.useEffect(function () {
|
|
170
|
+
if (nv.volumes.length !== 0) {
|
|
171
|
+
setLayers(__spreadArray([], nv.volumes, true));
|
|
172
|
+
setBoundMins(nv.frac2mm([0, 0, 0]));
|
|
173
|
+
setBoundMaxs(nv.frac2mm([1, 1, 1]));
|
|
174
|
+
// setMMs(nv.frac2mm([0.5, 0.5, 0.5])); // Commented to prevent recentering on volume load; we now re-apply saved crosshair if available
|
|
175
|
+
try {
|
|
176
|
+
// Initialize sliders to the engine's current crosshair (in mm), not a hard-coded 0.5
|
|
177
|
+
setMMs(nv.frac2mm(nv.scene.crosshairPos));
|
|
178
|
+
}
|
|
179
|
+
catch (_a) { }
|
|
180
|
+
setTimeout(function (args) { return nv.resizeListener(); }, 700);
|
|
181
|
+
}
|
|
182
|
+
}, []);
|
|
183
|
+
// Load initial volume on mount.
|
|
184
|
+
// Note: nv.loadVolumes() triggers onImageLoaded callback (line 285)
|
|
185
|
+
// which handles all the setup automatically.
|
|
186
|
+
React.useEffect(function () {
|
|
187
|
+
var loadInitialVolume = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
188
|
+
var e_1;
|
|
189
|
+
return __generator(this, function (_a) {
|
|
190
|
+
switch (_a.label) {
|
|
191
|
+
case 0:
|
|
192
|
+
if (!props.niis[selectedVolume]) return [3 /*break*/, 4];
|
|
193
|
+
_a.label = 1;
|
|
194
|
+
case 1:
|
|
195
|
+
_a.trys.push([1, 3, , 4]);
|
|
196
|
+
// loadVolumes calls onImageLoaded which does all setup
|
|
197
|
+
return [4 /*yield*/, nv.loadVolumes([niiToVolume(props.niis[selectedVolume])])];
|
|
198
|
+
case 2:
|
|
199
|
+
// loadVolumes calls onImageLoaded which does all setup
|
|
200
|
+
_a.sent();
|
|
201
|
+
// Force a multiplanar view switch to trigger proper rendering, then switch back
|
|
202
|
+
// TODO: fix this horrible hack
|
|
203
|
+
setTimeout(function () {
|
|
204
|
+
nv.setSliceType(nv.sliceTypeMultiplanar);
|
|
205
|
+
// Then switch to the desired slice type
|
|
206
|
+
setTimeout(function () {
|
|
207
|
+
nvUpdateSliceType(sliceType);
|
|
208
|
+
if (!lastMMRef.current) {
|
|
209
|
+
try {
|
|
210
|
+
setMMs(nv.frac2mm(nv.scene.crosshairPos));
|
|
211
|
+
}
|
|
212
|
+
catch (_a) { }
|
|
213
|
+
}
|
|
214
|
+
}, 50);
|
|
215
|
+
}, 100);
|
|
216
|
+
return [3 /*break*/, 4];
|
|
217
|
+
case 3:
|
|
218
|
+
e_1 = _a.sent();
|
|
219
|
+
console.error("Error loading initial volume:", e_1);
|
|
220
|
+
setWarning("Error loading results, please check internet connectivity");
|
|
221
|
+
setWarningOpen(true);
|
|
222
|
+
setTimeout(function () {
|
|
223
|
+
setWarningOpen(false);
|
|
224
|
+
setWarning("");
|
|
225
|
+
}, 2500);
|
|
226
|
+
return [3 /*break*/, 4];
|
|
227
|
+
case 4: return [2 /*return*/];
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}); };
|
|
231
|
+
loadInitialVolume();
|
|
232
|
+
}, []); // Empty dependency array - only run on mount
|
|
233
|
+
React.useEffect(function () {
|
|
234
|
+
// console.log(props.niis[props.selectedVolume]);
|
|
235
|
+
//Wait for other rendering processes to complete before applying styles
|
|
236
|
+
stylingProxy(props.niis[props.selectedVolume]);
|
|
237
|
+
}, [props.selectedVolume, props.niis]);
|
|
238
|
+
// only run this when the component is mounted on the page
|
|
239
|
+
// or else it will be recursive and continuously add all
|
|
240
|
+
// initial images supplied to the NiiVue component
|
|
241
|
+
//
|
|
242
|
+
// All subsequent imgaes should be added via a
|
|
243
|
+
// button or drag and drop
|
|
244
|
+
// React.useEffect(async ()=>{
|
|
245
|
+
// // props.volumes.map(async (vol)=>{
|
|
246
|
+
// // let image = await NVImage.loadFromUrl({url:vol.url})
|
|
247
|
+
// // nv.addVolume(image)
|
|
248
|
+
// // setLayers([...nv.volumes])
|
|
249
|
+
// // })
|
|
250
|
+
// await nv.loadVolumes(props.volumes)
|
|
251
|
+
// setLayers([...nv.volumes])
|
|
252
|
+
// }, [])
|
|
253
|
+
// values dualslider
|
|
254
|
+
var _25 = useState(0), rangeKey = _25[0], setRangeKey = _25[1];
|
|
255
|
+
nv.onResetContrast = function () {
|
|
256
|
+
setRangeKey(rangeKey + 1);
|
|
257
|
+
};
|
|
258
|
+
var _26 = useState([0, 0, 0]), boundMins = _26[0], setBoundMins = _26[1];
|
|
259
|
+
var _27 = useState([1, 1, 1]), boundMaxs = _27[0], setBoundMaxs = _27[1];
|
|
260
|
+
var _28 = useState([0.5, 0.5, 0.5]), mms = _28[0], setMMs = _28[1];
|
|
261
|
+
nv.onImageLoaded = function () {
|
|
262
|
+
var _a;
|
|
263
|
+
if (nv.volumes.length > 1) {
|
|
264
|
+
nv.loadVolumes([niiToVolume(props.niis[props.selectedVolume])]);
|
|
265
|
+
setWarning("Error loading results, please check internet connectivity");
|
|
266
|
+
setWarningOpen(true);
|
|
267
|
+
setTimeout(function () {
|
|
268
|
+
setWarningOpen(false);
|
|
269
|
+
setWarning("");
|
|
270
|
+
}, 2500);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
// console.log(nv.volumes);
|
|
274
|
+
setLayers(__spreadArray([], nv.volumes, true));
|
|
275
|
+
setBoundMins(nv.frac2mm([0, 0, 0]));
|
|
276
|
+
setBoundMaxs(nv.frac2mm([1, 1, 1]));
|
|
277
|
+
// setMMs(nv.frac2mm([0.5, 0.5, 0.5])); // Commented to prevent recentering on volume load; we now re-apply saved crosshair if available
|
|
278
|
+
if (verifyComplex(nv.volumes[0]))
|
|
279
|
+
//Check if there are complex components
|
|
280
|
+
nvSetDisplayedVoxels("absolute");
|
|
281
|
+
else
|
|
282
|
+
nvSetDisplayedVoxels("absolute");
|
|
283
|
+
var volume = nv.volumes[0];
|
|
284
|
+
nv.setGamma(1.0);
|
|
285
|
+
(_a = nv.onResetGamma) === null || _a === void 0 ? void 0 : _a.call(nv);
|
|
286
|
+
nv.resetScene();
|
|
287
|
+
nvSetDragMode(dragMode); // keep engine behavior in sync with dropdown
|
|
288
|
+
// Re-apply world/voxel mode and last crosshair after resets
|
|
289
|
+
nv.setSliceMM(worldSpace);
|
|
290
|
+
applySavedCrosshairIfAny();
|
|
291
|
+
// NEW: keep display mode consistent after resets
|
|
292
|
+
nvUpdateSliceType(sliceType);
|
|
293
|
+
if (!lastMMRef.current) {
|
|
294
|
+
try {
|
|
295
|
+
setMMs(nv.frac2mm(nv.scene.crosshairPos));
|
|
296
|
+
}
|
|
297
|
+
catch (_b) { }
|
|
298
|
+
}
|
|
299
|
+
// Force a complete re-render with texture rebinding
|
|
300
|
+
// This ensures textures are properly bound in the current view mode
|
|
301
|
+
setTimeout(function () {
|
|
302
|
+
nv.updateGLVolume();
|
|
303
|
+
nv.drawScene();
|
|
304
|
+
}, 100);
|
|
305
|
+
};
|
|
306
|
+
function checkRange(numbers) {
|
|
307
|
+
// console.log(numbers);
|
|
308
|
+
var range_min = getMin(numbers);
|
|
309
|
+
var range_max = getMax(numbers);
|
|
310
|
+
var range = range_max - range_min;
|
|
311
|
+
if (range == 0) {
|
|
312
|
+
return numbers;
|
|
313
|
+
}
|
|
314
|
+
if (range < 1e-2) {
|
|
315
|
+
// Find a suitable 'a' that is a whole power of 10
|
|
316
|
+
// Here, we want 'a' to scale the range to fit within [1, 10)
|
|
317
|
+
var a_1 = 1;
|
|
318
|
+
var power = 0;
|
|
319
|
+
while (range * a_1 < 1) {
|
|
320
|
+
a_1 *= 10;
|
|
321
|
+
power += 1;
|
|
322
|
+
}
|
|
323
|
+
// Calculate 'b' such that the minimum transformed value is 1 (x = 1)
|
|
324
|
+
var b_1 = Math.floor(a_1 * range_min - ((a_1 * range_min) % 10)) / a_1;
|
|
325
|
+
console.log(b_1);
|
|
326
|
+
// Apply the transformation ax + b
|
|
327
|
+
var transformed = numbers.map(function (y) { return a_1 * y - a_1 * b_1; });
|
|
328
|
+
setTransformFactors({ a: a_1, b: b_1 });
|
|
329
|
+
nv.transformA = a_1;
|
|
330
|
+
nv.transformB = b_1;
|
|
331
|
+
nv.power = power;
|
|
332
|
+
return transformed;
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
// If range is not smaller than 10E-2, return the original array
|
|
336
|
+
setTransformFactors({ a: 1, b: 0 });
|
|
337
|
+
nv.transformA = 1;
|
|
338
|
+
nv.transformB = 0;
|
|
339
|
+
nv.power = undefined;
|
|
340
|
+
return numbers;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
function verifyComplex(volume) {
|
|
344
|
+
volume.real = volume.img;
|
|
345
|
+
setComplexMode("absolute");
|
|
346
|
+
// Ensure volume.imaginary is defined and has the same length as volume.img
|
|
347
|
+
if (!volume.imaginary || volume.imaginary.length !== volume.img.length) {
|
|
348
|
+
setComplexOptions(["absolute", "real"]);
|
|
349
|
+
// Initialize absolute and phase arrays
|
|
350
|
+
volume.absolute = new volume.img.constructor(volume.img.length);
|
|
351
|
+
// Calculate absolute and phase values
|
|
352
|
+
for (var i = 0; i < volume.img.length; i++) {
|
|
353
|
+
var realPart = volume.real[i];
|
|
354
|
+
// Calculate the absolute value (magnitude)
|
|
355
|
+
volume.absolute[i] = Math.sqrt(realPart * realPart);
|
|
356
|
+
}
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
var allZero = true;
|
|
360
|
+
// Test for imaginary nulls
|
|
361
|
+
for (var i = 0; i < volume.img.length; i++) {
|
|
362
|
+
if (volume.imaginary[i] !== 0) {
|
|
363
|
+
allZero = false;
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
// Initialize absolute and phase arrays
|
|
368
|
+
volume.absolute = new Float32Array(volume.img.length);
|
|
369
|
+
volume.phase = new Float32Array(volume.img.length);
|
|
370
|
+
// Calculate absolute and phase values
|
|
371
|
+
for (var i = 0; i < volume.img.length; i++) {
|
|
372
|
+
var realPart = volume.real[i];
|
|
373
|
+
var imaginaryPart = volume.imaginary[i];
|
|
374
|
+
// Calculate the absolute value (magnitude)
|
|
375
|
+
volume.absolute[i] = Math.sqrt(realPart * realPart + imaginaryPart * imaginaryPart);
|
|
376
|
+
// Calculate the phase (argument)
|
|
377
|
+
volume.phase[i] = Math.atan2(imaginaryPart, realPart);
|
|
378
|
+
}
|
|
379
|
+
setComplexOptions(allZero
|
|
380
|
+
? ["absolute", "real"]
|
|
381
|
+
: ["absolute", "imaginary", "real", "phase"]);
|
|
382
|
+
return !allZero;
|
|
383
|
+
}
|
|
384
|
+
function nvSetDisplayedVoxels(voxelType) {
|
|
385
|
+
setComplexMode(voxelType);
|
|
386
|
+
var volume = nv.volumes[0];
|
|
387
|
+
switch (voxelType) {
|
|
388
|
+
case "phase":
|
|
389
|
+
volume.img = checkRange(volume.phase);
|
|
390
|
+
break;
|
|
391
|
+
case "absolute":
|
|
392
|
+
volume.img = checkRange(volume.absolute);
|
|
393
|
+
break;
|
|
394
|
+
case "real":
|
|
395
|
+
volume.img = checkRange(volume.real);
|
|
396
|
+
break;
|
|
397
|
+
case "imaginary":
|
|
398
|
+
volume.img = checkRange(volume.imaginary);
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
volume.calMinMax();
|
|
402
|
+
setMin(volume.cal_min);
|
|
403
|
+
setMax(volume.cal_max);
|
|
404
|
+
volume.vox_min = getMin(volume.img);
|
|
405
|
+
volume.vox_max = getMax(volume.img);
|
|
406
|
+
nv.setVolume(volume);
|
|
407
|
+
nv.drawScene();
|
|
408
|
+
resampleImage();
|
|
409
|
+
}
|
|
410
|
+
nv.onLocationChange = function (data) {
|
|
411
|
+
if (data.values[0]) {
|
|
412
|
+
setMMs(__spreadArray([], data.values[0].mm, true)); // ensure new array -> React re-renders
|
|
413
|
+
lastMMRef.current = __spreadArray([], data.values[0].mm, true); // keep a fresh copy in the ref too
|
|
414
|
+
data.values[0].transformA = nv.transformA;
|
|
415
|
+
data.values[0].transformB = nv.transformB;
|
|
416
|
+
data.values[0].power = nv.power;
|
|
417
|
+
}
|
|
418
|
+
setLocationData(data.values);
|
|
419
|
+
// if(drawingEnabled){
|
|
420
|
+
// setDrawingChanged(true);
|
|
421
|
+
// // resampleImage();
|
|
422
|
+
// }
|
|
423
|
+
// console.log(nv.scene.pan2Dxyzmm);
|
|
424
|
+
};
|
|
425
|
+
nv.onMouseUp = function (data) {
|
|
426
|
+
if (drawingEnabled) {
|
|
427
|
+
setDrawingChanged(true);
|
|
428
|
+
resampleImage();
|
|
429
|
+
}
|
|
430
|
+
};
|
|
431
|
+
/**
|
|
432
|
+
* Way to test all value changes
|
|
433
|
+
*/
|
|
434
|
+
nv.onIntensityChange = function () {
|
|
435
|
+
var volume = nv.volumes[0];
|
|
436
|
+
setMin(volume.cal_min);
|
|
437
|
+
setMax(volume.cal_max);
|
|
438
|
+
};
|
|
439
|
+
// nv.createEmptyDrawing();
|
|
440
|
+
// construct an array of <Layer> components. Each layer is a NVImage or NVMesh
|
|
441
|
+
var layerList = layers.map(function (layer, index) {
|
|
442
|
+
return index === 0 ? ( //Yuelong: we shall expect only one effective layer in this implementation
|
|
443
|
+
_jsx(Layer, { image: layer, nv: nv, nii: props.niis[props.selectedVolume], onColorMapChange: nvUpdateColorMap, onRemoveLayer: nvRemoveLayer, onOpacityChange: nvUpdateLayerOpacity, colorMapValues: nv.colormapFromKey(layer.colormap), getColorMapValues: function (colorMapName) {
|
|
444
|
+
return nv.colormapFromKey(colorMapName);
|
|
445
|
+
} }, layer.name)) : undefined;
|
|
446
|
+
});
|
|
447
|
+
function addLayer(file) {
|
|
448
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
449
|
+
var nvimage;
|
|
450
|
+
return __generator(this, function (_a) {
|
|
451
|
+
switch (_a.label) {
|
|
452
|
+
case 0: return [4 /*yield*/, NVImage.loadFromFile({
|
|
453
|
+
file: file
|
|
454
|
+
})];
|
|
455
|
+
case 1:
|
|
456
|
+
nvimage = _a.sent();
|
|
457
|
+
nv.addVolume(nvimage);
|
|
458
|
+
setLayers(__spreadArray([], nv.volumes, true));
|
|
459
|
+
return [2 /*return*/];
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
function toggleSettings() {
|
|
465
|
+
setOpenSettings(!openSettings);
|
|
466
|
+
}
|
|
467
|
+
function toggleLayers() {
|
|
468
|
+
setOpenLayers(!openLayers);
|
|
469
|
+
}
|
|
470
|
+
function toggleLocationTable() {
|
|
471
|
+
setLocationTableVisible(!locationTableVisible);
|
|
472
|
+
}
|
|
473
|
+
function toggleROIVisible() {
|
|
474
|
+
if (roiVisible) {
|
|
475
|
+
setDrawingOpacity(nv.drawOpacity);
|
|
476
|
+
setROIVisible(false);
|
|
477
|
+
nv.setDrawOpacity(0);
|
|
478
|
+
resampleImage();
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
nv.setDrawOpacity(drawingOpacity);
|
|
482
|
+
setROIVisible(true);
|
|
483
|
+
resampleImage();
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
function nvUpdateDrawingOpacity(opacity) {
|
|
487
|
+
setDrawingOpacity(opacity);
|
|
488
|
+
if (roiVisible) {
|
|
489
|
+
nv.setDrawOpacity(opacity);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
function nvUpdateOpacity(a) {
|
|
493
|
+
console.log("Opacity = " + a);
|
|
494
|
+
setopacity(a);
|
|
495
|
+
var n = nv.volumes.length;
|
|
496
|
+
for (var i = 0; i < n; i++) {
|
|
497
|
+
nv.volumes[i].opacity = a;
|
|
498
|
+
}
|
|
499
|
+
nv.updateGLVolume();
|
|
500
|
+
}
|
|
501
|
+
function nvToggleLabelVisible() {
|
|
502
|
+
if (textsVisible) {
|
|
503
|
+
nv.hideText = true;
|
|
504
|
+
nv.drawScene();
|
|
505
|
+
setTextsVisible(false);
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
nv.hideText = false;
|
|
509
|
+
nv.drawScene();
|
|
510
|
+
setTextsVisible(true);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
var _29 = useState("pan"), dragMode = _29[0], setDragMode = _29[1];
|
|
514
|
+
function nvSetDragMode(dragMode) {
|
|
515
|
+
switch (dragMode) {
|
|
516
|
+
case "none":
|
|
517
|
+
nv.opts.dragMode = nv.dragModes.none;
|
|
518
|
+
break;
|
|
519
|
+
case "contrast":
|
|
520
|
+
console.log("setting drag mode to contrast");
|
|
521
|
+
nv.opts.dragMode = nv.dragModes.contrast;
|
|
522
|
+
break;
|
|
523
|
+
case "measurement":
|
|
524
|
+
nv.opts.dragMode = nv.dragModes.measurement;
|
|
525
|
+
break;
|
|
526
|
+
case "pan":
|
|
527
|
+
// nv.opts.dragMode = 3;
|
|
528
|
+
nv.opts.dragMode = nv.dragModes.pan;
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
// nv.drawScene();
|
|
532
|
+
setDragMode(dragMode);
|
|
533
|
+
}
|
|
534
|
+
function nvSaveImage() {
|
|
535
|
+
nv.saveImage({
|
|
536
|
+
filename: "roi.nii",
|
|
537
|
+
isSaveDrawing: true
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
function nvUpdateDrawingEnabled() {
|
|
541
|
+
setDrawingEnabled(!drawingEnabled);
|
|
542
|
+
nv.setDrawingEnabled(!drawingEnabled);
|
|
543
|
+
nv.drawScene();
|
|
544
|
+
}
|
|
545
|
+
function nvSetDrawingEnabled(enabled) {
|
|
546
|
+
setDrawingEnabled(enabled);
|
|
547
|
+
nv.setDrawingEnabled(enabled);
|
|
548
|
+
nv.drawScene();
|
|
549
|
+
}
|
|
550
|
+
function nvUpdateDrawPen(a) {
|
|
551
|
+
setDrawPen(a.target.value);
|
|
552
|
+
var penValue = a.target.value;
|
|
553
|
+
nv.setPenValue(penValue & 7, penValue > 0);
|
|
554
|
+
if (penValue === 8) {
|
|
555
|
+
nv.setPenValue(0, true);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
function nvUpdateBrushSize(size) {
|
|
559
|
+
setBrushSize(size);
|
|
560
|
+
nv.opts.penBounds = (size - 1) / 2;
|
|
561
|
+
}
|
|
562
|
+
function nvUpdateDrawOpacity(a) {
|
|
563
|
+
setDrawOpacity(a);
|
|
564
|
+
nv.setDrawOpacity(a);
|
|
565
|
+
}
|
|
566
|
+
function nvUpdateCrosshairColor(rgb01, a) {
|
|
567
|
+
if (a === void 0) { a = 1; }
|
|
568
|
+
setCrosshairColor(__spreadArray(__spreadArray([], rgb01, true), [a], false));
|
|
569
|
+
nv.setCrosshairColor(__spreadArray(__spreadArray([], rgb01, true), [a], false));
|
|
570
|
+
}
|
|
571
|
+
function nvUpdateOrientCube() {
|
|
572
|
+
nv.opts.isOrientCube = !orientCube;
|
|
573
|
+
setOrientCube(!orientCube);
|
|
574
|
+
nv.drawScene();
|
|
575
|
+
}
|
|
576
|
+
function nvUpdateHighDPI() {
|
|
577
|
+
nv.setHighResolutionCapable(!highDPI);
|
|
578
|
+
setHighDPI(!highDPI);
|
|
579
|
+
}
|
|
580
|
+
function nvUpdateMultiplanarPadPixels(v) {
|
|
581
|
+
nv.opts.multiplanarPadPixels = v;
|
|
582
|
+
setMultiplanarPadPixels(v);
|
|
583
|
+
nv.drawScene();
|
|
584
|
+
}
|
|
585
|
+
function nvUpdateRuler() {
|
|
586
|
+
nv.opts.isRuler = !ruler;
|
|
587
|
+
setRuler(!ruler);
|
|
588
|
+
nv.drawScene();
|
|
589
|
+
}
|
|
590
|
+
function nvUpdateSagittalNoseLeft() {
|
|
591
|
+
nv.opts.sagittalNoseLeft = !sagittalNoseLeft;
|
|
592
|
+
setSagittalNoseLeft(!sagittalNoseLeft);
|
|
593
|
+
nv.drawScene();
|
|
594
|
+
}
|
|
595
|
+
function nvUpdateRulerWidth(v) {
|
|
596
|
+
nv.opts.rulerWidth = v;
|
|
597
|
+
setRulerWidth(v);
|
|
598
|
+
nv.drawScene();
|
|
599
|
+
}
|
|
600
|
+
function nvUpdateRulerOpacity(a) {
|
|
601
|
+
nv.opts.rulerColor = [rulerColor[0], rulerColor[1], rulerColor[2], a];
|
|
602
|
+
setRulerOpacity(a);
|
|
603
|
+
nv.drawScene();
|
|
604
|
+
}
|
|
605
|
+
function nvUpdateLongTouchTimeout(v) {
|
|
606
|
+
nv.opts.longTouchTimeout = v;
|
|
607
|
+
setLongTouchTimeout(v);
|
|
608
|
+
}
|
|
609
|
+
function nvUpdateDoubleTouchTimeout(v) {
|
|
610
|
+
nv.opts.doubleTouchTimeout = v;
|
|
611
|
+
setDoubleTouchTimeout(v);
|
|
612
|
+
}
|
|
613
|
+
function nvUpdateDragToMeasure() {
|
|
614
|
+
nv.opts.isDragShowsMeasurementTool = !dragToMeasure;
|
|
615
|
+
setDragToMeasure(!dragToMeasure);
|
|
616
|
+
}
|
|
617
|
+
function nvUpdateMaxDrawUndoBitmaps(v) {
|
|
618
|
+
nv.opts.maxDrawUndoBitmaps = v;
|
|
619
|
+
setMaxDrawUndoBitmaps(v);
|
|
620
|
+
}
|
|
621
|
+
function nvUpdateBackColor(rgb01, a) {
|
|
622
|
+
if (a === void 0) { a = 1; }
|
|
623
|
+
setBackColor(__spreadArray(__spreadArray([], rgb01, true), [a], false));
|
|
624
|
+
nv.opts.backColor = __spreadArray(__spreadArray([], rgb01, true), [a], false);
|
|
625
|
+
nv.drawScene();
|
|
626
|
+
}
|
|
627
|
+
function nvUpdateRulerColor(rgb01, a) {
|
|
628
|
+
if (a === void 0) { a = 1; }
|
|
629
|
+
setRulerColor(__spreadArray(__spreadArray([], rgb01, true), [a], false));
|
|
630
|
+
nv.opts.rulerColor = __spreadArray(__spreadArray([], rgb01, true), [a], false);
|
|
631
|
+
if (!ruler) {
|
|
632
|
+
nv.opts.isRuler = !ruler;
|
|
633
|
+
setRuler(!ruler);
|
|
634
|
+
}
|
|
635
|
+
nv.drawScene();
|
|
636
|
+
}
|
|
637
|
+
function nvUpdateClipPlaneColor(rgb01, a) {
|
|
638
|
+
if (a === void 0) { a = 1; }
|
|
639
|
+
setClipPlaneColor(__spreadArray(__spreadArray([], rgb01, true), [a], false));
|
|
640
|
+
nv.opts.clipPlaneColor = __spreadArray(__spreadArray([], rgb01, true), [a], false);
|
|
641
|
+
setClipPlane(true);
|
|
642
|
+
nv.setClipPlane([0, 270, 0]); //left
|
|
643
|
+
nv.updateGLVolume();
|
|
644
|
+
}
|
|
645
|
+
function nvUpdateClipPlane() {
|
|
646
|
+
if (!clipPlane) {
|
|
647
|
+
setClipPlane(true);
|
|
648
|
+
nv.setClipPlane([0, 270, 0]); //left
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
setClipPlane(false);
|
|
652
|
+
nv.setClipPlane([2, 0, 0]); //none
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
function nvUpdateColorBar() {
|
|
656
|
+
setColorBar(!colorBar);
|
|
657
|
+
nv.opts.isColorbar = !colorBar;
|
|
658
|
+
nv.drawScene();
|
|
659
|
+
}
|
|
660
|
+
function nvUpdateTextSize(v) {
|
|
661
|
+
setTextSize(v);
|
|
662
|
+
nv.opts.textHeight = v;
|
|
663
|
+
nv.drawScene();
|
|
664
|
+
}
|
|
665
|
+
function updateDecimalPrecision(v) {
|
|
666
|
+
setDecimalPrecision(v);
|
|
667
|
+
}
|
|
668
|
+
function nvUpdateWorldSpace() {
|
|
669
|
+
nvUpdateCrosshair3D();
|
|
670
|
+
setWorldSpace(!worldSpace);
|
|
671
|
+
nv.setSliceMM(!worldSpace);
|
|
672
|
+
// keep sliders synced to the currently displayed crosshair
|
|
673
|
+
try {
|
|
674
|
+
setMMs(nv.frac2mm(nv.scene.crosshairPos));
|
|
675
|
+
}
|
|
676
|
+
catch (_a) { }
|
|
677
|
+
}
|
|
678
|
+
function nvUpdateCornerText() {
|
|
679
|
+
nv.setCornerOrientationText(!cornerText);
|
|
680
|
+
setCornerText(!cornerText);
|
|
681
|
+
}
|
|
682
|
+
function nvUpdateCrosshair3D() {
|
|
683
|
+
nv.opts.show3Dcrosshair = !crosshair3D;
|
|
684
|
+
nv.updateGLVolume();
|
|
685
|
+
setCrosshair3D(!crosshair3D);
|
|
686
|
+
}
|
|
687
|
+
function nvUpdateCrosshair() {
|
|
688
|
+
nv.opts.crosshairWidth = showCrosshair ? 0 : 1;
|
|
689
|
+
nv.drawScene();
|
|
690
|
+
setShowCrosshair(!showCrosshair);
|
|
691
|
+
}
|
|
692
|
+
function nvUpdateRadiological() {
|
|
693
|
+
nv.setRadiologicalConvention(!radiological);
|
|
694
|
+
setRadiological(!radiological);
|
|
695
|
+
}
|
|
696
|
+
function nvUpdateCrosshairOpacity(a) {
|
|
697
|
+
nv.setCrosshairColor([
|
|
698
|
+
crosshairColor[0],
|
|
699
|
+
crosshairColor[1],
|
|
700
|
+
crosshairColor[2],
|
|
701
|
+
a,
|
|
702
|
+
]);
|
|
703
|
+
setCrosshairOpacity(a);
|
|
704
|
+
}
|
|
705
|
+
function nvUpdateClipPlaneOpacity(a) {
|
|
706
|
+
nv.opts.clipPlaneColor = [
|
|
707
|
+
clipPlaneColor[0],
|
|
708
|
+
clipPlaneColor[1],
|
|
709
|
+
clipPlaneColor[2],
|
|
710
|
+
a,
|
|
711
|
+
];
|
|
712
|
+
setClipPlaneOpacity(a);
|
|
713
|
+
nv.updateGLVolume();
|
|
714
|
+
}
|
|
715
|
+
function nvUpdateCrosshairSize(w) {
|
|
716
|
+
nv.opts.crosshairWidth = w;
|
|
717
|
+
nv.drawScene();
|
|
718
|
+
}
|
|
719
|
+
// Re-apply a saved crosshair position (in mm) after any operation that resets Niivue state.
|
|
720
|
+
function applySavedCrosshairIfAny() {
|
|
721
|
+
try {
|
|
722
|
+
if (!lastMMRef.current)
|
|
723
|
+
return;
|
|
724
|
+
// Ensure engine uses the currently selected coordinate system
|
|
725
|
+
nv.setSliceMM(worldSpace);
|
|
726
|
+
var frac = nv.mm2frac(lastMMRef.current);
|
|
727
|
+
if (Array.isArray(frac) && frac.length === 3) {
|
|
728
|
+
nv.scene.crosshairPos = frac;
|
|
729
|
+
nv.drawScene();
|
|
730
|
+
setMMs(nv.frac2mm(frac)); // returns a new array; guarantees a state change
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
catch (e) {
|
|
734
|
+
// Intentionally ignore; if conversion fails we simply skip re-applying.
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
var _30 = useState({}), labelMapping = _30[0], setLabelMapping = _30[1];
|
|
738
|
+
function resampleImage(mapping) {
|
|
739
|
+
if (mapping === void 0) { mapping = labelMapping; }
|
|
740
|
+
var image = nv.volumes[0];
|
|
741
|
+
var rois = [];
|
|
742
|
+
var layout = {
|
|
743
|
+
barmode: "overlay",
|
|
744
|
+
title: { text: "ROI Histogram" },
|
|
745
|
+
// height: 100,
|
|
746
|
+
margin: {
|
|
747
|
+
l: 50,
|
|
748
|
+
r: 50,
|
|
749
|
+
b: 50,
|
|
750
|
+
t: 60,
|
|
751
|
+
pad: 4
|
|
752
|
+
},
|
|
753
|
+
xaxis: {
|
|
754
|
+
autoscale: true,
|
|
755
|
+
title: { text: "Voxel value" },
|
|
756
|
+
showgrid: true
|
|
757
|
+
},
|
|
758
|
+
yaxis: {
|
|
759
|
+
autoscale: true,
|
|
760
|
+
title: { text: "Bin frequency" },
|
|
761
|
+
showgrid: true
|
|
762
|
+
},
|
|
763
|
+
responsive: true
|
|
764
|
+
}; // Set the height of the plot here};
|
|
765
|
+
// Bitmap depicts the drawn content
|
|
766
|
+
if (nv.drawBitmap === null) {
|
|
767
|
+
Plotly.newPlot("histoplot", [], layout, { responsive: true });
|
|
768
|
+
setROIs([]);
|
|
769
|
+
return;
|
|
770
|
+
} //If ROI (drawing) is not inside the stack
|
|
771
|
+
var min = image.robust_min;
|
|
772
|
+
var max = image.robust_max;
|
|
773
|
+
var samples = {
|
|
774
|
+
1: [],
|
|
775
|
+
2: [],
|
|
776
|
+
3: [],
|
|
777
|
+
4: [],
|
|
778
|
+
5: [],
|
|
779
|
+
6: [],
|
|
780
|
+
7: []
|
|
781
|
+
};
|
|
782
|
+
for (var i = 0; i < nv.drawBitmap.length; i++) {
|
|
783
|
+
//val&7-1 converts to r,g,b index through bit operations
|
|
784
|
+
if (samples[nv.drawBitmap[i]] === undefined) {
|
|
785
|
+
samples[nv.drawBitmap[i]] = [];
|
|
786
|
+
}
|
|
787
|
+
samples[nv.drawBitmap[i]].push(image.img[i]);
|
|
788
|
+
}
|
|
789
|
+
if (nv.hiddenBitmap !== undefined) {
|
|
790
|
+
for (var i = 0; i < nv.hiddenBitmap.length; i++) {
|
|
791
|
+
//val&7-1 converts to r,g,b index through bit operations
|
|
792
|
+
if (samples[nv.hiddenBitmap[i]] === undefined) {
|
|
793
|
+
samples[nv.hiddenBitmap[i]] = [];
|
|
794
|
+
}
|
|
795
|
+
samples[nv.hiddenBitmap[i]].push(image.img[i]);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
var colors = [
|
|
799
|
+
"#bbb",
|
|
800
|
+
"#f00",
|
|
801
|
+
"#0f0",
|
|
802
|
+
"#00f",
|
|
803
|
+
"yellow",
|
|
804
|
+
"cyan",
|
|
805
|
+
"#e81ce8",
|
|
806
|
+
"#e8dbc7",
|
|
807
|
+
];
|
|
808
|
+
Object.keys(samples).forEach(function (_key) {
|
|
809
|
+
var key = Number(_key);
|
|
810
|
+
var sample = samples[key];
|
|
811
|
+
if (sample.length > 0 && key > 0) {
|
|
812
|
+
console.log(key);
|
|
813
|
+
rois.push({
|
|
814
|
+
label: key.toString(),
|
|
815
|
+
alias: mapping[key] ? mapping[key] : key.toString(),
|
|
816
|
+
visibility: nv.getLabelVisibility(Number(key)),
|
|
817
|
+
color: colors[key],
|
|
818
|
+
mu: calculateMean(sample),
|
|
819
|
+
std: calculateStandardDeviation(sample),
|
|
820
|
+
opacity: nv.drawOpacity,
|
|
821
|
+
count: sample.length,
|
|
822
|
+
sample: sample
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
setROIs(rois);
|
|
827
|
+
// plot a histogram of numbers
|
|
828
|
+
var traces = [];
|
|
829
|
+
for (var _i = 0, rois_1 = rois; _i < rois_1.length; _i++) {
|
|
830
|
+
var roi = rois_1[_i];
|
|
831
|
+
// if(roi.visibility){
|
|
832
|
+
traces.push({
|
|
833
|
+
x: roi.sample,
|
|
834
|
+
type: "histogram",
|
|
835
|
+
name: roi.alias,
|
|
836
|
+
opacity: roi.visibility ? 0.5 : 0.1,
|
|
837
|
+
marker: {
|
|
838
|
+
color: roi.color
|
|
839
|
+
},
|
|
840
|
+
autobinx: false,
|
|
841
|
+
xbins: {
|
|
842
|
+
end: max,
|
|
843
|
+
size: (max - min) / 100,
|
|
844
|
+
start: min
|
|
845
|
+
}
|
|
846
|
+
});
|
|
847
|
+
// }
|
|
848
|
+
}
|
|
849
|
+
Plotly.newPlot("histoplot", traces, layout, { responsive: true });
|
|
850
|
+
}
|
|
851
|
+
function nvUpdateSelectionBoxColor(rgb01) {
|
|
852
|
+
setSelectionBoxColor(__spreadArray(__spreadArray([], rgb01, true), [0.5], false));
|
|
853
|
+
nv.setSelectionBoxColor(__spreadArray(__spreadArray([], rgb01, true), [0.5], false));
|
|
854
|
+
}
|
|
855
|
+
var _31 = React.useState("axial"), sliceType = _31[0], setSliceType = _31[1];
|
|
856
|
+
function nvUpdateSliceType(newSliceType) {
|
|
857
|
+
setSliceType(newSliceType);
|
|
858
|
+
if (newSliceType === "axial") {
|
|
859
|
+
nv.setSliceType(nv.sliceTypeAxial);
|
|
860
|
+
}
|
|
861
|
+
else if (newSliceType === "coronal") {
|
|
862
|
+
nv.setSliceType(nv.sliceTypeCoronal);
|
|
863
|
+
}
|
|
864
|
+
else if (newSliceType === "sagittal") {
|
|
865
|
+
nv.setSliceType(nv.sliceTypeSagittal);
|
|
866
|
+
}
|
|
867
|
+
else if (newSliceType === "multi") {
|
|
868
|
+
nv.setSliceType(nv.sliceTypeMultiplanar);
|
|
869
|
+
}
|
|
870
|
+
else if (newSliceType === "3d") {
|
|
871
|
+
nv.setSliceType(nv.sliceTypeRender);
|
|
872
|
+
}
|
|
873
|
+
nvSetDragMode(dragMode); // some Niivue builds reset interaction on slice change
|
|
874
|
+
// Re-apply world/voxel mode and last crosshair after slice type changes
|
|
875
|
+
nv.setSliceMM(worldSpace);
|
|
876
|
+
applySavedCrosshairIfAny();
|
|
877
|
+
}
|
|
878
|
+
function nvUpdateLayerOpacity(a) {
|
|
879
|
+
nv.updateGLVolume();
|
|
880
|
+
}
|
|
881
|
+
function nvUpdateColorMap(id, clr) {
|
|
882
|
+
nv.setColorMap(id, clr);
|
|
883
|
+
var volume = nv.volumes[0];
|
|
884
|
+
setMin(volume.cal_min);
|
|
885
|
+
setMax(volume.cal_max);
|
|
886
|
+
}
|
|
887
|
+
function nvRemoveLayer(imageToRemove) {
|
|
888
|
+
nv.removeVolume(imageToRemove);
|
|
889
|
+
setLayers(__spreadArray([], nv.volumes, true));
|
|
890
|
+
}
|
|
891
|
+
function stylingProxy(nii) {
|
|
892
|
+
if (nii.dim === 2) {
|
|
893
|
+
nvUpdateSliceType("axial");
|
|
894
|
+
setShowCrosshair(false);
|
|
895
|
+
setTextsVisible(false);
|
|
896
|
+
nv.opts.crosshairWidth = 0;
|
|
897
|
+
nv.hideText = true;
|
|
898
|
+
setTimeout(function () {
|
|
899
|
+
nv.setCenteredZoom(0.7);
|
|
900
|
+
}, 300);
|
|
901
|
+
}
|
|
902
|
+
else {
|
|
903
|
+
// nvUpdateSliceType('multi');
|
|
904
|
+
nvUpdateSliceType(sliceType);
|
|
905
|
+
setShowCrosshair(true);
|
|
906
|
+
setTextsVisible(false);
|
|
907
|
+
nv.opts.crosshairWidth = 1;
|
|
908
|
+
nv.hideText = true;
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
var dispatch = useAppDispatch();
|
|
912
|
+
var pipeline = useAppSelector(function (state) { var _a; return (_a = state.result.activeJob) === null || _a === void 0 ? void 0 : _a.pipeline_id; });
|
|
913
|
+
var selectVolume = function (volumeIndex) { return __awaiter(_this, void 0, void 0, function () {
|
|
914
|
+
var openVolume;
|
|
915
|
+
var _this = this;
|
|
916
|
+
return __generator(this, function (_a) {
|
|
917
|
+
openVolume = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
918
|
+
var e_2;
|
|
919
|
+
return __generator(this, function (_a) {
|
|
920
|
+
switch (_a.label) {
|
|
921
|
+
case 0:
|
|
922
|
+
nv.closeDrawing();
|
|
923
|
+
setDrawingChanged(false);
|
|
924
|
+
if (drawingEnabled)
|
|
925
|
+
nvUpdateDrawingEnabled();
|
|
926
|
+
if (props.niis[selectedVolume] !== undefined) {
|
|
927
|
+
nv.removeVolume(niiToVolume(props.niis[selectedVolume]));
|
|
928
|
+
}
|
|
929
|
+
_a.label = 1;
|
|
930
|
+
case 1:
|
|
931
|
+
_a.trys.push([1, 3, , 4]);
|
|
932
|
+
// loadVolumes calls onImageLoaded which does all setup
|
|
933
|
+
return [4 /*yield*/, nv.loadVolumes([niiToVolume(props.niis[volumeIndex])])];
|
|
934
|
+
case 2:
|
|
935
|
+
// loadVolumes calls onImageLoaded which does all setup
|
|
936
|
+
_a.sent();
|
|
937
|
+
// Force a multiplanar view switch to trigger proper rendering, then switch back
|
|
938
|
+
// RJW TODO: fix this horrible hack
|
|
939
|
+
setTimeout(function () {
|
|
940
|
+
nv.setSliceType(nv.sliceTypeMultiplanar);
|
|
941
|
+
nv.resizeListener();
|
|
942
|
+
nv.drawScene();
|
|
943
|
+
// Then switch to the desired slice type
|
|
944
|
+
setTimeout(function () {
|
|
945
|
+
nvUpdateSliceType(sliceType);
|
|
946
|
+
nv.resizeListener();
|
|
947
|
+
nv.drawScene();
|
|
948
|
+
}, 50);
|
|
949
|
+
}, 100);
|
|
950
|
+
return [3 /*break*/, 4];
|
|
951
|
+
case 3:
|
|
952
|
+
e_2 = _a.sent();
|
|
953
|
+
setWarning("Error loading results, please check internet connectivity");
|
|
954
|
+
setWarningOpen(true);
|
|
955
|
+
setTimeout(function () {
|
|
956
|
+
setWarningOpen(false);
|
|
957
|
+
setWarning("");
|
|
958
|
+
}, 2500);
|
|
959
|
+
return [2 /*return*/];
|
|
960
|
+
case 4:
|
|
961
|
+
setSelectedVolume(volumeIndex);
|
|
962
|
+
setSelectedDrawingLayer(null);
|
|
963
|
+
return [2 /*return*/];
|
|
964
|
+
}
|
|
965
|
+
});
|
|
966
|
+
}); };
|
|
967
|
+
// In case that changes has been made
|
|
968
|
+
if (drawingChanged) {
|
|
969
|
+
setWarningConfirmationCallback(function () { return function () {
|
|
970
|
+
saveDrawingLayer(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
971
|
+
return __generator(this, function (_a) {
|
|
972
|
+
switch (_a.label) {
|
|
973
|
+
case 0:
|
|
974
|
+
if (!pipeline) return [3 /*break*/, 2];
|
|
975
|
+
return [4 /*yield*/, dispatch(getPipelineROI({ pipeline: pipeline }))];
|
|
976
|
+
case 1:
|
|
977
|
+
_a.sent();
|
|
978
|
+
_a.label = 2;
|
|
979
|
+
case 2:
|
|
980
|
+
setSaving(false);
|
|
981
|
+
openVolume();
|
|
982
|
+
return [2 /*return*/];
|
|
983
|
+
}
|
|
984
|
+
});
|
|
985
|
+
}); }, function () {
|
|
986
|
+
setSaving(true);
|
|
987
|
+
});
|
|
988
|
+
}; });
|
|
989
|
+
setWarningCancelCallback(function () { return function () {
|
|
990
|
+
openVolume();
|
|
991
|
+
}; });
|
|
992
|
+
setConfirmationOpen(true);
|
|
993
|
+
}
|
|
994
|
+
else
|
|
995
|
+
openVolume();
|
|
996
|
+
return [2 /*return*/];
|
|
997
|
+
});
|
|
998
|
+
}); };
|
|
999
|
+
var _32 = useState(null), selectedROI = _32[0], setSelectedDrawingLayer = _32[1];
|
|
1000
|
+
var _33 = useState(false), saveDialogOpen = _33[0], setSaveDialogOpen = _33[1];
|
|
1001
|
+
var _34 = useState(function (text) { }), saveConfirmCallback = _34[0], setSaveConfirmCallback = _34[1];
|
|
1002
|
+
var _35 = useState(false), confirmationOpen = _35[0], setConfirmationOpen = _35[1];
|
|
1003
|
+
var _36 = useState(function () { }), warningConfirmationCallback = _36[0], setWarningConfirmationCallback = _36[1];
|
|
1004
|
+
var _37 = useState(function () { }), warningCancelCallback = _37[0], setWarningCancelCallback = _37[1];
|
|
1005
|
+
var _38 = useState(false), drawingChanged = _38[0], setDrawingChanged = _38[1];
|
|
1006
|
+
var setLabelAlias = function (label, alias) {
|
|
1007
|
+
labelMapping[label] = alias;
|
|
1008
|
+
setLabelMapping(labelMapping);
|
|
1009
|
+
resampleImage(labelMapping);
|
|
1010
|
+
};
|
|
1011
|
+
var zipAndSendDrawingLayer = function (uploadURL, filename, blob) {
|
|
1012
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1013
|
+
var zip, descriptor, content, file;
|
|
1014
|
+
return __generator(this, function (_a) {
|
|
1015
|
+
switch (_a.label) {
|
|
1016
|
+
case 0:
|
|
1017
|
+
zip = new JSZip();
|
|
1018
|
+
descriptor = {
|
|
1019
|
+
data: [
|
|
1020
|
+
{
|
|
1021
|
+
filename: "".concat(filename, ".nii"),
|
|
1022
|
+
id: 1,
|
|
1023
|
+
name: filename,
|
|
1024
|
+
type: "image",
|
|
1025
|
+
// "numpyPixelType": "complex64",
|
|
1026
|
+
// "pixelType": "complex"
|
|
1027
|
+
labelMapping: labelMapping
|
|
1028
|
+
},
|
|
1029
|
+
]
|
|
1030
|
+
};
|
|
1031
|
+
zip.file("info.json", JSON.stringify(descriptor));
|
|
1032
|
+
zip.file("".concat(filename, ".nii"), blob, { base64: true });
|
|
1033
|
+
return [4 /*yield*/, zip.generateAsync({ type: "blob" })];
|
|
1034
|
+
case 1:
|
|
1035
|
+
content = _a.sent();
|
|
1036
|
+
file = new File([content], filename, {
|
|
1037
|
+
type: content.type,
|
|
1038
|
+
lastModified: Date.now()
|
|
1039
|
+
});
|
|
1040
|
+
// Upload to bucket
|
|
1041
|
+
return [4 /*yield*/, axios.put(uploadURL, file, {
|
|
1042
|
+
headers: {
|
|
1043
|
+
"Content-Type": "application/octet-stream"
|
|
1044
|
+
}
|
|
1045
|
+
})];
|
|
1046
|
+
case 2:
|
|
1047
|
+
// Upload to bucket
|
|
1048
|
+
_a.sent();
|
|
1049
|
+
return [2 /*return*/];
|
|
1050
|
+
}
|
|
1051
|
+
});
|
|
1052
|
+
});
|
|
1053
|
+
};
|
|
1054
|
+
var unzipAndRenderDrawingLayer = function (accessURL) { return __awaiter(_this, void 0, void 0, function () {
|
|
1055
|
+
var response, blob, zip, fileInfo, content, info_1, niiFilePath, niiDrawing, base64;
|
|
1056
|
+
return __generator(this, function (_a) {
|
|
1057
|
+
switch (_a.label) {
|
|
1058
|
+
case 0: return [4 /*yield*/, fetch(accessURL)];
|
|
1059
|
+
case 1:
|
|
1060
|
+
response = _a.sent();
|
|
1061
|
+
// Check if the request was successful
|
|
1062
|
+
if (!response.ok) {
|
|
1063
|
+
props.warn("Failed to load the requested ROI Layer");
|
|
1064
|
+
return [2 /*return*/];
|
|
1065
|
+
}
|
|
1066
|
+
return [4 /*yield*/, response.blob()];
|
|
1067
|
+
case 2:
|
|
1068
|
+
blob = _a.sent();
|
|
1069
|
+
zip = new JSZip();
|
|
1070
|
+
return [4 /*yield*/, zip.loadAsync(blob)];
|
|
1071
|
+
case 3:
|
|
1072
|
+
_a.sent();
|
|
1073
|
+
fileInfo = zip.file("info.json");
|
|
1074
|
+
if (!fileInfo) return [3 /*break*/, 8];
|
|
1075
|
+
return [4 /*yield*/, fileInfo.async("string")];
|
|
1076
|
+
case 4:
|
|
1077
|
+
content = _a.sent();
|
|
1078
|
+
info_1 = JSON.parse(content);
|
|
1079
|
+
niiFilePath = info_1.data[0].filename;
|
|
1080
|
+
niiDrawing = zip.file(niiFilePath);
|
|
1081
|
+
if (!niiDrawing) return [3 /*break*/, 6];
|
|
1082
|
+
return [4 /*yield*/, niiDrawing.async("base64")];
|
|
1083
|
+
case 5:
|
|
1084
|
+
base64 = _a.sent();
|
|
1085
|
+
console.log(niiFilePath);
|
|
1086
|
+
nv.loadDrawingFromBase64(niiFilePath, base64).then(function () {
|
|
1087
|
+
setLabelMapping(info_1.data[0].labelMapping);
|
|
1088
|
+
resampleImage(info_1.data[0].labelMapping);
|
|
1089
|
+
});
|
|
1090
|
+
return [3 /*break*/, 7];
|
|
1091
|
+
case 6:
|
|
1092
|
+
console.log("".concat(niiFilePath, " not found in the ZIP file."));
|
|
1093
|
+
props.warn("".concat(niiFilePath, " not found in the ZIP file."));
|
|
1094
|
+
return [2 /*return*/, null];
|
|
1095
|
+
case 7: return [3 /*break*/, 9];
|
|
1096
|
+
case 8:
|
|
1097
|
+
console.log("info.json not found in the ZIP file.");
|
|
1098
|
+
props.warn("info.json not found in the ZIP file.");
|
|
1099
|
+
return [2 /*return*/, null];
|
|
1100
|
+
case 9: return [2 /*return*/];
|
|
1101
|
+
}
|
|
1102
|
+
});
|
|
1103
|
+
}); };
|
|
1104
|
+
// This is a small fix that prevents the selected roi index from jumping to
|
|
1105
|
+
// the newest saved roi after user has performed a roi reselection during
|
|
1106
|
+
// roi saving
|
|
1107
|
+
var _39 = useState(false), selectedDuringSaving = _39[0], setSelectedDuringSaving = _39[1];
|
|
1108
|
+
var selectDrawingLayer = function (roiIndex) { return __awaiter(_this, void 0, void 0, function () {
|
|
1109
|
+
return __generator(this, function (_a) {
|
|
1110
|
+
switch (_a.label) {
|
|
1111
|
+
case 0:
|
|
1112
|
+
// console.log(nv.drawBitmap);
|
|
1113
|
+
console.log(props.rois[roiIndex].link);
|
|
1114
|
+
return [4 /*yield*/, unzipAndRenderDrawingLayer(props.rois[roiIndex].link)];
|
|
1115
|
+
case 1:
|
|
1116
|
+
_a.sent();
|
|
1117
|
+
setSelectedDrawingLayer(roiIndex);
|
|
1118
|
+
setSelectedDuringSaving(true);
|
|
1119
|
+
setDrawingChanged(false);
|
|
1120
|
+
return [2 /*return*/];
|
|
1121
|
+
}
|
|
1122
|
+
});
|
|
1123
|
+
}); };
|
|
1124
|
+
var unpackROI = function (accessURL) { return __awaiter(_this, void 0, void 0, function () {
|
|
1125
|
+
return __generator(this, function (_a) {
|
|
1126
|
+
switch (_a.label) {
|
|
1127
|
+
case 0: return [4 /*yield*/, unzipAndRenderDrawingLayer(accessURL)];
|
|
1128
|
+
case 1:
|
|
1129
|
+
_a.sent();
|
|
1130
|
+
setDrawingChanged(false);
|
|
1131
|
+
setSelectedDrawingLayer(props.rois.length);
|
|
1132
|
+
return [2 /*return*/];
|
|
1133
|
+
}
|
|
1134
|
+
});
|
|
1135
|
+
}); };
|
|
1136
|
+
var refreshROI = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1137
|
+
var roiIndex, load;
|
|
1138
|
+
return __generator(this, function (_a) {
|
|
1139
|
+
roiIndex = selectedROI;
|
|
1140
|
+
console.log(nv.drawBitmap);
|
|
1141
|
+
if (roiIndex !== null) {
|
|
1142
|
+
load = function (idx) {
|
|
1143
|
+
console.log(props.rois[idx].link);
|
|
1144
|
+
console.trace();
|
|
1145
|
+
nv.loadDrawingFromUrl(props.rois[idx].link).then(function (value) {
|
|
1146
|
+
resampleImage();
|
|
1147
|
+
});
|
|
1148
|
+
setSelectedDrawingLayer(roiIndex);
|
|
1149
|
+
setDrawingChanged(false);
|
|
1150
|
+
};
|
|
1151
|
+
load(roiIndex);
|
|
1152
|
+
}
|
|
1153
|
+
return [2 /*return*/];
|
|
1154
|
+
});
|
|
1155
|
+
}); };
|
|
1156
|
+
var saveDrawingLayer = function (afterSaveCallback, preSaveCallback) {
|
|
1157
|
+
if (preSaveCallback === void 0) { preSaveCallback = function () { }; }
|
|
1158
|
+
var endpoints = getEndpoints();
|
|
1159
|
+
setSaveDialogOpen(true);
|
|
1160
|
+
setSaveConfirmCallback(function () { return function (filename) { return __awaiter(_this, void 0, void 0, function () {
|
|
1161
|
+
var config, response, originalCreateObjectURL, successful;
|
|
1162
|
+
return __generator(this, function (_a) {
|
|
1163
|
+
switch (_a.label) {
|
|
1164
|
+
case 0:
|
|
1165
|
+
preSaveCallback();
|
|
1166
|
+
config = {};
|
|
1167
|
+
return [4 /*yield*/, AuthenticatedHttpClient.post(endpoints.ROI_UPLOAD, {
|
|
1168
|
+
filename: "".concat(filename),
|
|
1169
|
+
pipeline_id: props.pipelineID,
|
|
1170
|
+
type: "image",
|
|
1171
|
+
contentType: "application/octet-stream"
|
|
1172
|
+
}, config)];
|
|
1173
|
+
case 1:
|
|
1174
|
+
response = _a.sent();
|
|
1175
|
+
originalCreateObjectURL = URL.createObjectURL;
|
|
1176
|
+
// Redefine the method
|
|
1177
|
+
URL.createObjectURL = function (blob) {
|
|
1178
|
+
var _this = this;
|
|
1179
|
+
console.log("saving blob");
|
|
1180
|
+
console.log(blob);
|
|
1181
|
+
setSelectedDuringSaving(false);
|
|
1182
|
+
zipAndSendDrawingLayer(response.data.upload_url, filename, blob).then(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
1183
|
+
return __generator(this, function (_a) {
|
|
1184
|
+
switch (_a.label) {
|
|
1185
|
+
case 0:
|
|
1186
|
+
// Update available rois with this callback
|
|
1187
|
+
props.saveROICallback();
|
|
1188
|
+
setDrawingChanged(false);
|
|
1189
|
+
if (!(afterSaveCallback instanceof Function)) return [3 /*break*/, 2];
|
|
1190
|
+
return [4 /*yield*/, afterSaveCallback()];
|
|
1191
|
+
case 1:
|
|
1192
|
+
_a.sent();
|
|
1193
|
+
_a.label = 2;
|
|
1194
|
+
case 2:
|
|
1195
|
+
if (!selectedDuringSaving)
|
|
1196
|
+
//Only switch to the newest roi when user hasn't performed reselection
|
|
1197
|
+
// during the period
|
|
1198
|
+
setSelectedDrawingLayer(props.rois.length);
|
|
1199
|
+
return [2 /*return*/];
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
}); });
|
|
1203
|
+
// Call the original method and return its result
|
|
1204
|
+
return "javascript:void(0);";
|
|
1205
|
+
};
|
|
1206
|
+
successful = nv.saveImage({
|
|
1207
|
+
filename: filename,
|
|
1208
|
+
isSaveDrawing: true
|
|
1209
|
+
});
|
|
1210
|
+
// De-patch
|
|
1211
|
+
URL.createObjectURL = originalCreateObjectURL;
|
|
1212
|
+
return [2 /*return*/];
|
|
1213
|
+
}
|
|
1214
|
+
});
|
|
1215
|
+
}); }; });
|
|
1216
|
+
};
|
|
1217
|
+
var drawToolkitProps = {
|
|
1218
|
+
nv: nv,
|
|
1219
|
+
volumes: props.niis.map(niiToVolume),
|
|
1220
|
+
selectedVolume: selectedVolume,
|
|
1221
|
+
setSelectedVolume: selectVolume,
|
|
1222
|
+
updateDrawPen: nvUpdateDrawPen,
|
|
1223
|
+
drawPen: drawPen,
|
|
1224
|
+
drawingEnabled: drawingEnabled,
|
|
1225
|
+
setDrawingEnabled: nvSetDrawingEnabled,
|
|
1226
|
+
showColorBar: colorBar,
|
|
1227
|
+
toggleColorBar: nvUpdateColorBar,
|
|
1228
|
+
changesMade: drawingChanged,
|
|
1229
|
+
// toggleSampleDistribution,
|
|
1230
|
+
drawUndo: function () {
|
|
1231
|
+
//To be moved and organized
|
|
1232
|
+
nv.drawUndo();
|
|
1233
|
+
resampleImage();
|
|
1234
|
+
},
|
|
1235
|
+
brushSize: brushSize,
|
|
1236
|
+
updateBrushSize: nvUpdateBrushSize,
|
|
1237
|
+
resampleImage: resampleImage,
|
|
1238
|
+
roiVisible: roiVisible,
|
|
1239
|
+
toggleROIVisible: toggleROIVisible,
|
|
1240
|
+
drawingOpacity: drawingOpacity,
|
|
1241
|
+
setDrawingOpacity: nvUpdateDrawingOpacity,
|
|
1242
|
+
setDrawingChanged: setDrawingChanged
|
|
1243
|
+
};
|
|
1244
|
+
return (_jsxs(Box, __assign({ sx: {
|
|
1245
|
+
display: "flex",
|
|
1246
|
+
flexDirection: "column",
|
|
1247
|
+
height: "100%",
|
|
1248
|
+
width: "100%",
|
|
1249
|
+
alignItems: "center",
|
|
1250
|
+
justifyContent: "center"
|
|
1251
|
+
} }, { children: [_jsxs(SettingsPanel, __assign({ open: openSettings, width: 300, toggleMenu: toggleSettings }, { children: [_jsx(ColorPicker, { colorRGB01: backColor, onSetColor: nvUpdateBackColor, title: "Background color" }), _jsx(ColorPicker, { colorRGB01: clipPlaneColor, onSetColor: nvUpdateClipPlaneColor, title: "Clip plane color" }), _jsx(NumberPicker, { value: clipPlaneOpacity, onChange: nvUpdateClipPlaneOpacity, title: "Clip plane opacity", min: 0, max: 1, step: 0.1 }), _jsx(ColorPicker, { colorRGB01: crosshairColor, onSetColor: nvUpdateCrosshairColor, title: "Crosshair color" }), _jsx(NumberPicker, { value: crosshairOpacity, onChange: nvUpdateCrosshairOpacity, title: "Crosshair opacity", min: 0, max: 1, step: 0.1 }), _jsx(ColorPicker, { colorRGB01: selectionBoxColor, onSetColor: nvUpdateSelectionBoxColor, title: "Selection box color" }), _jsx(NumberPicker, { value: nv.opts.crosshairWidth, onChange: nvUpdateCrosshairSize, title: "Crosshair size", min: 0, max: 10, step: 1 }), _jsx(NumberPicker, { value: textSize, onChange: nvUpdateTextSize, title: "Text size", min: 0, max: 0.2, step: 0.01 }), _jsx(ColorPicker, { colorRGB01: rulerColor, onSetColor: nvUpdateRulerColor, title: "Ruler color" }), _jsx(NumberPicker, { value: rulerWidth, onChange: nvUpdateRulerWidth, title: "Ruler thickness", min: 0, max: 10, step: 1 }), _jsx(NumberPicker, { value: rulerOpacity, onChange: nvUpdateRulerOpacity, title: "Ruler opacity", min: 0, max: 1, step: 0.1 }), _jsx(NumberPicker, { value: opacity, onChange: nvUpdateOpacity, title: "Opacity", min: 0, max: 1, step: 0.01 }), _jsx(NumberPicker, { value: drawOpacity, onChange: nvUpdateDrawOpacity, title: "Draw Opacity", min: 0, max: 1, step: 0.01 }), _jsx("label", __assign({ htmlFor: "drawPen" }, { children: "Draw color:" })), _jsxs("select", __assign({ name: "drawPen", id: "drawPen", onChange: nvUpdateDrawPen, defaultValue: drawPen }, { children: [_jsx("option", __assign({ value: "0" }, { children: "Erase" })), _jsx("option", __assign({ value: "1" }, { children: "Red" })), _jsx("option", __assign({ value: "2" }, { children: "Green" })), _jsx("option", __assign({ value: "3" }, { children: "Blue" })), _jsx("option", __assign({ value: "8" }, { children: "Filled Erase" })), _jsx("option", __assign({ value: "9" }, { children: "Filled Red" })), _jsx("option", __assign({ value: "10" }, { children: "Filled Green" })), _jsx("option", __assign({ value: "11" }, { children: "Filled Blue" })), _jsx("option", __assign({ value: "12" }, { children: "Erase Selected Cluster" }))] })), _jsx(Button, __assign({ title: "Save image", onClick: nvSaveImage }, { children: "Save image" })), _jsx(NVSwitch, { checked: locationTableVisible, title: "Location table", onChange: toggleLocationTable }), _jsx(NVSwitch, { checked: drawingEnabled, title: "Enable drawing", onChange: nvUpdateDrawingEnabled }), _jsx(NVSwitch, { checked: orientCube, title: "Orientation cube", onChange: nvUpdateOrientCube }), _jsx(NVSwitch, { checked: ruler, title: "Ruler", onChange: nvUpdateRuler }), _jsx(NVSwitch, { checked: clipPlane, title: "Clip plane", onChange: nvUpdateClipPlane }), _jsx(NVSwitch, { checked: cornerText, title: "Corner text", onChange: nvUpdateCornerText }), _jsx(NVSwitch, { checked: radiological, title: "radiological", onChange: nvUpdateRadiological }), _jsx(NVSwitch, { checked: crosshair3D, title: "3D crosshair", onChange: nvUpdateCrosshair3D }), _jsx(NVSwitch, { checked: colorBar, title: "Show color bar", onChange: nvUpdateColorBar }), _jsx(NVSwitch, { checked: worldSpace, title: "World space", onChange: nvUpdateWorldSpace }), _jsx(NVSwitch, { checked: sagittalNoseLeft, title: "Nose left", onChange: nvUpdateSagittalNoseLeft }), _jsx(NVSwitch, { checked: dragToMeasure, title: "Drag to measure", onChange: nvUpdateDragToMeasure }), _jsx(NVSwitch, { checked: highDPI, title: "High DPI", onChange: nvUpdateHighDPI }), _jsx(NumberPicker, { value: decimalPrecision, onChange: updateDecimalPrecision, title: "Decimal precision", min: 0, max: 8, step: 1 }), _jsx(NumberPicker, { value: multiplanarPadPixels, onChange: nvUpdateMultiplanarPadPixels, title: "Multiplanar padding", min: 0, max: 20, step: 2 }), _jsx(NumberPicker, { value: maxDrawUndoBitmaps, onChange: nvUpdateMaxDrawUndoBitmaps, title: "Max Draw Undos", min: 8, max: 28, step: 1 }), _jsx(NumberPicker, { value: longTouchTimeout, onChange: nvUpdateLongTouchTimeout, title: "Long touch timeout msec", min: 1000, max: 5000, step: 100 }), _jsx(NumberPicker, { value: doubleTouchTimeout, onChange: nvUpdateDoubleTouchTimeout, title: "Double touch timeout msec", min: 500, max: 999, step: 25 })] })), _jsx(LayersPanel, __assign({ open: openLayers, width: 320, onToggleMenu: toggleLayers, onAddLayer: addLayer }, { children: layerList })), _jsx(Toolbar, { nv: nv, nvUpdateSliceType: nvUpdateSliceType, sliceType: sliceType, toggleSettings: toggleSettings, toggleLayers: toggleLayers, volumes: props.niis.map(niiToVolume), selectedVolume: selectedVolume, setSelectedVolume: selectVolume, showColorBar: colorBar, toggleColorBar: nvUpdateColorBar, rois: props.rois, selectedROI: selectedROI, refreshROI: refreshROI, setSelectedROI: selectDrawingLayer, toggleShowCrosshair: nvUpdateCrosshair, showCrosshair: showCrosshair, dragMode: dragMode, setDragMode: nvSetDragMode, toggleRadiological: nvUpdateRadiological, radiological: radiological, saveROI: saveDrawingLayer, complexMode: complexMode, setComplexMode: nvSetDisplayedVoxels, complexOptions: complexOptions, labelsVisible: textsVisible, toggleLabelsVisible: nvToggleLabelVisible, saving: saving, setSaving: setSaving }), _jsx(Confirmation, { name: "New Changes Made", message: "Consider saving your drawing before switching.", open: confirmationOpen, setOpen: setConfirmationOpen, cancellable: true, confirmCallback: warningConfirmationCallback, cancelCallback: warningCancelCallback, cancelText: "Don't save" }), _jsx(CmrEditConfirmation, { name: "Save drawings", message: "Please enter the name of the saved drawing", open: saveDialogOpen, setOpen: setSaveDialogOpen, confirmCallback: saveConfirmCallback, cancellable: true, cancelCallback: function () { },
|
|
1252
|
+
// suffix={'.zip'}
|
|
1253
|
+
defaultText: selectedROI
|
|
1254
|
+
? props.rois[selectedROI] !== undefined
|
|
1255
|
+
? props.rois[selectedROI].filename
|
|
1256
|
+
: undefined
|
|
1257
|
+
: undefined }), props.niis[selectedVolume] !== undefined && (_jsx(NiivuePanel, { nv: nv,
|
|
1258
|
+
// key={`${selectedVolume}`}
|
|
1259
|
+
transformFactors: transformFactors, decimalPrecision: decimalPrecision, locationData: locationData, locationTableVisible: locationTableVisible, pipelineID: props.pipelineID || "", resampleImage: resampleImage, rois: rois, drawToolkitProps: drawToolkitProps, layerList: layerList, mins: boundMins, maxs: boundMaxs, mms: mms, min: min, max: max, setMin: setMin, setMax: setMax, rangeKey: rangeKey, unzipAndRenderROI: unpackROI, zipAndSendROI: zipAndSendDrawingLayer, setLabelAlias: setLabelAlias, gamma: gamma, gammaKey: gammaKey, setGamma: setGamma }))] })));
|
|
1260
|
+
}
|
|
1261
|
+
function niiToVolume(nii) {
|
|
1262
|
+
return {
|
|
1263
|
+
//URL is for NiiVue blob loading
|
|
1264
|
+
url: nii.link,
|
|
1265
|
+
//name is for NiiVue name replacer (needs proper extension like .nii)
|
|
1266
|
+
name: nii.filename.split("/").pop() || nii.filename,
|
|
1267
|
+
//alias is for user selection in toolbar
|
|
1268
|
+
alias: nii.name
|
|
1269
|
+
};
|
|
1270
|
+
}
|