slicerio


Nameslicerio JSON
Version 1.1.1 PyPI version JSON
download
home_pagehttps://github.com/lassoan/slicerio
SummaryUtilities for 3D Slicer
upload_time2024-09-06 20:56:56
maintainerAndras Lasso
docs_urlNone
authorAndras Lasso
requires_python>=3.6
licenseNone
keywords 3dslicer medical imaging segmentation
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![Python package](https://github.com/lassoan/slicerio/workflows/Python%20package/badge.svg)](https://github.com/lassoan/slicerio/actions?query=workflow%3A%22Python+package%22)
![Upload Python Package](https://github.com/lassoan/slicerio/workflows/Upload%20Python%20Package/badge.svg)
[![PyPI version](https://badge.fury.io/py/slicerio.svg)](https://badge.fury.io/py/slicerio)

# *slicerio*

Python utilities for [3D Slicer](https://www.slicer.org) interoperability.

The package contains utility functions for reading and writing segmentation files and convenience functions for using 3D Slicer via its web API. More functions will be added in the future.

See [this page](UsingStandardTerminology.md) to learn more about how standard terms can be used to describe content of segmentation files.

## Installation

Using [pip](https://pip.pypa.io/en/stable/):

```
pip install slicerio
```

## Examples

### Read segmentation and show some information about segments

```python
import slicerio
import json

segmentation = slicerio.read_segmentation("path/to/Segmentation.seg.nrrd", skip_voxels=True)

number_of_segments = len(segmentation["segments"])
print(f"Number of segments: {number_of_segments}")

segment_names = slicerio.segment_names(segmentation)
print(f"Segment names: {', '.join(segment_names)}")

segment0 = slicerio.segment_from_name(segmentation, segment_names[0])
print("First segment info:\n" + json.dumps(segment0, sort_keys=False, indent=4))
```

### Extract selected segments with chosen label values

#### Extract segments by terminology

Example for getting a 3D [NRRD](SegmentationFileFormat.md) file that has label values assigned based on [standard terminology codes](UsingStandardTerminology.md).
Terminology is a `dict` that must specify `category` and `type` codes and may optionally also specify `typeModifier`, `anatomicRegion`, and `anatomicRegionModifier`. Each code is specifed by a triplet of "coding scheme designator", "code value", "code meaning" in a list.

Coding scheme designator is typically `SCT` (SNOMED-CT) for clinical images. You can find codes in the [SNOMED-CT browser](https://browser.ihtsdotools.org/). When code exists for "entire X" and "structure of X" then always use the "structure" code ("entire" code has a very strict meaning that is rarely applicable in practice).

Code meaning (third component of codes, such as "Anatomical Structure", "Ribs", "Right") is informational only, it can be used for troubleshooting or displayed to the user, but it is ignored in information processing (e.g., two codes match if their coding scheme designator and code value are the same even if code meaning is different).

```python
import slicerio

input_filename = "path/to/Segmentation.seg.nrrd"
output_filename = "path/to/SegmentationExtracted.seg.nrrd"
segments_to_labels = [
   ({"category": ["SCT", "123037004", "Anatomical Structure"], "type": ["SCT", "113197003", "Ribs"]}, 1),
   ({"category": ["SCT", "123037004", "Anatomical Structure"], "type": ["SCT", "39607008", "Lung"], "typeModifier": ["SCT", "24028007", "Right"]}, 3)
   ]

segmentation = slicerio.read_segmentation(input_filename)
extracted_segmentation = slicerio.extract_segments(segmentation, segments_to_labels)
slicerio.write_segmentation(output_filename, extracted_segmentation)
```

#### Extract segments by name

It is strongly recommended to look up segments by [standard terminology codes](UsingStandardTerminology.md) instead of segment name, as spelling errors and inconsistent use of names often causes mismatch.

```python
import slicerio

input_filename = "path/to/Segmentation.seg.nrrd"
output_filename = "path/to/SegmentationExtracted.seg.nrrd"
segment_names_to_labels = [("ribs", 10), ("right lung", 12), ("left lung", 6)]

segmentation = slicerio.read_segmentation(input_filename)
extracted_segmentation = slicerio.extract_segments(segmentation, segment_names_to_labels)
slicerio.write_segmentation(output_filename, extracted_segmentation)
```

### Create segmentation file from numpy array

```python
# Create segmentation with two labels (1, 3)
voxels = np.zeros([100, 120, 150])
voxels[30:50, 20:60, 70:100] = 1
voxels[70:90, 80:110, 60:110] = 3

# Image geometry
spacing = [0.5, 0.5, 0.8]
origin = [10, 30, 15]

segmentation = {
   "voxels": voxels,
   "encoding": "gzip",
   "ijkToLPS": [[ spacing[0], 0., 0., origin[0]],
                [ 0., spacing[1], 0., origin[1]],
                [ 0., 0., spacing[2], origin[2]],
                [ 0., 0., 0., 1. ]]
   "segmentation": {
      "containedRepresentationNames": ["Binary labelmap", "Closed surface"],
      # "masterRepresentation": "Binary labelmap",
      # "referenceImageExtentOffset": [0, 0, 0],
   },
   "segments": [
      {
         "id": "Segment_1",
         "labelValue": 1,
         "layer": 0,
         "color": [0.9, 0.9, 0.6],
         "name": "ribs",
         "terminology": {
            "contextName": "Segmentation category and type - 3D Slicer General Anatomy list",
            "category": ["SCT", "123037004", "Anatomical Structure"],
            "type": ["SCT", "113197003", "Rib"] }
      },
      {
         "id": "Segment_2",
         "labelValue": 3,
         "layer": 0,
         "color": [0.9, 0.9, 0.6],
         "name": "spine",
         "status": "inprogress",
         "terminology": {
            "contextName": "Segmentation category and type - 3D Slicer General Anatomy list",
            "category": ["SCT", "123037004", "Anatomical Structure"],
            "type": ["SCT", "122494005", "Cervical spine"] }
      },
   ]
}

slicerio.write_segmentation(segmentation, "path/to/Segmentation.seg.nrrd")
```

### Create segmentation file from NIFTI labelmap image file

```python
input_nifti_filename = "path/to/Segmentation.nii.gz"
output_filename = "path/to/Segmentation.seg.nrrd"

segmentation = slicerio.read_segmentation(input_nifti_filename)

# Specify segment metadata for each label value
# (NIFTI cannot store segment metadata in the image file)
segmentation["segments"] = [
    { "labelValue": 1,
      "color": [0.9, 0.9, 0.6],
      "name": "ribs",
      "terminology": {
          "contextName": "Segmentation category and type - 3D Slicer General Anatomy list",
          "category": ["SCT", "123037004", "Anatomical Structure"],
          "type": ["SCT", "113197003", "Rib"] } },
    { "labelValue": 3,
      "color": [0.9, 0.1, 0.2],
      "name": "spine",
      "terminology": {
          "contextName": "Segmentation category and type - 3D Slicer General Anatomy list",
          "category": ["SCT", "123037004", "Anatomical Structure"],
          "type": ["SCT", "122494005", "Cervical spine"] } },
   ]

slicerio.write_segmentation(output_filename, segmentation)
```

### View files in 3D Slicer

The `server` module allows using Slicer as a data viewer in any Python environment.
All files are loaded into a single Slicer instance, which eliminates the wait time for application startup
and also allows analyzing, comparing multiple data sets in one workspace. The feature is implemented by using
[3D Slicer's built-in Web Server module](https://slicer.readthedocs.io/en/latest/user_guide/modules/webserver.html), which offers data access via a REST API.

For example, an image file can be loaded with the command below. The command starts a new Slicer application instance
with the web API enabled.

```python
import os
import slicerio.server

# Load from remote URL
slicerio.server.file_load("https://github.com/rbumm/SlicerLungCTAnalyzer/releases/download/SampleData/LungCTAnalyzerChestCT.nrrd")

# Load from local file
# A Slicer application instance (with Web Server enabled) is automatically started, if it is not running already.
slicerio.server.file_load("path/to/SomeImage.nrrd", slicer_executable=f"{os.environ["LOCALAPPDATA"]}/NA-MIC/Slicer 5.2.0/Slicer.exe")
```

A segmentation file can be loaded by specifying the `SegmentationFile` file type:

```python
nodeID = slicerio.server.file_load("path/to/Segmentation.seg.nrrd", "SegmentationFile")
```

If the loaded file is modified then it can be reloaded from the updated file:

```python
slicerio.server.node_reload(id=nodeID)
```

#### Supported file types
- image files (nrrd, nii.gz, ...): `VolumeFile`
- segmentation file (.seg.nrrd, nrrd, nii.gz, ...): `SegmentationFile`
- model file (.stl, .ply, .vtk, .vtp, .vtu, ...): `ModelFile`
- markup file (.mrj.json): `MarkupsFile`
- transform file (.tfm, .h5, .txt): `TransformFile`
- spreadsheet file (.csv, .tsv): `TableFile`
- text file (.txt, .json, ...): `TextFile`
- sequence file (.mrb, .seq.nrrd): `SequenceFile`
- Slicer scene file (.mrml, .mrb): `SceneFile`

### Inspect data in 3D Slicer

Metadata of data sets loaded into the server can be obtained using `node_properties` function:

```python
properties= slicerio.server.node_properties(name="MRHead")[0]
print(properties["ClassName"])
print(properties["ImageData"]["Extent"])

properties = slicerio.server.node_properties(id=segmentationId)[0]
segments = properties["Segmentation"]["Segments"]
for segmentId in segments:
   print(f"Segment name: {segments[segmentId]['Name']} - color: {segments[segmentId]['Color']}")
```

List of available nodes can be retrieved using `node_names` and `node_ids`functions:

```python
# Retreve node names of all images
slicerio.server.node_names(class_name="vtkMRMLVolumeNode")

# Retrieve all node IDs
slicerio.server.node_ids(class_name="vtkMRMLVolumeNode")
```

Nodes can be removed from the workspace:

```python
# Remove node by name
slicerio.server.node_remove(name="MRHead")

# Clear the whole scene
slicerio.server.node_remove()
```

### Export files from 3D Slicer

Data sets created in Slicer (e.g., segmentations, landmark point sets), which can be retrieved by writing into file.

```python
# Save the node identified by `MRHead` node name, uncompressed, into the specified file.
slicerio.server.file_save("c:/tmp/MRHeadSaved.nrrd", name="MRHead", properties={'useCompression': False})
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/lassoan/slicerio",
    "name": "slicerio",
    "maintainer": "Andras Lasso",
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": "lasso@queensu.ca",
    "keywords": "3DSlicer medical imaging segmentation",
    "author": "Andras Lasso",
    "author_email": "lasso@queensu.ca",
    "download_url": "https://files.pythonhosted.org/packages/c9/6e/b4a1e1b8c2a8bef63fe1391f74b4a55174afa961974a0167edb48afac77a/slicerio-1.1.1.tar.gz",
    "platform": null,
    "description": "[![Python package](https://github.com/lassoan/slicerio/workflows/Python%20package/badge.svg)](https://github.com/lassoan/slicerio/actions?query=workflow%3A%22Python+package%22)\n![Upload Python Package](https://github.com/lassoan/slicerio/workflows/Upload%20Python%20Package/badge.svg)\n[![PyPI version](https://badge.fury.io/py/slicerio.svg)](https://badge.fury.io/py/slicerio)\n\n# *slicerio*\n\nPython utilities for [3D Slicer](https://www.slicer.org) interoperability.\n\nThe package contains utility functions for reading and writing segmentation files and convenience functions for using 3D Slicer via its web API. More functions will be added in the future.\n\nSee [this page](UsingStandardTerminology.md) to learn more about how standard terms can be used to describe content of segmentation files.\n\n## Installation\n\nUsing [pip](https://pip.pypa.io/en/stable/):\n\n```\npip install slicerio\n```\n\n## Examples\n\n### Read segmentation and show some information about segments\n\n```python\nimport slicerio\nimport json\n\nsegmentation = slicerio.read_segmentation(\"path/to/Segmentation.seg.nrrd\", skip_voxels=True)\n\nnumber_of_segments = len(segmentation[\"segments\"])\nprint(f\"Number of segments: {number_of_segments}\")\n\nsegment_names = slicerio.segment_names(segmentation)\nprint(f\"Segment names: {', '.join(segment_names)}\")\n\nsegment0 = slicerio.segment_from_name(segmentation, segment_names[0])\nprint(\"First segment info:\\n\" + json.dumps(segment0, sort_keys=False, indent=4))\n```\n\n### Extract selected segments with chosen label values\n\n#### Extract segments by terminology\n\nExample for getting a 3D [NRRD](SegmentationFileFormat.md) file that has label values assigned based on [standard terminology codes](UsingStandardTerminology.md).\nTerminology is a `dict` that must specify `category` and `type` codes and may optionally also specify `typeModifier`, `anatomicRegion`, and `anatomicRegionModifier`. Each code is specifed by a triplet of \"coding scheme designator\", \"code value\", \"code meaning\" in a list.\n\nCoding scheme designator is typically `SCT` (SNOMED-CT) for clinical images. You can find codes in the [SNOMED-CT browser](https://browser.ihtsdotools.org/). When code exists for \"entire X\" and \"structure of X\" then always use the \"structure\" code (\"entire\" code has a very strict meaning that is rarely applicable in practice).\n\nCode meaning (third component of codes, such as \"Anatomical Structure\", \"Ribs\", \"Right\") is informational only, it can be used for troubleshooting or displayed to the user, but it is ignored in information processing (e.g., two codes match if their coding scheme designator and code value are the same even if code meaning is different).\n\n```python\nimport slicerio\n\ninput_filename = \"path/to/Segmentation.seg.nrrd\"\noutput_filename = \"path/to/SegmentationExtracted.seg.nrrd\"\nsegments_to_labels = [\n   ({\"category\": [\"SCT\", \"123037004\", \"Anatomical Structure\"], \"type\": [\"SCT\", \"113197003\", \"Ribs\"]}, 1),\n   ({\"category\": [\"SCT\", \"123037004\", \"Anatomical Structure\"], \"type\": [\"SCT\", \"39607008\", \"Lung\"], \"typeModifier\": [\"SCT\", \"24028007\", \"Right\"]}, 3)\n   ]\n\nsegmentation = slicerio.read_segmentation(input_filename)\nextracted_segmentation = slicerio.extract_segments(segmentation, segments_to_labels)\nslicerio.write_segmentation(output_filename, extracted_segmentation)\n```\n\n#### Extract segments by name\n\nIt is strongly recommended to look up segments by [standard terminology codes](UsingStandardTerminology.md) instead of segment name, as spelling errors and inconsistent use of names often causes mismatch.\n\n```python\nimport slicerio\n\ninput_filename = \"path/to/Segmentation.seg.nrrd\"\noutput_filename = \"path/to/SegmentationExtracted.seg.nrrd\"\nsegment_names_to_labels = [(\"ribs\", 10), (\"right lung\", 12), (\"left lung\", 6)]\n\nsegmentation = slicerio.read_segmentation(input_filename)\nextracted_segmentation = slicerio.extract_segments(segmentation, segment_names_to_labels)\nslicerio.write_segmentation(output_filename, extracted_segmentation)\n```\n\n### Create segmentation file from numpy array\n\n```python\n# Create segmentation with two labels (1, 3)\nvoxels = np.zeros([100, 120, 150])\nvoxels[30:50, 20:60, 70:100] = 1\nvoxels[70:90, 80:110, 60:110] = 3\n\n# Image geometry\nspacing = [0.5, 0.5, 0.8]\norigin = [10, 30, 15]\n\nsegmentation = {\n   \"voxels\": voxels,\n   \"encoding\": \"gzip\",\n   \"ijkToLPS\": [[ spacing[0], 0., 0., origin[0]],\n                [ 0., spacing[1], 0., origin[1]],\n                [ 0., 0., spacing[2], origin[2]],\n                [ 0., 0., 0., 1. ]]\n   \"segmentation\": {\n      \"containedRepresentationNames\": [\"Binary labelmap\", \"Closed surface\"],\n      # \"masterRepresentation\": \"Binary labelmap\",\n      # \"referenceImageExtentOffset\": [0, 0, 0],\n   },\n   \"segments\": [\n      {\n         \"id\": \"Segment_1\",\n         \"labelValue\": 1,\n         \"layer\": 0,\n         \"color\": [0.9, 0.9, 0.6],\n         \"name\": \"ribs\",\n         \"terminology\": {\n            \"contextName\": \"Segmentation category and type - 3D Slicer General Anatomy list\",\n            \"category\": [\"SCT\", \"123037004\", \"Anatomical Structure\"],\n            \"type\": [\"SCT\", \"113197003\", \"Rib\"] }\n      },\n      {\n         \"id\": \"Segment_2\",\n         \"labelValue\": 3,\n         \"layer\": 0,\n         \"color\": [0.9, 0.9, 0.6],\n         \"name\": \"spine\",\n         \"status\": \"inprogress\",\n         \"terminology\": {\n            \"contextName\": \"Segmentation category and type - 3D Slicer General Anatomy list\",\n            \"category\": [\"SCT\", \"123037004\", \"Anatomical Structure\"],\n            \"type\": [\"SCT\", \"122494005\", \"Cervical spine\"] }\n      },\n   ]\n}\n\nslicerio.write_segmentation(segmentation, \"path/to/Segmentation.seg.nrrd\")\n```\n\n### Create segmentation file from NIFTI labelmap image file\n\n```python\ninput_nifti_filename = \"path/to/Segmentation.nii.gz\"\noutput_filename = \"path/to/Segmentation.seg.nrrd\"\n\nsegmentation = slicerio.read_segmentation(input_nifti_filename)\n\n# Specify segment metadata for each label value\n# (NIFTI cannot store segment metadata in the image file)\nsegmentation[\"segments\"] = [\n    { \"labelValue\": 1,\n      \"color\": [0.9, 0.9, 0.6],\n      \"name\": \"ribs\",\n      \"terminology\": {\n          \"contextName\": \"Segmentation category and type - 3D Slicer General Anatomy list\",\n          \"category\": [\"SCT\", \"123037004\", \"Anatomical Structure\"],\n          \"type\": [\"SCT\", \"113197003\", \"Rib\"] } },\n    { \"labelValue\": 3,\n      \"color\": [0.9, 0.1, 0.2],\n      \"name\": \"spine\",\n      \"terminology\": {\n          \"contextName\": \"Segmentation category and type - 3D Slicer General Anatomy list\",\n          \"category\": [\"SCT\", \"123037004\", \"Anatomical Structure\"],\n          \"type\": [\"SCT\", \"122494005\", \"Cervical spine\"] } },\n   ]\n\nslicerio.write_segmentation(output_filename, segmentation)\n```\n\n### View files in 3D Slicer\n\nThe `server` module allows using Slicer as a data viewer in any Python environment.\nAll files are loaded into a single Slicer instance, which eliminates the wait time for application startup\nand also allows analyzing, comparing multiple data sets in one workspace. The feature is implemented by using\n[3D Slicer's built-in Web Server module](https://slicer.readthedocs.io/en/latest/user_guide/modules/webserver.html), which offers data access via a REST API.\n\nFor example, an image file can be loaded with the command below. The command starts a new Slicer application instance\nwith the web API enabled.\n\n```python\nimport os\nimport slicerio.server\n\n# Load from remote URL\nslicerio.server.file_load(\"https://github.com/rbumm/SlicerLungCTAnalyzer/releases/download/SampleData/LungCTAnalyzerChestCT.nrrd\")\n\n# Load from local file\n# A Slicer application instance (with Web Server enabled) is automatically started, if it is not running already.\nslicerio.server.file_load(\"path/to/SomeImage.nrrd\", slicer_executable=f\"{os.environ[\"LOCALAPPDATA\"]}/NA-MIC/Slicer 5.2.0/Slicer.exe\")\n```\n\nA segmentation file can be loaded by specifying the `SegmentationFile` file type:\n\n```python\nnodeID = slicerio.server.file_load(\"path/to/Segmentation.seg.nrrd\", \"SegmentationFile\")\n```\n\nIf the loaded file is modified then it can be reloaded from the updated file:\n\n```python\nslicerio.server.node_reload(id=nodeID)\n```\n\n#### Supported file types\n- image files (nrrd, nii.gz, ...): `VolumeFile`\n- segmentation file (.seg.nrrd, nrrd, nii.gz, ...): `SegmentationFile`\n- model file (.stl, .ply, .vtk, .vtp, .vtu, ...): `ModelFile`\n- markup file (.mrj.json): `MarkupsFile`\n- transform file (.tfm, .h5, .txt): `TransformFile`\n- spreadsheet file (.csv, .tsv): `TableFile`\n- text file (.txt, .json, ...): `TextFile`\n- sequence file (.mrb, .seq.nrrd): `SequenceFile`\n- Slicer scene file (.mrml, .mrb): `SceneFile`\n\n### Inspect data in 3D Slicer\n\nMetadata of data sets loaded into the server can be obtained using `node_properties` function:\n\n```python\nproperties= slicerio.server.node_properties(name=\"MRHead\")[0]\nprint(properties[\"ClassName\"])\nprint(properties[\"ImageData\"][\"Extent\"])\n\nproperties = slicerio.server.node_properties(id=segmentationId)[0]\nsegments = properties[\"Segmentation\"][\"Segments\"]\nfor segmentId in segments:\n   print(f\"Segment name: {segments[segmentId]['Name']} - color: {segments[segmentId]['Color']}\")\n```\n\nList of available nodes can be retrieved using `node_names` and `node_ids`functions:\n\n```python\n# Retreve node names of all images\nslicerio.server.node_names(class_name=\"vtkMRMLVolumeNode\")\n\n# Retrieve all node IDs\nslicerio.server.node_ids(class_name=\"vtkMRMLVolumeNode\")\n```\n\nNodes can be removed from the workspace:\n\n```python\n# Remove node by name\nslicerio.server.node_remove(name=\"MRHead\")\n\n# Clear the whole scene\nslicerio.server.node_remove()\n```\n\n### Export files from 3D Slicer\n\nData sets created in Slicer (e.g., segmentations, landmark point sets), which can be retrieved by writing into file.\n\n```python\n# Save the node identified by `MRHead` node name, uncompressed, into the specified file.\nslicerio.server.file_save(\"c:/tmp/MRHeadSaved.nrrd\", name=\"MRHead\", properties={'useCompression': False})\n```\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Utilities for 3D Slicer",
    "version": "1.1.1",
    "project_urls": {
        "Download": "https://github.com/lassoan/slicerio/archive/master.zip",
        "Homepage": "https://github.com/lassoan/slicerio"
    },
    "split_keywords": [
        "3dslicer",
        "medical",
        "imaging",
        "segmentation"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b6396e19df9a05113371a831c653ef2136441a18520e8b6f0e68a740dc1fe155",
                "md5": "2b63229050fdb2770842c7daf1200385",
                "sha256": "584bc2386d02b0cfc9cc9b9b7bd970c5ab5c65928ffa3431516c18b557fc71a6"
            },
            "downloads": -1,
            "filename": "slicerio-1.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "2b63229050fdb2770842c7daf1200385",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 20760,
            "upload_time": "2024-09-06T20:56:55",
            "upload_time_iso_8601": "2024-09-06T20:56:55.309894Z",
            "url": "https://files.pythonhosted.org/packages/b6/39/6e19df9a05113371a831c653ef2136441a18520e8b6f0e68a740dc1fe155/slicerio-1.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c96eb4a1e1b8c2a8bef63fe1391f74b4a55174afa961974a0167edb48afac77a",
                "md5": "dde9b7fd2290df4d361163c090cbd67d",
                "sha256": "baaa32ed3730f56341d79e1daf34858e9147e38511731a9f16d21d82007760c6"
            },
            "downloads": -1,
            "filename": "slicerio-1.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "dde9b7fd2290df4d361163c090cbd67d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 22640,
            "upload_time": "2024-09-06T20:56:56",
            "upload_time_iso_8601": "2024-09-06T20:56:56.728668Z",
            "url": "https://files.pythonhosted.org/packages/c9/6e/b4a1e1b8c2a8bef63fe1391f74b4a55174afa961974a0167edb48afac77a/slicerio-1.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-06 20:56:56",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "lassoan",
    "github_project": "slicerio",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "slicerio"
}
        
Elapsed time: 0.31338s