Background
=============

*pathology-image-features* builds off of ontology principles to standardize common processes in an image analysis pipeline, specifically
for the analysis of pathology data. This allows for better understanding how different types of quantitative metrics and processes
are related to each other, as well as preparing data for input into an RDF/graph database.

With this library, one can:

- Read annotations for whole slide images (WSIs) from a variety of formats
- Extract corresponding image regions for individual structures
- String together complicated processes with minimal coding required
- Define quantitative feature extraction pipelines with built-in documentation

Why use ontology? What is ontology?
------------------------------------

In philosophy, ontology is the study of *being* (`Wikipedia <https://en.wikipedia.org/wiki/Ontology>`_). Ontologists collaborate (and sometimes argue)
on the fundamental structure of reality and every entity within it. How different entities are defined, how they relate to one another, how
individual "instances" of an entity are differentiated, and how sub-categories of entities are distinguished all fall under the umbrella of ontology.

The highly specific nature of ontological concepts results in a highly formalized language for definitions which can be difficult for non-ontology
experts to understand. One such example of an ontology is the `Basic Formal Ontology  <https://github.com/bfo-ontology/BFO-2020>`_. As an "upper-level"
ontology, the BFO is meant to be as general as possible. This means that you won't find any specific terms relating to physical, chemical, or biological
entities where a more specific "middle-" or "lower-" level ontology would be more appropriate. The `Gene Ontology <https://github.com/geneontology>`_
is used for characterizing how individual genes are involved in specific biological processes and is useful for determining what is impacted under
experimental conditions.

Integrating ontology in Python
-------------------------------

In the context of programming, ontology principles are actually employed fairly often without people realizing it. Take a look at the following code
adapted from `Owlready2 documentation <https://owlready2.readthedocs.io/en/v0.49/intro.html>`_.

.. code-block:: python

    from restaurant.menu import Pizza
    from grocery_store.items import (
        Cheese, PizzaSauce,
        Pepperoni, Sausage,
        Olives, Peppers
    )

    class VegetarianPizza(Pizza):
        def add_topping(self, topping):
            if type(topping) in [Pepperoni,Sausage]:
                raise Exception('No meat allowed!')
            self.toppings.append(topping)

    class PepperoniAndCheesePizza(Pizza):
        def add_topping(self, topping):
            if type(topping) not in [Cheese,Pepperoni,PizzaSauce]:
                raise Exception('What part of Pepperoni and Cheese do you not understand??')
            self.toppings.append(topping)

We can clearly see that `VegetarianPizza` and `PepperoniAndCheesePizza`, while both being types of `Pizza`, are constrained in the types of toppings
that can be added to them. Using inheritance in Python, we can avoid restating a large amount of shared properties while assigning specific methods
and properties to subclasses based on their desired function or characteristics. Extending on this example, we can define which types of customers
can have which types of `Pizza` based on any dietary restrictions they might have (think `VegetarianCustomer` vs. `CarnivoreCustomer`). In OWL
(Web Ontology Language), a `VegetarianPizza` can be defined like this (from `pizza.owl  <https://github.com/owlcs/pizza-ontology/blob/master/pizza.owl>`_):

.. code-block:: xml

    <owl:Class rdf:about="#VegetarianPizza">
        <rdfs:label xml:lang="pt"
            >PizzaVegetariana</rdfs:label>
        <rdfs:comment xml:lang="en"
            >Any pizza that does not have fish topping and does not have meat topping is a VegetarianPizza. Members of this class do not need to have any toppings at all.</rdfs:comment>
        <owl:equivalentClass>
            <owl:Class>
                <owl:intersectionOf rdf:parseType="Collection">
                    <owl:Class rdf:about="#Pizza"/>
                    <owl:Class>
                        <owl:complementOf>
                            <owl:Restriction>
                                <owl:onProperty rdf:resource="#hasTopping"/>
                                <owl:someValuesFrom rdf:resource="#MeatTopping"/>
                            </owl:Restriction>
                        </owl:complementOf>
                    </owl:Class>
                    <owl:Class>
                        <owl:complementOf>
                            <owl:Restriction>
                                <owl:onProperty rdf:resource="#hasTopping"/>
                                <owl:someValuesFrom rdf:resource="#FishTopping"/>
                            </owl:Restriction>
                        </owl:complementOf>
                    </owl:Class>
                </owl:intersectionOf>
            </owl:Class>
        </owl:equivalentClass>
    </owl:Class>


Ontology in pathology image analysis
--------------------------------------

Pathology images are different from everyday, ordinary images for a variety of reasons. They are generally very high-resolution, they contain tissue
which may have a specific type of stain applied, and they sometimes contain annotations of regions of interest (ROIs). In the process of analyzing
these images, custom workflows are developed and subsequent datasets are constructed consisting of more images, annotations, or quantitative metrics.

While writing up an ontology for these different components of an image analysis workflow, we realized that it would be also be beneficial to define the
actual Python scripts which are used in the execution of these parts within the ontology. Not only would this prevent confusion in how a specific metric
is calculated, it would also provide a means for serializing a pipeline into a graph database which can be reconstructed and run on subsequent datasets.
And therefore, *pathology-image-features* was born!
