{"id":18736699,"url":"https://github.com/digitalslidearchive/girder_volview","last_synced_at":"2025-04-12T19:31:47.227Z","repository":{"id":115327635,"uuid":"596345509","full_name":"DigitalSlideArchive/girder_volview","owner":"DigitalSlideArchive","description":null,"archived":false,"fork":false,"pushed_at":"2025-04-03T17:53:43.000Z","size":205,"stargazers_count":3,"open_issues_count":6,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-03T18:36:25.365Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DigitalSlideArchive.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-02T01:18:42.000Z","updated_at":"2025-04-03T17:43:52.000Z","dependencies_parsed_at":"2023-12-11T22:56:10.919Z","dependency_job_id":"25035f7b-328c-4fe4-9fd0-18b2b1a5bca6","html_url":"https://github.com/DigitalSlideArchive/girder_volview","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DigitalSlideArchive%2Fgirder_volview","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DigitalSlideArchive%2Fgirder_volview/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DigitalSlideArchive%2Fgirder_volview/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DigitalSlideArchive%2Fgirder_volview/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DigitalSlideArchive","download_url":"https://codeload.github.com/DigitalSlideArchive/girder_volview/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248621131,"owners_count":21134753,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T15:22:10.537Z","updated_at":"2025-04-12T19:31:47.220Z","avatar_url":"https://github.com/DigitalSlideArchive.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Girder Plugin for VolView\n\nOpen Items in [VolView](https://github.com/Kitware/VolView) with a \"Open in VolView\" button. The button is located in the top right, on an Item's page.\n\n## Supported Files\n\nVolView tries to load all files in a Girder Item.\n`.zip` files, and all `.zip` files they contain, are unzipped and VolView will load all resulting files.\n\n### Supported Image File Formats\n\n- DICOM `.dcm`\n- Nrrd `.nrrd`\n- NIFTI `.nii`\n- VTK image `.vti`\n- And many more. Try dragging and dropping the file(s) on the [VolView Demo Site](https://volview.netlify.app/)\n\n## Layers of Images\n\nTo overlay PET and CT images, place all image files in one Girder Item.\nVolView will show the PET and CT images as separate \"volumes\".\nFirst load the base volume, say the CT one. Then click the \"Add Layer\" icon on the overlay image, probably the PET one.\n\nThe overlaid image is \"resampled\" to match the physical and pixel space of the base image.  \nIf there is no overlap in physical space as gleaned from the images' metadata, the overlay won't work.\n\n## Client Configuration file\n\nAdd a `.volview_config.yaml` file higher in the folder hierarchy. Example file:\n\n```yml\nlayout:\n  activeLayout: \"Axial Only\"\nlabels:\n  defaultLabels:\n    artifact:\n      color: \"gray\"\n      strokeWidth: 3\n    needs-review:\n      color: \"#FFBF00\"\n```\n\nTo merge with `.volview_config.yaml`s higher in the folder hierarchy, include `__inherit__: true`\nin the child `.volview_config.yaml` file. Example:\n\nChild `.volview_config.yaml`\n\n```yml\n__inherit__: true\nshortcuts:\n  polygon: \"Ctrl+p\"\n  rectangle: \"b\"\n```\n\nParent `.volview_config.yaml`\n\n```yml\nlayout:\n  activeLayout: \"Axial Only\"\n```\n\nResult\n\n```yml\nshortcuts:\n  polygon: \"Ctrl+p\"\n  rectangle: \"b\"\nlayout:\n  activeLayout: \"Axial Only\"\n```\n\n### Layout Configuration\n\nTo set the initial view, add a `layout: activeLayout` section to the `.volview_config.yaml` file.\n\n```yml\nlayout:\n  # options: Axial Only, Axial Primary, 3D Primary, Quad View, 3D Only\n  activeLayout: \"Axial Only\"\n```\n\n### Label Configuration\n\nTo assign labels and their properties, add a `.volview_config.yaml` file higher in the folder hierarchy.  \nExample `.volview_config.yaml` file:\n\n```yml\n# defaultLabels are shared by polygon, ruler and rectangle tool\nlabels:\n  defaultLabels:\n    artifact:\n      color: \"gray\"\n      strokeWidth: 3\n    needs-review:\n      color: \"#FFBF00\"\n```\n\nLabels can be configured per tool:\n\n```yml\nlabels:\n  rectangleLabels:\n    lesion: # label name\n      color: \"#ff0000\"\n      fillColor: \"transparent\"\n    innocuous:\n      color: \"white\"\n      fillColor: \"#00ff0030\"\n    tumor:\n      color: \"green\"\n      fillColor: \"transparent\"\n\n  rulerLabels:\n    big:\n      color: \"#ff0000\"\n    small:\n      color: \"white\"\n```\n\nLabel sections could be empty to disable labels for a tool.\n\n```yml\nlabels:\n  rulerLabels:\n\n  rectangleLabels:\n    lesion:\n      color: \"#ff0000\"\n      fillColor: \"transparent\"\n    innocuous:\n      color: \"white\"\n      fillColor: \"#00ff0030\"\n```\n\n### Keyboard Shortcuts Configuration\n\nConfigure the keys to activate tools, change selected labels, and more.\nNames for shortcut actions are in [constants.ts](https://github.com/Kitware/VolView/blob/main/src/constants.ts#L53) are under the `ACTIONS` variable.\n\nTo configure a key for an action, add its action name and the key(s) under the `shortcuts` section. For key combinations, use `+` like `Ctrl+f`.\n\n```yml\nshortcuts:\n  polygon: \"Ctrl+p\"\n  rectangle: \"b\"\n```\n\nIn VolView, show a dialog with the configured keyboard shortcuts by pressing the `?` key.\n\n### Saved Segment Group File Format\n\nEdited segment groups are saved as separate files within session.volview.zip files.  By default the segment group file format is `nii.gz`.  Recommended formats: `nrrd`, `nii`, `nii.gz`\n\n```yml\nio:\n  segmentGroupSaveFormat: \"nii.gz\" # default is nii.gz\n```\n\n### Automatic Segment Groups by File Name\n\nWhen loading files, VolView can automatically convert images to segment groups\nif they follow a naming convention. For example, an image with name `foo.seg.bar`\nwill be converted to a segment group for a base image named `foo.baz`.  \nThe `seg` extension is defined by the `io.segmentGroupExtension` key, which takes a\nstring. Files `[baseFileName].[segmentGroupExtension].bar` will be automatically converted to\nsegment groups for a base image named `[baseFileName].baz`. The default is `'seg'`.\n\nThis will define `myFile.seg.nrrd` as a segment group for a `myFile.nii` base file.\n\n```yml\nio:\n  segmentGroupExtension: \"seg\" # \"seg\" is the default\n```\n\nFor multiple segmentation images, the first part of the file name up until the first `.` is what is used to match base + segmentation images. For example, this group of file names will match: `my-study.nii`, `my-study.foo.seg.nii`, `my-study.bar.seg.nii`\n\n### Default Window Level\n\nWill force the window level for all loaded volumes.\n\n```yml\nwindowing:\n  level: 100\n  width: 50\n```\n\n## Table View via Grider Plugin Configuration File\n\n![image](https://github.com/DigitalSlideArchive/girder_volview/assets/16823231/9ab0f04d-9103-431a-ab22-cbf87ee760e2)\n\nTo show DICOM tags in a table view, add a `.large_image_config.yaml` file higher in the Girder folder hierarchy. When a DICOM file is imported/uploaded, its DICOM tags are saved on the Item metadata under the top level `dicom` key.\n\nMore information on `.large_image_config.yaml` here:\nhttps://girder.github.io/large_image/girder_config_options.html#large-image-config-yaml\n\nExample `.large_image_config.yaml` file:\n\n```yml\n# If present, show a table with column headers in item lists\nitemList:\n  # Show these columns in order from left to right.  Each column has a\n  # \"type\" and \"value\".  It optionally has a \"title\" used for the column\n  # header, and a \"format\" used for searching and filtering.  The \"label\",\n  # if any, is displayed to the left of the column value.  This is more\n  # useful in an grid view than in a column view.\n  columns:\n    - # The \"record\" type is from the default item record.  The value is\n      # one of \"name\", \"size\", or \"controls\".\n      type: record\n      value: name\n    - type: record\n      value: size\n    - # The \"metadata\" type is taken from the item's \"meta\" contents.  It\n      # can be a nested key by using dots in its name.\n      type: metadata\n      value: dicom.Modality\n      title: Modality\n    - type: metadata\n      value: dicom.BodyPartExamined\n      title: Body Part Examined\n    - type: metadata\n      value: dicom.StudyDate\n      title: Study Date\n    - type: metadata\n      value: dicom.StudyDescription\n      title: Study Description\n    - type: metadata\n      value: dicom.SeriesDescription\n      title: Series Description\n    - type: metadata\n      value: dicom.ManufacturerModelName\n      title: Manufacturer Model Name\n    - type: metadata\n      value: dicom.StudyInstanceUID\n      title: Study Instance UID\n    - type: metadata\n      value: dicom.SeriesInstanceUID\n      title: Series Instance UID\n```\n\n## Speedup S3 file downloading by disabling proxying\n\nThe VolView plugin proxies request to download files from S3 by default.\nThis avoids a CORS error when loading a file from an S3 bucket asset store without CORS configuration.\nTo speed up downloading of files from S3, the Girder admin can:\n\n1. [Configure CORS](https://girder.readthedocs.io/en/stable/user-guide.html#s3) in the S3 bucket for the Girder server.\n2. Change the global [Girder configuration](https://girder.readthedocs.io/en/stable/configuration.html) to add\n   a `[volview]` section with a `proxy_assetstores = False` option. See below:\n\n```\n[volview]\n# Workaround CORS configuration errors in S3 assetstores.\n# If True, the Girder server will proxy file download requests from\n# VolView clients to the S3 assetstore. This will use more server bandwidth.\n# If False, VolView client requests to download files are redirected to S3.\n# Defaults to True.\nproxy_assetstores = False\n```\n\n3. Configure AWS Cloudfront for the S3 bucket to support HTTP/2 connections\n\n## API Endpoints\n\n- GET folder/:id/volview?items=[itemIds]\u0026folders=[folderIds] -\u003e download JSON with URLS to files or the latest `*.volview.zip` file in the folder\n- GET item/:id/volview -\u003e download JSON with URLs to all files in item or the latest `*.volview.zip` file\n- POST item/:id/volview -\u003e upload file to Item with cookie authentication\n- GET file/:id/proxiable/:name -\u003e download a file with option to proxy\n- GET folder/:id/volview_config/:name -\u003e download JSON with VolView config properties\n- Deprecated: GET item/:id/volview/datasets -\u003e download all files in item except the `*.volview.zip`\n\n## Example Saving Roundtrip flow\n\n### Open Item\n\n1. User clicks Open in VolView for Item - Plugin checks if `*volview.zip` file exists in Item, finds none:\n   Opens VolView with file download url `item/:id/volview/datasets`\n1. VolView opens, fetches from `item/:id/volview/datasets`, receives zip of all files in Item except files ending in `*volview.zip`\n1. In VolView, User clicks the Save button - VolView POSTs session.volview.zip to `item/:id/volview`\n1. girder_volview plugin saves new session.volview.zip in Item.\n1. User clicks Open in VolView for Item - Plugin finds a `*volview.zip` in the Item. Opens VolView with file download URL pointing to `item/:id/volview`\n1. VolView opens, fetches from `item/:id/volview`, receives most recently created `*volview.zip` file in Item.\n\nVolView creates a new session.volview.zip file in the Girder Item every time the Save button is clicked.\n\n### Open Checked\n\n1. User checks a set of items or folders. Clicks \"Open Checked in VolView\".\n1. Browser client updates the `lastOpened` metadata on a checked item/folder metadata with the current time.\n1. Browser opens VolView with file download url pointing to `GET folder/:id/volview?items=[...ids]\u0026folders=[...ids]`. That endpoint returns a JSON file with URLs to Girder files.\n1. VolView save URL is pointing to `PUT folder/:id/volview?metadata={items: [...ids], folders: [...ids]}`. `metadata` parameter matches the checked set in the Girder file browser. User clicks save. `session.volview.zip` item is created in the folder with a `linkedResources` metadata key holding the folder and item IDs. If user checked a session.volview.zip item, then `items` points to an existing session.volview.zip. The new session.volview.zip takes the `linkedResources` of the older session.volview.zip.\n1. If user clicks refresh in VolView, the `GET folder/:id/volview?items=[...ids]\u0026folders=[...ids]` end point is hit again. If a session.volview.zip is in the `items` parameter, the plugin reads the volview.zip's `linkedResources` and searches for a newer session.volview.zips with matching `linkedResources` and returns that if found.\n1. If user checks a new set of folders or items that does not include a session.volview.zip item, the `GET folder/:id/volview` endpoint does not pick a session.volview.zip with matching `linkedResources` as `lastOpened` metadata on one of the checked items/folders is newer than the matching session.volview.zip. This allows opening of images with a clean slate.\n\n## Development\n\nGet this running https://github.com/DigitalSlideArchive/digital_slide_archive/tree/master/devops/with-dive-volview\n\nIn the `provision.divevolview.yaml` file, add some `volumes` pointing to this girder plugin and optionally\na VolView repo checkout. Example:\n\n```yaml\nservices:\n  girder:\n    volumes:\n      - ../with-dive-volview/provision.divevolview.yaml:/opt/digital_slide_archive/devops/dsa/provision.yaml\n      - ../../../girder-volview:/opt/girder_volview\n      - ~/src/volview-stuff/VolView:/opt/volview-package\n```\n\nComment out the pip install of this plugin here: https://github.com/DigitalSlideArchive/digital_slide_archive/blob/master/devops/with-dive-volview/provision.divevolview.yaml#L3\n\nTo install volume mapped girder-volview plugin and incorporate changes as files are edited, add this to the `shell` section of the provision.yaml:\n\n```yaml\nshell:\n  - cd /opt/girder_volview/ \u0026\u0026 pip install -e .\n  - (sleep 30 \u0026\u0026 girder build --dev --watch-plugin volview)\u0026\n```\n\n### Develop VolView client\n\nChange the directory the Webpack copy plugin pulls from to your mounted volume with local VolView build\nIn here: https://github.com/PaulHax/girder_volview/blob/main/girder_volview/web_client/webpack.helper.js#L9-L14\n\n```js\nnew CopyWebpackPlugin([\n  {\n    from: \"/opt/volview-package/dist\",\n    to: config.output.path,\n    toType: \"dir\",\n  },\n]);\n```\n\nThen build VolView with the right flags:\nhttps://github.com/PaulHax/girder_volview/blob/main/volview-girder-client/buildvolview.sh#L14C2-L14C108\n\n```\nVITE_ENABLE_REMOTE_SAVE=true npm run build -- --base=/static/built/plugins/volview\n```\n\n### VolView Client Update Steps\n\nChange VolView commit SHA in `volview-girder-client/buildvolview.sh`\n\nBuild VolView client with Girder specific CLI arguments:\n\n```sh\ncd volview-girder-client\nsource buildvolview.sh\n```\n\nIncrease version in `volview-girder-client/package.json`.\n\nPublish built VolView `dist` directory to NPM:\n\n```sh\ncd volview-girder-client\nnpm publish\n```\n\nUpdate volview-girder-client version in `./grider_volview/web_client/package.json`\n\nTo test new client: push up changes to a new branch on GitHub. Change `provision.divevolview.yaml` to point to your branch like this: `git+https://github.com/PaulHax/girder_volview@new-branch`.\nRebuild DSA Girder docker image.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalslidearchive%2Fgirder_volview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigitalslidearchive%2Fgirder_volview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalslidearchive%2Fgirder_volview/lists"}