Metadata-Version: 2.1
Name: gcapi
Version: 0.5.1
Summary: Python client for the grand-challenge.org API
Home-page: https://github.com/DIAGNijmegen/rse-gcapi
Author: James Meakin
Author-email: code@jmsmkn.com
License: Apache Software License 2.0
Keywords: gcapi
Platform: UNKNOWN
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Provides-Extra: test
License-File: LICENSE
License-File: AUTHORS.rst

==========================
Grand Challenge API Client
==========================


.. image:: https://img.shields.io/pypi/v/gcapi.svg
   :target: https://pypi.python.org/pypi/gcapi

.. image:: https://github.com/DIAGNijmegen/rse-gcapi/workflows/CI/badge.svg
   :target: https://github.com/DIAGNijmegen/rse-gcapi/actions?query=workflow%3ACI+branch%3Amaster
   :alt: Build Status

.. image:: https://codecov.io/gh/DIAGNijmegen/rse-gcapi/branch/master/graph/badge.svg
   :target: https://codecov.io/gh/DIAGNijmegen/rse-gcapi
   :alt: Code Coverage Status


Python client for the grand-challenge.org API


* Free software: Apache Software License 2.0


Features
--------

This client library is a handy way to interact with the REST API for grand-challenge.org from python, and provides some
convenience methods.

Authorize with your personal token
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To authorize on the api you will need your API token. You can generate the token yourself by logging in on
Grand Challenge -> Your Profile -> Manage API Tokens.

Create a token and use it to authorise with the client. Please treat this token like a password!

.. code:: python

    from gcapi import Client

    c = Client(token="Your Personal API Token")


Starting an Algorithm Job
~~~~~~~~~~~~~~~~~~~~~~~~~

First, you need the slug of the algorithm you wish to use. You can get the slug from the url of the algorithm.
For example, if you would like to upload to the algorithm at https://grand-challenge.org/algorithms/corads-ai/ you
would use ``algorithm="corads-ai"``. Note that slugs are case sensitive.

Second, you need to provide the input(s) for the algorithm. The inputs are defined on the algorithm with interfaces,
which are identified by their slugs and determine the type of input that is expected by the algorithm.
There are three super-types of interfaces: ``Image``, ``File`` and ``Value``. For example, for the algorithm at
https://grand-challenge.org/algorithms/corads-ai/ a single input interface with slug ``generic-medical-image`` of
super_kind ``Image`` is defined.

You can get the input interfaces for an algorithm as follows:

.. code:: python

    alg = c.algorithms.detail(slug="corads-ai")

    print(alg["inputs"])
    [{
         'title': 'Generic Medical Image',
         'description': '',
         'slug': 'generic-medical-image',
         'kind': 'Image',
         'pk': 1,
         'default_value': None,
         'super_kind': 'Image'
    }],


You will need to create a dictionary with the keys being the slugs of the interfaces and the values being the values
you want to use. There are two ways to provide a value for an interface of super_kind ``Image``. Either provide a list
of files for an image you want to upload, or provide an image hyperlink if the image is already uploaded to Grand Challenge.

To run an Algorithm with a list of files:

.. code:: python

    from pathlib import Path

    # prepare the files
    files = [f.resolve() for f in Path("/path/to/files").iterdir()]

    # run the algorithm
    job = client.run_external_job(
        algorithm="corads-ai",
        inputs={
            "generic-medical-image": files
        }
    )

To run an Algorithm with an existing image:

.. code:: python

    # run the algorithm
    job = client.run_external_job(
        algorithm="corads-ai",
        inputs={
            "generic-medical-image":
            "https://grand-challenge.org/api/v1/cases/images/.../"
        }
    )

To run an Algorithm with other types of inputs:

.. code:: python

    # run the algorithm
    job = client.run_external_job(
        algorithm="some-algorithm",
        inputs={
            "lung-volume":
            1.234,
            "nodules":
            {...}
        }
    )


The function will run the algorithm with the provided inputs and return a job object.
You can refresh the job object with

.. code:: python

    job = c.algorithm_jobs.detail(job["pk"])

and check the job status with ``job["status"]``.

Uploading Files to Archives or Reader Studies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Prepare the list of files for each image you want to upload.

.. code:: python

    from pathlib import Path

    files = [f.resolve() for f in Path("/path/to/files").iterdir()]

