Source code for raidnr.manager.remapper


# ---------------------------------------------------
# ¦¦¦¦¦¦¦    ¦¦¦¦¦   ¦¦¦¦  ¦¦¦¦¦¦¦¦  
#  ¦¦   ¦¦  ¦¦   ¦¦   ¦¦    ¦¦   ¦¦¦   
#  ¦¦¦¦¦¦   ¦¦¦¦¦¦¦   ¦¦    ¦¦   ¦¦¦   
#  ¦¦   ¦¦  ¦¦   ¦¦   ¦¦    ¦¦   ¦¦¦  
# ¦¦¦   ¦¦¦ ¦¦   ¦¦¦ ¦¦¦¦  ¦¦¦¦¦¦¦¦    
# ---------------------------------------------------
# Bryden Wood
# License: MIT, see full license in LICENSE.txt
# Web: repository-link
#-----------------------------------------------------
# Date: 30.09.2019
# Authors: Claudio Campanile
#-----------------------------------------------------
# Description
#-----------------------------------------------------
# Remapper class to relate topographic metrics to an evaluation value
#-----------------------------------------------------
# Docs Reference : link to module docs
#-----------------------------------------------------

# modules
import numpy as np
from json import JSONEncoder
import json


class Remapper(object):
    
    def __init__(self, thresholds, default_val=0., min_v=0., max_v=1.0, trend='linear'):
        """ Callable class to remap a quantity (alignment metric) to a range.

        Parameters
        ----------
        thresholds : dict
            {weight:[val1,val2],...}

        default_val : float
            [optional] to replace nans
        
        min_v : float
            minimum value
        
        max_v : float
            maximum value
        
        trend : str
            [optional] default='linear'. Either 'linear' or 'exp', to remap weights linearly or exponentially
        """
        assert(trend=='linear' or trend=='exp'),"trend must be 'linear' or 'exp', got {}".format(trend)
        self.thresholds = thresholds
        self.default_val = default_val
        self.trend = trend
        self.min_v = min_v
        self.max_v = max_v


    def __call__(self, value):
        """ Remap a value acocrdingly to remapping parameters

        Parameters
        ----------
        value : float
            represent a metric

        Returns
        -------
        float
            remapped from metric value to defined range as per self.thresholds
        """
        if np.isnan(value):
            value=self.default_val
        assert(value>=self.min_v and value<=self.max_v),"Curvature must be between 0. and 1., got {}".format(value)
        
        weight=0.1
        for w,iv in self.thresholds.items():
            if value < iv[0] and value > iv[1]:
                weight += w
                break
        if self.trend=='exp':
            return np.exp(weight)
        elif self.trend=='linear':
            return weight
        else:
            raise Exception("trend must be 'linear' or 'exp', got {}".format(self.trend))


[docs]class RemapperEncoder(JSONEncoder): # Encode a Remapper object
[docs] def default(self, object): if isinstance(object, Remapper): return object.__dict__ else: return JSONEncoder.default(self, object)