# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['wsidicom']

package_data = \
{'': ['*']}

install_requires = \
['Pillow>=9.1.1,<10.0.0', 'numpy>=1.22.0,<2.0.0', 'pydicom>=2.1.0,<3.0.0']

setup_kwargs = {
    'name': 'wsidicom',
    'version': '0.6.0',
    'description': 'Tools for handling DICOM based whole scan images',
    'long_description': '# *wsidicom*\n*wsidicom* is a Python package for reading [DICOM WSI](http://dicom.nema.org/Dicom/DICOMWSI/) file sets. The aims with the project are:\n- Easy to use interface for reading and writing WSI DICOM images and annotations using the DICOM Media Storage Model.\n- Support the latest and upcomming DICOM standards.\n- Platform independent installation via PyPI.\n\n## Installing *wsidicom*\n*wsidicom* is available on PyPI:\n```console\n$ pip install wsidicom\n```\nAnd through conda:\n```console\nconda install -c conda-forge wsidicom\n```\n\n## Important note\nPlease note that this is an early release and the API is not frozen yet. Function names and functionality is prone to change.\n\n## Requirements\n*wsidicom* uses pydicom, numpy and Pillow (with jpeg and jpeg2000 plugins).\n\n## Limitations\nLevels are required to have (close to) 2 factor scale and same tile size.\n\nOnly JPEGBaseline8Bit, JPEG2000 and JPEG2000Lossless transfer syntax is supported.\n\nOptical path identifiers needs to be unique across file set.\n\n## Basic usage\n***Load a WSI dataset from files in folder.***\n```python\nfrom wsidicom import WsiDicom\nslide = WsiDicom.open(path_to_folder)\n```\n***Read a 200x200 px region starting from px 1000, 1000 at level 6.***\n ```python\nregion = slide.read_region((1000, 1000), 6, (200, 200))\n```\n***Read 3x3 mm region starting at 0, 0 mm at level 6.***\n ```python\nregion_mm = slide.read_region_mm((0, 0), 6, (3, 3))\n```\n***Read 3x3 mm region starting at 0, 0 mm with pixel spacing 0.01 mm/px.***\n ```python\nregion_mpp = slide.read_region_mpp((0, 0), 0.01, (3, 3))\n```\n***Read a thumbnail of the whole slide with maximum dimensions 200x200 px.***\n ```python\nthumbnail = slide.read_thumbnail(200, 200)\n```\n***Read an overview image (if available).***\n ```python\noverview = slide.read_overview()\n```\n***Read a label image (if available).***\n ```python\nlabel = slide.read_label()\n```\n***Read (decoded) tile from position 1, 1 in level 6.***\n ```python\ntile = slide.read_tile(6, (1, 1))\n```\n***Read (encoded) tile from position 1, 1 in level 6.***\n ```python\ntile_bytes = slide.read_encoded_tile(6, (1, 1))\n```\n***Close files***\n ```python\nslide.close()\n```\n\n## Settings\n*wsidicom* can be configured with the settings variable. For example, set the parsing of files to strict:\n```python\nfrom wsidicom import settings\nsettings.strict_uid_check = True\nsettings._strict_attribute_check = True\n```\n\n## Data structure\nA WSI DICOM pyramid is in *wsidicom* represented by a hierarchy of objects of different classes, starting from bottom:\n- *WsiDicomFile*, represents a WSI DICOM file, used for accessing DicomImageData and WsiDataset.\n- *DicomImageData*, represents the image data in one or several WSI DICOM files.\n- *WsiDataset*, represents the image metadata in one or several WSI DICOM files.\n- *WsiInstance*, represents image data and image metadata.\n- *WsiDicomLevel*, represents a group of instances with the same image size, i.e. of the same level.\n- *WsiDicomLevels*, represents a group of levels, i.e. the pyrimidal structure.\n- *WsiDicom*, represents a collection of levels, labels and overviews.\n\nLabels and overviews are structured similarly to levels, but with somewhat different properties and restrictions.\n\nThe structure is easiest created using the open() helper functions, e.g. to create a WsiDicom-object:\n```python\nslide = WsiDicom.open(path_to_folder)\n```\n\nBut the structure can also be created manually from the bottom:\n```python\nfile = WsiDicomFile(path_to_file)\ninstance = WsiInstance(file.dataset, DicomImageData(files))\nlevel = WsiDicomLevel([instance])\nlevels = WsiDicomLevels([level])\nslide = WsiDicom([levels])\n```\n\n## Adding support for other file formats.\nBy subclassing *ImageData* and implementing the required properties (transfer_syntax, image_size, tile_size, and pixel_spacing) and methods (get_tile() and close()) *wsidicom* can be used to access wsi images in other file formats than DICOM. In addition to a ImageData-object, image data, specified in a DICOM dataset, must also be created. For example, assuming a implementation of MyImageData exists that takes a path to a image file as argument and create_dataset() produces a DICOM dataset (see is_wsi_dicom() of WsiDataset for required attributes), WsiInstancees could be created for each pyramidal level, label, or overview:\n```python\nimage_data = MyImageData(\'path_to_image_file\')\ndataset = create_dataset()\ninstance = WsiInstance(dataset, image_data)\n```\nThe created instances can then be arranged into levels etc, and opened as a WsiDicom-object as described in \'Data structure\'.\n\n## Annotation usage\nAnnotations are structured in a hierarchy:\n- AnnotationInstance\n    Represents a collection of AnnotationGroups. All the groups have the same frame of reference, i.e. annotations are from the same wsi stack.\n- AnnotationGroup\n    Represents a group of annotations. All annotations in the group are of the same type (e.g. PointAnnotation), have the same label, description and category and type. The category and type are codes that are used to define the annotated feature. A good resource for working with codes is avaiable [here](https://qiicr.gitbook.io/dcmqi-guide/opening/coding_schemes).\n- Annotation\n    Represents a annotation. An Annotation has a geometry (currently Point, Polyline, Polygon) and an optional list of Measurements.\n- Measurement\n    Represents a measurement for an Annotation. A Measurement consists of a type-code (e.g. "Area"), a value and a unit-code ("mm")\n\nCodes that are defined in the 222-draft can be created using the create(source, type) function of the ConceptCode-class.\n\n***Load a WSI dataset from files in folder.***\n```python\nfrom wsidicom import WsiDicom\nslide = WsiDicom.open(path_to_folder)\n```\n***Create a point annotation at x=10.0, y=20.0 mm.***\n```python\nfrom wsidicom import Annotation, Point\npoint_annotation = Annotation(Point(10.0, 20.0))\n```\n\n***Create a point annotation with a measurement.***\n```python\nfrom wsidicom import ConceptCode, Measurement\n# A measurement is defined by a type code (\'Area\'), a value (25.0) and a unit code (\'Pixels).\narea = ConceptCode.measurement(\'Area\')\npixels = ConceptCode.unit(\'Pixels\')\nmeasurement = Measurement(area, 25.0, pixels)\npoint_annotation_with_measurment = Annotation(Point(10.0, 20.0), [measurement])\n```\n\n***Create a group of the annotations.***\n```python\nfrom wsidicom import PointAnnotationGroup\n# The 222 suplement requires groups to have a label, a category and a type\ngroup = PointAnnotationGroup(\n    annotations=[point_annotation, point_annotation_with_measurment],\n    label=\'group label\',\n    categorycode=ConceptCode.category(\'Tissue\'),\n    typecode=ConceptCode.type(\'Nucleus\'),\n    description=\'description\'\n)\n```\n\n***Create a collection of annotation groups.***\n```python\nfrom wsidicom import AnnotationInstance\nannotations = AnnotationInstance([group], \'volume\', slide.uids)\n```\n\n***Save the collection to file.***\n```python\nannotations.save(\'path_to_dicom_dir/annotation.dcm\')\n```\n\n***Reopen the slide and access the annotation instance.***\n```python\nslide = WsiDicom.open(path_to_folder)\nannotations = slide.annotations\n```\n\n## Setup environment for development\nRequires poetry installed in the virtual environment.\n\n```console\n$ git clone https://github.com/imi-bigpicture/wsidicom.git\n$ poetry install\n```\n\nTo watch unit tests use:\n\n```console\n$ poetry run pytest-watch -- -m unittest\n```\n\nThe integration tests uses test images from nema.org thats needs to be downloaded. The location of the test images can be changed from the default tests\\testdata\\slides using the enviroment variable WSIDICOM_TESTDIR. Download the images using the supplied script:\n\n```console\n$ python .\\tests\\download_test_images.py\n```\n\nIf the files are already downloaded the script will validate the checksums.\n\nTo run integration tests:\n\n```console\n$ poetry run pytest -m integration\n```\n\n## Other DICOM python tools\n- [pydicom](https://pydicom.github.io/)\n- [highdicom](https://github.com/MGHComputationalPathology/highdicom)\n\n## Contributing\nWe welcome any contributions to help improve this tool for the WSI DICOM community!\n\nWe recommend first creating an issue before creating potential contributions to check that the contribution is in line with the goals of the project. To submit your contribution, please issue a pull request on the imi-bigpicture/wsidicom repository with your changes for review.\n\nOur aim is to provide constructive and positive code reviews for all submissions. The project relies on gradual typing and roughly follows PEP8. However, we are not dogmatic. Most important is that the code is easy to read and understand.\n\n## Acknowledgement\n*wsidicom*: Copyright 2021 Sectra AB, licensed under Apache 2.0.\n\nThis project is part of a project that has received funding from the Innovative Medicines Initiative 2 Joint Undertaking under grant agreement No 945358. This Joint Undertaking receives support from the European Union’s Horizon 2020 research and innovation programme and EFPIA. IMI website: www.imi.europa.eu\n',
    'author': 'Erik O Gabrielsson',
    'author_email': 'erik.o.gabrielsson@sectra.com',
    'maintainer': 'None',
    'maintainer_email': 'None',
    'url': 'https://github.com/imi-bigpicture/wsidicom',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.8,<3.12',
}


setup(**setup_kwargs)