Now, you can upload these files to an Archive or Reader Study which are identified by a slug.
For instance, if you would like to upload to the archive at https://grand-challenge.org/archives/radboudcovid/ you
would use ``archive="radboudcovid"``. Note that this is case sensitive.

Now you can start the upload.

.. code:: python

    session = c.upload_cases(files=files, archive="radboudcovid")

You can change ``archive`` to ``reader_study``.

You will get a session that starts the conversion of the files, and then adds the standardised images to the selected
object once it has succeeded.
You can refresh the session object with

.. code:: python

    session = c(url=session["api_url"])

and check the session status with ``session["status"]``.

Downloading Files
-----------------

An image can consist of one or multiple files, such as a single mha file or a dzi and a tiff file. You can download all files
associated with an image at once.

.. code:: python

    from pathlib import Path

    downloaded_files = c.images.download(pk="...", filename=Path("path/to/output"))

You can also use other parameters to identify the image, such as the API URL (use ``url="..."``), and you can also supply the "files" list
directly if you have already obtained the image details.

.. code:: python

    image = c.images.detail(pk="...")
    c.images.download(files=image["files"], filename=Path("path/to/output"))

Note that the filename needs to be specified without file extension. The extension is automatically added because multiple files with
different file extensions can be assosicated with an image (dzi/tif and mhd/zraw for example).

Credits
-------

This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.

.. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage


=======
History
=======

0.5.1 (2021-12-02)
------------------

* Added ``client.images.download``
* Removed deprecated ``client.raw_image_upload_session_files``

0.5.0 (2021-11-01)
------------------

* **Breaking Change** Switched the backend from ``requests`` to ``httpx``
* **Breaking Change** Removed ``client.get_algorithm(algorithm=...)``, use ``client.algorithms.detail(slug=...)`` instead
* Added ``AsyncClient`` for asynchronous interation with the Grand Challenge API
* Added option for getting objects by filters in detail view
* Added optional ``timeout`` parameter to client
* Removed deprecated ``algorithm`` argument to ``upload_cases``
* Added optional ``answer`` argument to ``upload_cases``
* Added ``archives`` endpoint
* Added ``MASK`` answertype
* Added optional `follow_redirects` argument to `Client.__call__`

0.4.0 (2021-06-01)
------------------

* Added ``run_external_job`` to execute algorithms directly
* Deprecated the ``algorithm`` argument to ``upload_cases`` which will be removed in 0.5.0, use ``run_external_job`` instead

0.3.5 (2021-03-01)
------------------

* Allow same domain calls
* Normalize API tokens

0.3.4 (2021-02-03)
------------------

* Fix number answer type support for readerstudy validation

0.3.3 (2021-02-02)
------------------

* Adds support for multiple polygon image answers

0.3.2 (2021-02-01)
------------------

* Adds support for Number answers

0.3.1 (2021-02-01)
------------------

* Adds support for Image answers
* Allows setting `content` rather than `filename` in `upload_files`

0.3.0 (2020-12-02)
------------------

* Breaking Changes in ``upload_cases``:
    * Renamed kwarg ``files_to_upload`` to ``files``
    * ``algorithm`` kwarg now takes a ``slug`` rather than a ``title``
    * Removed ``run_external_algorithm``, use ``upload_cases`` instead
* Add Multiple 2D bounding box question types to reader studies

0.2.9 (2020-09-29)
------------------

* Add support for ETDRS grid annotation endpoints

0.2.8 (2020-06-05)
------------------

* Skip validation of PATCH requests

0.2.7 (2020-05-16)
------------------

* Fixed reader study detail lookups

0.2.6 (2020-05-15)
------------------

* Note: this release has been yanked from pypi
* Added support for retina polygon annotation sets and retina single polygon annotations
* If authentication token is unset, the `GRAND_CHALLENGE_AUTHORIZATION` will be used as a fallback

0.2.5 (2020-04-24)
------------------

* Allow null answers

0.2.4 (2020-04-03)
------------------

* Added GET request params

0.2.3 (2020-03-26)
------------------

* Added ground truth endpoint for reader studies

0.2.2 (2020-03-24)
------------------

* Added support for uploading to archives and reader studies

0.2.1 (2020-03-23)
------------------

* Added Polygon and Choice question types to reader studies

0.2.0 (2020-02-09)
------------------

* Dropped Python 2.7 and 3.5
* Added support for Python 3.7 and 3.8

0.1.0 (2019-05-07)
------------------

* First release on PyPI.


