Implement a new Mapper

Purpose of this Chapter

The aim of this chapter is to explain how to implement a new mapper. This will be presented by implementing a simple example. Let’s assume that we want to implement a mapper that maps probabilities to validities. Our mapper maps probabilities lower than the passed threshold to Erroneous and values greater equals than the threshold to Good. To reduce overhead, we use the autom8qc.core.validitiesStandardValidities and don’t define them by our own.

Define the Metadata of the Mapper

Note

Each mapper has to inherit from the abstract class BaseMapper and has to implement the abstract method map. Moreover, each mapper has to provide its metadata. The following metadata has to be provided by each mapper: NAME and DESCRIPTION. See also: autom8qc.mappers.base.BaseMapper

Warning

Make sure that the class name ends with the suffix Mapper. Other modules will check for the suffix to identify that the class is a mapper.

import numpy as np
import pandas as pd

from autom8qc.core import exceptions
from autom8qc.core.parameters import Parameter
from autom8qc.core.parameters import ParameterList
from autom8qc.core.validities import StandardValidities
from autom8qc.mappers.base import BaseMapper

class SimpleMapper(BaseMapper):

    NAME = "Simple Mapper"
    DESCRIPTION = "Maps probabilities greater equals than 0.5 to Good, otherwise to Erroneous"

Define the Supported Parameters

Each mapper has to provide the supported parameters. Therefore, you have to implement the static method supported_parameters. The method allows you to access the supported parameters without creating an instance of the class. If your mapper doesn’t need additional parameters you don’t have to implement it. In our case, we have the additional parameter threshold with the default value 0.5.

@staticmethod
def supported_parameters():
    return ParameterList(
        Parameter(
            name="threshold",
            description="Threshold value",
            dtype=float,
            optional=False,
            default=0.5
        )
    )

Implement the Constructor

The constructor is a method that is called when an object is created. In our case, we have to pass the parameter threshold to the constructor and store the value in the related Parameter which we defined in the method supported_parameters. Note that you don’t have to check the type of the parameters since a Parameter checks the type when you set the value. If you want to implement additional checks (e.g., the threshold must be between 0 and 1), you have to implement them in the constructor and raise an exception if a constraint is not satisfied. Finally, you have to call the super method check_metadata that checks if the instance is valid.

Warning

Make sure that you call the super constructor before assigning the parameters.

def __init__(self, threshold=0.5):
    if threshold <= 0 or threshold > 1:
        raise exceptions.InvalidValue("threshold must be between 0 and 1!")
    super().__init__()
    self.parameters["threshold"] = threshold
    self.validities = StandardValidities()
    self.check_metadata()

Implement the Abstract Method

Finally, we have to implement the abstract method map. The method takes a pd.Series as a parameter and returns the mapped values. For our example, we assume that we only support series. If a non-series will pass to the method, the method raises an error.

def map(self, probabilities):
    if not isinstance(probabilities, pd.Series):
        raise exceptions.InvalidType("probabilities must be an instance of pd.Series!")
    threshold = self.parameters["threshold"].value
    mask = probabilities[probabilities >= threshold]
    flags = pd.Series(self.validities.ERRONEOUS, index=probabilities.index)
    flags[mask] = self.validities.GOOD
    return flags