|
1 | 1 | # State Files |
2 | 2 |
|
3 | | -VolView state files save your scene configuration: annotations, camera positions, colormaps, layouts, and more. There are two formats: |
| 3 | +State files save your scene so you can return to your work later or share it with others. They preserve annotations, segmentations, camera positions, colormaps, layouts, and other view settings. |
4 | 4 |
|
5 | | -## Zip State Files (`*.volview.zip`) |
| 5 | +## Saving a Scene |
6 | 6 |
|
7 | | -Save by clicking the "Disk" icon in the toolbar. This embeds your image data that was loaded from local files alongside the application state. Useful for sharing annotations with collaborators. |
| 7 | +Click the **Save** (disk) icon in the toolbar to download a `*.volview.zip` file. Images loaded from local files are included alongside the saved scene. |
8 | 8 |
|
9 | | -## Sparse Manifest Files (`*.volview.json`) |
| 9 | +## Linked State Files |
10 | 10 |
|
11 | | -JSON files that reference remote data via URIs instead of embedding it. Useful for: |
| 11 | +A `*.volview.json` file references data hosted on a server instead of including it in the file. This lets workflows and external applications open a prepared scene without copying large datasets. Anyone opening the scene needs access to the referenced data. |
12 | 12 |
|
13 | | -- Linking to data hosted on servers |
14 | | -- Sharing annotations without duplicating large datasets |
15 | | -- Integrating with external systems (AI pipelines, access control, etc.) |
| 13 | +## Loading a Saved Scene |
16 | 14 |
|
17 | | -## Manifest (version 7.0.0) |
18 | | - |
19 | | -Both formats carry this manifest. A segmentation owns one image's segment masks; |
20 | | -labelmaps encode those masks for storage or interchange. The top-level `segments` |
21 | | -list holds the identities the masks paint and the tools draw with, each mask names |
22 | | -the segment it carries voxels for, and `order` lists the masks of that |
23 | | -segmentation. A mask `order` leaves out is skipped on restore. `selectedSegment` |
24 | | -names the segment that was selected. |
25 | | - |
26 | | -A segment has a `name` and an RGBA `color`. It may also state `visible` and |
27 | | -`locked`, which default to `true` and `false`, and `fillOpacity`, `outlineOpacity` |
28 | | -and `strokeWidth`, which fall back to the app defaults. A segmentation may state |
29 | | -the `fillOpacity`, `outlineOpacity` and `outlineThickness` of the image's Display |
30 | | -settings. Rulers, rectangles and polygons under `tools` name their segment with |
31 | | -`segmentId`. |
32 | | - |
33 | | -A segment the file lists takes over an existing segment of the same name that |
34 | | -holds no masks or shapes yet, such as one a configuration defined. If that |
35 | | -segment already holds content, the restored one gets a numbered name like |
36 | | -`Tumor (2)`. |
37 | | - |
38 | | -A mask saved into a zip names its own archive entry with `path`. A sparse |
39 | | -manifest instead points at a whole label volume: `segmentationArtifacts` names |
40 | | -that volume, its `dataSourceId` says where the bytes come from, and each mask |
41 | | -whose `artifactId` points at it is filled from the `sourceValue` it declares, 1 |
42 | | -when omitted. |
43 | | -An artifact is a single-component label volume; one with several components is |
44 | | -skipped on restore. Extents are placeholders until the volume is read. A value |
45 | | -no mask reads, including every value of a volume no mask points at, gets its |
46 | | -segment the way loading that volume on its own would: it joins an existing |
47 | | -segment of its name, even one holding content on another image, unless that |
48 | | -segment already has a mask on this image, in which case the value gets a new |
49 | | -segment with a numbered name. |
50 | | - |
51 | | -```json |
52 | | -{ |
53 | | - "version": "7.0.0", |
54 | | - "dataSources": [ |
55 | | - { "id": 0, "type": "uri", "uri": "https://example.com/scan.zip" }, |
56 | | - { "id": 1, "type": "uri", "uri": "https://example.com/segmentation.nii.gz" } |
57 | | - ], |
58 | | - "segments": [ |
59 | | - { |
60 | | - "id": "segment-tumor", |
61 | | - "name": "Tumor", |
62 | | - "color": [255, 0, 0, 255], |
63 | | - "visible": true, |
64 | | - "locked": false |
65 | | - } |
66 | | - ], |
67 | | - "segmentations": [ |
68 | | - { |
69 | | - "id": "segmentation-0", |
70 | | - "name": "Tumor Segmentation", |
71 | | - "parentImage": "0", |
72 | | - "masks": [ |
73 | | - { |
74 | | - "id": "mask-tumor", |
75 | | - "segmentId": "segment-tumor", |
76 | | - "representations": { |
77 | | - "labelmap": { |
78 | | - "artifactId": "labelmap-1", |
79 | | - "sourceValue": 1, |
80 | | - "extent": [0, -1, 0, -1, 0, -1] |
81 | | - } |
82 | | - } |
83 | | - } |
84 | | - ], |
85 | | - "order": ["mask-tumor"] |
86 | | - } |
87 | | - ], |
88 | | - "segmentationArtifacts": [ |
89 | | - { |
90 | | - "id": "labelmap-1", |
91 | | - "parentImage": "0", |
92 | | - "name": "Tumor Segmentation", |
93 | | - "dataSourceId": 1 |
94 | | - } |
95 | | - ], |
96 | | - "selectedSegment": "segment-tumor", |
97 | | - "tools": { |
98 | | - "rectangles": { |
99 | | - "tools": [ |
100 | | - { |
101 | | - "imageID": "0", |
102 | | - "frameOfReference": { |
103 | | - "planeNormal": [0, 0, 1], |
104 | | - "planeOrigin": [0, 0, 50] |
105 | | - }, |
106 | | - "slice": 50, |
107 | | - "firstPoint": [-20, -20, 50], |
108 | | - "secondPoint": [20, 20, 50], |
109 | | - "segmentId": "segment-tumor" |
110 | | - } |
111 | | - ] |
112 | | - } |
113 | | - } |
114 | | -} |
115 | | -``` |
116 | | - |
117 | | -## Legacy 6.x manifest (still read on import) |
118 | | - |
119 | | -Manifests up to version 6.4.0, such as this 6.2.0 one, are migrated on load: the |
120 | | -historical `segmentGroups` field becomes the current segmentation model, and the |
121 | | -per-tool `labels` records become segments the tools reference by id. Nothing |
122 | | -writes this form any more. |
123 | | - |
124 | | -```json |
125 | | -{ |
126 | | - "version": "6.2.0", |
127 | | - "dataSources": [ |
128 | | - { "id": 0, "type": "uri", "uri": "https://example.com/scan.zip" }, |
129 | | - { "id": 1, "type": "uri", "uri": "https://example.com/segmentation.nii.gz" } |
130 | | - ], |
131 | | - "segmentGroups": [ |
132 | | - { |
133 | | - "id": "seg-1", |
134 | | - "dataSourceId": 1, |
135 | | - "metadata": { |
136 | | - "name": "Tumor Segmentation", |
137 | | - "parentImage": "0", |
138 | | - "segments": { |
139 | | - "order": [1], |
140 | | - "byValue": { |
141 | | - "1": { "value": 1, "name": "Tumor", "color": [255, 0, 0, 255] } |
142 | | - } |
143 | | - } |
144 | | - } |
145 | | - } |
146 | | - ], |
147 | | - "tools": { |
148 | | - "rectangles": { |
149 | | - "tools": [ |
150 | | - { |
151 | | - "imageID": "0", |
152 | | - "frameOfReference": { |
153 | | - "planeNormal": [0, 0, 1], |
154 | | - "planeOrigin": [0, 0, 50] |
155 | | - }, |
156 | | - "slice": 50, |
157 | | - "firstPoint": [-20, -20, 50], |
158 | | - "secondPoint": [20, 20, 50], |
159 | | - "label": "lesion" |
160 | | - } |
161 | | - ], |
162 | | - "labels": { |
163 | | - "lesion": { "color": "red" } |
164 | | - } |
165 | | - } |
166 | | - } |
167 | | -} |
168 | | -``` |
169 | | - |
170 | | -## Loading State Files |
171 | | - |
172 | | -- **Drag and drop** onto VolView |
173 | | -- **File browser** via the "Folder" icon below the save button |
174 | | -- **URL parameter**: `?urls=[https://example.com/session.volview.json]` |
| 15 | +- Drag and drop a state file onto VolView. |
| 16 | +- Click the **Load** (folder) icon in the toolbar and select a state file. |
| 17 | +- Open a link that includes a state file in the `urls` parameter, such as `?urls=[https://example.com/session.volview.json]`. |
0 commit comments