pyosirix


Namepyosirix JSON
Version 0.2.1b4 PyPI version JSON
download
home_pageNone
SummaryPythonic interface for interacting with Osirix through a gRPC protocol
upload_time2024-06-14 22:29:13
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseCopyright (c) 2024 Matthew D Blackledge, Timothy Sum Hon Mun, and The Institute of Cancer Research Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords artificial intelligence dicom image processing medical imaging
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # pyOsiriX

![Welcome to pyOsiriX!](https://raw.githubusercontent.com/osirixgrpc/osirixgrpc/dev/docs/docs/assets/logo/logo-python.png)

[![Powered By gRPC](https://img.shields.io/badge/powered_by-gRPC-green?labelColor=red)](https://grpc.io)
[![GitHub License](https://img.shields.io/github/license/osirixgrpc/osirixgrpc?color=blue)](https://github.com/osirixgrpc/osirixgrpc/blob/main/LICENSE)
![PyPI - Downloads](https://img.shields.io/pypi/dm/pyosirix)
[![Static Badge](https://img.shields.io/badge/issues-pyosirix-red?logo=github)](https://github.com/osirixgrpc/osirixgrpc/issues)
[![Static Badge](https://img.shields.io/badge/citation-AI2ASE-green?logo=googlescholar)](https://ai-2-ase.github.io/papers/29%5cCameraReady%5cAAAI_OsiriXgrpc__Rapid_prototyping_and_development_of_state_of_the_art_artificial_intelligence_in_OsiriX_cam_ready.pdf)

pyOsiriX provides a pythonic interface to the [OsiriXgrpc plugin](https://osirixgrpc.github.io/osirixgrpc/index.html) 
for the OsiriX medical image viewing platform. Our vision is to accelerate the development of robust research image 
processing tools for the medical community, including straight-forward deployment of AI algorithms.

Example functionality includes:

 1. Interrogating metadata of studies/series/imaging included within the OsiriX database.
 2. Accessing and adjusting pixel values within a 2D OsiriX viewer.
 3. Adjusting visualization settings of 3D volume rendering windows.
 4. Obtaining and creating regions of interest (ROIs) within image viewing windows.

## Installation
```
pip install -i https://pypi.org/simple/ --extra-index-url https://test.pypi.org/simple/ pyosirix==0.2.1-beta4
```

## Requirements
 - [`osirixgrpc`](https://pypi.org/project/osirixgrpc/)
 - [`numpy`](https://pypi.org/project/numpy/)

## Contributions
If you would like to contribute to pyOsiriX, please have a look at our 
[contributing](https://osirixgrpc.github.io/osirixgrpc/contributing/CONTRIBUTING.html) page. We are always eager to hear
your ideas and improve pyOsiriX. Examples include:

 1. Publishing example scripts of pyOsiriX in use. For example, something small that helps your day-to-day workflows.
 2. Editing documentation or suggesting changes.
 3. Reporting any bugs you find by [raising an issue](https://github.com/osirixgrpc/osirixgrpc/issues).
 4. Testing new version of pyOsiriX (and OsiriXgrpc!) prior to release.
 5. Contributing to or suggesting changes to the whole project, including requests for more OsiriX function exposure.

Please contact us at [osirixgrpc@gmail.com](mailto:osirixgrpc@gmail.com) to find out more.

## Examples of use
__Note__: These are for exemplary use only and just touch on what is capable with OsiriXgrpc. Over time we will compile 
a list of more complete examples as found in the [documentation](https://osirixgrpc.github.io/osirixgrpc/pyosirix).

### Accessing the 2D viewer
If 2D OsiriX viewers are open, it is possible to obtain its instance by simply running: 
```python
import osirix
displayed_viewers = osirix.displayed_2d_viewers()  # Returns a list of all open viewers
frontmost_viewer = osirix.frontmost_viewer()  # Returns the viewer that is currently active (red frame)
```

### Accessing image data
It is straightforward to obtain image data within the 2D viewer and manipulate it. The following doubles the pixel 
values of the currently displayed image.
```python
import osirix
frontmost_viewer = osirix.frontmost_viewer()
pixels = frontmost_viewer.cur_dcm().image  # Obtain pixel data (as 2D NumPy array) from currently displayed image slice.
new_pixels = pixels * 2  # Manipulate the array
frontmost_viewer.cur_dcm().image = new_pixels  # Update the image data for the currently shown image slice.
frontmost_viewer.needs_display_update()  # Tell OsiriX to redraw itself
```

### Accessing (all) image data
Images in the viewer are stored in arrays, one array per frame, each array having the same length as the number of 
displayed slices. The following does the same as the example above, but applies to all images in the viewer.
```python
import osirix
frontmost_viewer = osirix.frontmost_viewer()
pix_list = frontmost_viewer.pix_list(0)  # Obtain an array of DCMPix objects for the first (zeroth) frame. 
for pix in pix_list:  # Loop through all DCMPix
    pixels = pix.image
    new_pixels = pixels * 2  # Manipulate the array
    pix.image = new_pixels
frontmost_viewer.needs_display_update()  # Tell OsiriX to redraw itself
```

### Accessing ROIs
Similarly to images, ROIs can be obtained as an array for each requested frame in the 2D OsiriX viewer. Each element of 
the array is another array, containing however, many ROIs are on that slice (some may be empty). This will produce a 
list of unique ROI names in the viewer.
```python
import osirix
frontmost_viewer = osirix.frontmost_viewer()
roi_list = frontmost_viewer.roi_list(0)  # ROI list for the first (zeroth) frame.
unique_names = []  # Empty storage
for roi_slice in roi_list:
    for roi in roi_slice:  # There may be more than one ROI in a slice!
        if roi.name not in unique_names:  # You could also use numpy.unique...  
            unique_names.append(roi.name)
if len(unique_names) == 0:
    print("No ROIs found in the viewer!")
else:
    print(f"Unique names are: {unique_names}")
```

### Accessing ROIs by name
If you know the name of the ROI it is easy to avoid looping through
```python
import osirix
frontmost_viewer = osirix.frontmost_viewer()
roi_name = "my_perfect_roi"
rois = frontmost_viewer.rois_with_name(roi_name)
print(f"Number of ROIs with name {roi_name}: {len(rois)}")
```

### Converting an ROI to a mask
Another useful thing to do is obtain a mask (a 2D array of boolean values) representing the region of the ROI. To do
this you need a DCMPix instance to compute it from. Luckily, this is easy to obtain!
```python
import osirix
import numpy as np
frontmost_viewer = osirix.frontmost_viewer()
roi_name = "my_perfect_roi"
rois = frontmost_viewer.rois_with_name(roi_name)
if len(rois) == 0:
    raise ValueError(f"Could not find any ROIs with the name {roi_name}")
voxels = []  # Storage
for roi in rois:
    pix = roi.pix  # The DCMPix on which the ROI was drawn
    mask = pix.get_map_from_roi(roi)  # The mask we wanted.
    voxels = np.r_[pix.image[mask], voxels]  # Append the voxel values
mean = np.mean(voxels)  # Let's get some statistics
std = np.std(voxels, ddof=1)
print(f"ROIs with name {roi_name} have mean {mean:.2f} and std-dev {std: .2f}") 
```

### Accessing Dicom files in the OsiriX database
It is possible to get access to the selected series and studies in the OsiriX database. This example sorts the 
DicomImages in the first selected DicomSeries by slice location and then opens them in a new 2D viewer.
```python
import osirix
import numpy as np
browser_controller = osirix.current_browser()  #The main window (database) of OsiriX
studies, series = browser_controller.database_selection()  # User selection as lists of DicomStudy/DicomSeries
if len(series) == 0:
    raise ValueError("No series have been selected")
dicom_images = np.array(series[0].images)  # An array of DicomImage instances
sorted_idx = np.argsort([image.slice_location for image in dicom_images])  # Sort the images by slice location
dicom_images = dicom_images[sorted_idx]
viewer_controller = browser_controller.open_viewer_2d(dicom_images)  # Open up and view
```

### Accessing the VRController
Once a user has opened a VRController (or done so programmatically via pyOsiriX!), it is possible to access it as per
the 2D viewer. This example shows this and also how to make the contained ROIVolumes display themselves.
```python
import osirix
frontmost_viewer = osirix.frontmost_viewer()
vr_controllers = frontmost_viewer.vr_controllers()  # Get a list of currently open ones.
if len(vr_controllers) == 0:
    print("No open VR Controller.  Creating one.")
    vr_controller = frontmost_viewer.open_vr_viewer(mode="MIP")  # Only other alternative is "VR"
else:
    vr_controller = vr_controllers[0]
roi_volumes = vr_controller.roi_volumes()
if len(roi_volumes) == 0:
    print("No valid ROI volumes available")  # Note that ROIs defined on a single slice do not count!
for roi_volume in roi_volumes:
    print(f"Displaying ROI volume with name {roi_volume.name} and modifying is attributes")
    roi_volume.visible = True
    roi_volume.color = (1., 0., 1.)  # Purple color in unit RGB space
    roi_volume.opacity = 0.5
    roi_volume.texture = False  # Generally looks better to us
```
            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "pyosirix",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "Matthew D Blackledge <mattyblackledge@gmail.com>",
    "keywords": "Artificial Intelligence, Dicom, Image Processing, Medical Imaging",
    "author": null,
    "author_email": "Matthew D Blackledge <mattyblackledge@gmail.com>, Timothy Sum Hon Mun <timothy22000@gmail.com>, Richard Holbrey <richard.holbrey@icr.ac.uk>",
    "download_url": "https://files.pythonhosted.org/packages/eb/7c/1711db0cbf606819ea9cd85798fc3da2c2d91fc88e7ebb6a4a546b566caa/pyosirix-0.2.1b4.tar.gz",
    "platform": null,
    "description": "# pyOsiriX\n\n![Welcome to pyOsiriX!](https://raw.githubusercontent.com/osirixgrpc/osirixgrpc/dev/docs/docs/assets/logo/logo-python.png)\n\n[![Powered By gRPC](https://img.shields.io/badge/powered_by-gRPC-green?labelColor=red)](https://grpc.io)\n[![GitHub License](https://img.shields.io/github/license/osirixgrpc/osirixgrpc?color=blue)](https://github.com/osirixgrpc/osirixgrpc/blob/main/LICENSE)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/pyosirix)\n[![Static Badge](https://img.shields.io/badge/issues-pyosirix-red?logo=github)](https://github.com/osirixgrpc/osirixgrpc/issues)\n[![Static Badge](https://img.shields.io/badge/citation-AI2ASE-green?logo=googlescholar)](https://ai-2-ase.github.io/papers/29%5cCameraReady%5cAAAI_OsiriXgrpc__Rapid_prototyping_and_development_of_state_of_the_art_artificial_intelligence_in_OsiriX_cam_ready.pdf)\n\npyOsiriX provides a pythonic interface to the [OsiriXgrpc plugin](https://osirixgrpc.github.io/osirixgrpc/index.html) \nfor the OsiriX medical image viewing platform. Our vision is to accelerate the development of robust research image \nprocessing tools for the medical community, including straight-forward deployment of AI algorithms.\n\nExample functionality includes:\n\n 1. Interrogating metadata of studies/series/imaging included within the OsiriX database.\n 2. Accessing and adjusting pixel values within a 2D OsiriX viewer.\n 3. Adjusting visualization settings of 3D volume rendering windows.\n 4. Obtaining and creating regions of interest (ROIs) within image viewing windows.\n\n## Installation\n```\npip install -i https://pypi.org/simple/ --extra-index-url https://test.pypi.org/simple/ pyosirix==0.2.1-beta4\n```\n\n## Requirements\n - [`osirixgrpc`](https://pypi.org/project/osirixgrpc/)\n - [`numpy`](https://pypi.org/project/numpy/)\n\n## Contributions\nIf you would like to contribute to pyOsiriX, please have a look at our \n[contributing](https://osirixgrpc.github.io/osirixgrpc/contributing/CONTRIBUTING.html) page. We are always eager to hear\nyour ideas and improve pyOsiriX. Examples include:\n\n 1. Publishing example scripts of pyOsiriX in use. For example, something small that helps your day-to-day workflows.\n 2. Editing documentation or suggesting changes.\n 3. Reporting any bugs you find by [raising an issue](https://github.com/osirixgrpc/osirixgrpc/issues).\n 4. Testing new version of pyOsiriX (and OsiriXgrpc!) prior to release.\n 5. Contributing to or suggesting changes to the whole project, including requests for more OsiriX function exposure.\n\nPlease contact us at [osirixgrpc@gmail.com](mailto:osirixgrpc@gmail.com) to find out more.\n\n## Examples of use\n__Note__: These are for exemplary use only and just touch on what is capable with OsiriXgrpc. Over time we will compile \na list of more complete examples as found in the [documentation](https://osirixgrpc.github.io/osirixgrpc/pyosirix).\n\n### Accessing the 2D viewer\nIf 2D OsiriX viewers are open, it is possible to obtain its instance by simply running: \n```python\nimport osirix\ndisplayed_viewers = osirix.displayed_2d_viewers()  # Returns a list of all open viewers\nfrontmost_viewer = osirix.frontmost_viewer()  # Returns the viewer that is currently active (red frame)\n```\n\n### Accessing image data\nIt is straightforward to obtain image data within the 2D viewer and manipulate it. The following doubles the pixel \nvalues of the currently displayed image.\n```python\nimport osirix\nfrontmost_viewer = osirix.frontmost_viewer()\npixels = frontmost_viewer.cur_dcm().image  # Obtain pixel data (as 2D NumPy array) from currently displayed image slice.\nnew_pixels = pixels * 2  # Manipulate the array\nfrontmost_viewer.cur_dcm().image = new_pixels  # Update the image data for the currently shown image slice.\nfrontmost_viewer.needs_display_update()  # Tell OsiriX to redraw itself\n```\n\n### Accessing (all) image data\nImages in the viewer are stored in arrays, one array per frame, each array having the same length as the number of \ndisplayed slices. The following does the same as the example above, but applies to all images in the viewer.\n```python\nimport osirix\nfrontmost_viewer = osirix.frontmost_viewer()\npix_list = frontmost_viewer.pix_list(0)  # Obtain an array of DCMPix objects for the first (zeroth) frame. \nfor pix in pix_list:  # Loop through all DCMPix\n    pixels = pix.image\n    new_pixels = pixels * 2  # Manipulate the array\n    pix.image = new_pixels\nfrontmost_viewer.needs_display_update()  # Tell OsiriX to redraw itself\n```\n\n### Accessing ROIs\nSimilarly to images, ROIs can be obtained as an array for each requested frame in the 2D OsiriX viewer. Each element of \nthe array is another array, containing however, many ROIs are on that slice (some may be empty). This will produce a \nlist of unique ROI names in the viewer.\n```python\nimport osirix\nfrontmost_viewer = osirix.frontmost_viewer()\nroi_list = frontmost_viewer.roi_list(0)  # ROI list for the first (zeroth) frame.\nunique_names = []  # Empty storage\nfor roi_slice in roi_list:\n    for roi in roi_slice:  # There may be more than one ROI in a slice!\n        if roi.name not in unique_names:  # You could also use numpy.unique...  \n            unique_names.append(roi.name)\nif len(unique_names) == 0:\n    print(\"No ROIs found in the viewer!\")\nelse:\n    print(f\"Unique names are: {unique_names}\")\n```\n\n### Accessing ROIs by name\nIf you know the name of the ROI it is easy to avoid looping through\n```python\nimport osirix\nfrontmost_viewer = osirix.frontmost_viewer()\nroi_name = \"my_perfect_roi\"\nrois = frontmost_viewer.rois_with_name(roi_name)\nprint(f\"Number of ROIs with name {roi_name}: {len(rois)}\")\n```\n\n### Converting an ROI to a mask\nAnother useful thing to do is obtain a mask (a 2D array of boolean values) representing the region of the ROI. To do\nthis you need a DCMPix instance to compute it from. Luckily, this is easy to obtain!\n```python\nimport osirix\nimport numpy as np\nfrontmost_viewer = osirix.frontmost_viewer()\nroi_name = \"my_perfect_roi\"\nrois = frontmost_viewer.rois_with_name(roi_name)\nif len(rois) == 0:\n    raise ValueError(f\"Could not find any ROIs with the name {roi_name}\")\nvoxels = []  # Storage\nfor roi in rois:\n    pix = roi.pix  # The DCMPix on which the ROI was drawn\n    mask = pix.get_map_from_roi(roi)  # The mask we wanted.\n    voxels = np.r_[pix.image[mask], voxels]  # Append the voxel values\nmean = np.mean(voxels)  # Let's get some statistics\nstd = np.std(voxels, ddof=1)\nprint(f\"ROIs with name {roi_name} have mean {mean:.2f} and std-dev {std: .2f}\") \n```\n\n### Accessing Dicom files in the OsiriX database\nIt is possible to get access to the selected series and studies in the OsiriX database. This example sorts the \nDicomImages in the first selected DicomSeries by slice location and then opens them in a new 2D viewer.\n```python\nimport osirix\nimport numpy as np\nbrowser_controller = osirix.current_browser()  #The main window (database) of OsiriX\nstudies, series = browser_controller.database_selection()  # User selection as lists of DicomStudy/DicomSeries\nif len(series) == 0:\n    raise ValueError(\"No series have been selected\")\ndicom_images = np.array(series[0].images)  # An array of DicomImage instances\nsorted_idx = np.argsort([image.slice_location for image in dicom_images])  # Sort the images by slice location\ndicom_images = dicom_images[sorted_idx]\nviewer_controller = browser_controller.open_viewer_2d(dicom_images)  # Open up and view\n```\n\n### Accessing the VRController\nOnce a user has opened a VRController (or done so programmatically via pyOsiriX!), it is possible to access it as per\nthe 2D viewer. This example shows this and also how to make the contained ROIVolumes display themselves.\n```python\nimport osirix\nfrontmost_viewer = osirix.frontmost_viewer()\nvr_controllers = frontmost_viewer.vr_controllers()  # Get a list of currently open ones.\nif len(vr_controllers) == 0:\n    print(\"No open VR Controller.  Creating one.\")\n    vr_controller = frontmost_viewer.open_vr_viewer(mode=\"MIP\")  # Only other alternative is \"VR\"\nelse:\n    vr_controller = vr_controllers[0]\nroi_volumes = vr_controller.roi_volumes()\nif len(roi_volumes) == 0:\n    print(\"No valid ROI volumes available\")  # Note that ROIs defined on a single slice do not count!\nfor roi_volume in roi_volumes:\n    print(f\"Displaying ROI volume with name {roi_volume.name} and modifying is attributes\")\n    roi_volume.visible = True\n    roi_volume.color = (1., 0., 1.)  # Purple color in unit RGB space\n    roi_volume.opacity = 0.5\n    roi_volume.texture = False  # Generally looks better to us\n```",
    "bugtrack_url": null,
    "license": "Copyright (c) 2024 Matthew D Blackledge, Timothy Sum Hon Mun, and The Institute of Cancer Research  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.",
    "summary": "Pythonic interface for interacting with Osirix through a gRPC protocol",
    "version": "0.2.1b4",
    "project_urls": {
        "Bug Tracker": "https://github.com/osirixgrpc/osirixgrpc/issues",
        "Documentation": "https://osirixgrpc.github.io/osirixgrpc/",
        "Homepage": "https://osirixgrpc.github.io/osirixgrpc/",
        "Repository": "https://github.com/osirixgrpc/osirixgrpc"
    },
    "split_keywords": [
        "artificial intelligence",
        " dicom",
        " image processing",
        " medical imaging"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4a4a156b0a5bed7dea3f187c81c558a34069f63876e91308da1f81f2f4eb50ee",
                "md5": "a0b667f38535ecdd95ca5632e5fb86ec",
                "sha256": "179d0fd26eab91ed29be965a6c480d4c7394fe6dfd6b8993931d793bc3d06edd"
            },
            "downloads": -1,
            "filename": "pyosirix-0.2.1b4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a0b667f38535ecdd95ca5632e5fb86ec",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 30053,
            "upload_time": "2024-06-14T22:29:11",
            "upload_time_iso_8601": "2024-06-14T22:29:11.484008Z",
            "url": "https://files.pythonhosted.org/packages/4a/4a/156b0a5bed7dea3f187c81c558a34069f63876e91308da1f81f2f4eb50ee/pyosirix-0.2.1b4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "eb7c1711db0cbf606819ea9cd85798fc3da2c2d91fc88e7ebb6a4a546b566caa",
                "md5": "e2de5348fab3b736879a5c6fa58ee1d4",
                "sha256": "0b9b59c706c1d075cd62995841f60470e1846a57fa00b0f08d2da62baf65288f"
            },
            "downloads": -1,
            "filename": "pyosirix-0.2.1b4.tar.gz",
            "has_sig": false,
            "md5_digest": "e2de5348fab3b736879a5c6fa58ee1d4",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 28936,
            "upload_time": "2024-06-14T22:29:13",
            "upload_time_iso_8601": "2024-06-14T22:29:13.108461Z",
            "url": "https://files.pythonhosted.org/packages/eb/7c/1711db0cbf606819ea9cd85798fc3da2c2d91fc88e7ebb6a4a546b566caa/pyosirix-0.2.1b4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-06-14 22:29:13",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "osirixgrpc",
    "github_project": "osirixgrpc",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "pyosirix"
}
        
Elapsed time: 0.48049s