github.com/go-graphite/carbonapi@v0.17.0/expr/functions/pearson/function.go (about)

     1  package pearson
     2  
     3  import (
     4  	"context"
     5  	"math"
     6  
     7  	"github.com/dgryski/go-onlinestats"
     8  	"github.com/go-graphite/carbonapi/expr/helper"
     9  	"github.com/go-graphite/carbonapi/expr/interfaces"
    10  	"github.com/go-graphite/carbonapi/expr/types"
    11  	"github.com/go-graphite/carbonapi/pkg/parser"
    12  )
    13  
    14  type pearson struct{}
    15  
    16  func GetOrder() interfaces.Order {
    17  	return interfaces.Any
    18  }
    19  
    20  func New(configFile string) []interfaces.FunctionMetadata {
    21  	res := make([]interfaces.FunctionMetadata, 0)
    22  	f := &pearson{}
    23  	functions := []string{"pearson"}
    24  	for _, n := range functions {
    25  		res = append(res, interfaces.FunctionMetadata{Name: n, F: f})
    26  	}
    27  	return res
    28  }
    29  
    30  // pearson(series, series, windowSize)
    31  func (f *pearson) Do(ctx context.Context, eval interfaces.Evaluator, e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) {
    32  	arg1, err := helper.GetSeriesArg(ctx, eval, e.Arg(0), from, until, values)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	arg2, err := helper.GetSeriesArg(ctx, eval, e.Arg(1), from, until, values)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	if len(arg1) != 1 || len(arg2) != 1 {
    43  		return nil, types.ErrWildcardNotAllowed
    44  	}
    45  
    46  	a1 := arg1[0]
    47  	a2 := arg2[0]
    48  
    49  	windowSize, err := e.GetIntArg(2)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  
    54  	w1 := &types.Windowed{Data: make([]float64, windowSize)}
    55  	w2 := &types.Windowed{Data: make([]float64, windowSize)}
    56  
    57  	r := a1.CopyLinkTags()
    58  	r.Name = "pearson(" + a1.Name + "," + a2.Name + "," + e.Arg(2).StringValue() + ")"
    59  	r.Values = make([]float64, len(a1.Values))
    60  	r.StartTime = from
    61  	r.StopTime = r.StartTime + int64(len(r.Values))*r.StepTime
    62  
    63  	for i, v1 := range a1.Values {
    64  		v2 := a2.Values[i]
    65  
    66  		w1.Push(v1)
    67  		w2.Push(v2)
    68  		if i >= windowSize-1 {
    69  			r.Values[i] = onlinestats.Pearson(w1.Data, w2.Data)
    70  		} else {
    71  			r.Values[i] = math.NaN()
    72  		}
    73  	}
    74  
    75  	return []*types.MetricData{r}, nil
    76  }
    77  
    78  func (f *pearson) Description() map[string]types.FunctionDescription {
    79  	return map[string]types.FunctionDescription{
    80  		"pearson": {
    81  			Description: `
    82  Implementation of Pearson product-moment correlation coefficient (PMCC) function(s)
    83  
    84  .. code-block:: none
    85  
    86  	pearson( seriesA, seriesB, windowSize )
    87  
    88  
    89  Calculate Pearson score between seriesA and seriesB over windowSize.
    90  
    91  Note:
    92  Pearson will discard epochs where either series has a missing value.
    93  
    94  Additionally there is a special case where a series (or window) containing only zeros leads to a division-by-zero
    95  and will manifest as if the entire window/series had missing values.`,
    96  			Function: "pearson(seriesList, seriesList, windowSize)",
    97  			Group:    "Transform",
    98  			Module:   "graphite.render.functions.custom",
    99  			Name:     "pearsonClosest",
   100  			Params: []types.FunctionParam{
   101  				{
   102  					Name:     "seriesList",
   103  					Required: true,
   104  					Type:     types.SeriesList,
   105  				},
   106  				{
   107  					Name:     "seriesList",
   108  					Required: true,
   109  					Type:     types.SeriesList,
   110  				},
   111  				{
   112  					Name:     "windowSize",
   113  					Required: true,
   114  					Type:     types.Integer,
   115  				},
   116  			},
   117  			NameChange:   true, // name changed
   118  			ValuesChange: true, // values changed
   119  		},
   120  	}
   121  }