Coverage Report

Created: 2021-08-28 18:14

D:\git\skunkworks\herald-for-cpp\herald\include\herald\analysis\risk.h
Line
Count
Source (jump to first uncovered line)
1
//  Copyright 2021 Herald Project Contributors
2
//  SPDX-License-Identifier: Apache-2.0
3
//
4
5
#ifndef HERALD_RISK_H
6
#define HERALD_RISK_H
7
8
#include <cmath>
9
10
#include "aggregates.h"
11
#include "ranges.h"
12
#include "sampling.h"
13
14
namespace herald {
15
namespace analysis {
16
namespace algorithms {
17
namespace risk {
18
19
using namespace herald::analysis::aggregates;
20
21
/// A Basic sample but non scientific risk aggregation model.
22
/// Similar in function to the Oxford Risk Model, but without its calibration values and scaling.
23
/// NOT FOR PRODUCTION EPIDEMIOLOGICAL USE - SAMPLE ONLY!!!
24
struct RiskAggregationBasic {
25
  static constexpr int runs = 1;
26
27
  RiskAggregationBasic(double timeScale,double distanceScale,double minimumDistanceClamp,double minimumRiskScoreAtClamp,double logScale = 3.3598856662 ) 
28
    : run(1), timeScale(timeScale), distanceScale(distanceScale), minimumDistanceClamp(minimumDistanceClamp), 
29
      minimumRiskScoreAtClamp(minimumRiskScoreAtClamp), logScale(logScale), nMinusOne(-1.0), n(-1.0), timeMinusOne(0), time(0), riskScore(0)
30
1
  {
31
1
    ; // no other set up
32
1
  }
33
  ~RiskAggregationBasic() = default;
34
35
11
  void beginRun(int thisRun) { // 1 indexed
36
11
    run = thisRun;
37
11
    if (1 == run) {
38
11
      // clear run temporaries
39
11
      nMinusOne = -1.0;
40
11
      n = -1.0;
41
11
      timeMinusOne = 0;
42
11
      time = 0;
43
11
    }
44
11
  }
45
46
  template <typename SampleT>
47
19
  void map(const herald::analysis::sampling::Sample<SampleT>& value) {
48
19
    nMinusOne = n;
49
19
    timeMinusOne = time;
50
19
    n = value.value;
51
19
    time = value.taken.secondsSinceUnixEpoch();
52
19
  }
53
54
11
  double reduce() {
55
11
    if (-1.0 != nMinusOne) {
56
10
      // we have two values with which to calculate
57
10
      // using nMinusOne and n, and calculate interim risk score addition
58
10
      double dist = distanceScale * n;
59
10
      double t = timeScale * (time - timeMinusOne); // seconds
60
10
61
10
      double riskSlice = minimumRiskScoreAtClamp; // assume < clamp distance
62
10
      if (dist > minimumDistanceClamp) {
63
9
        // otherwise, do the inverse log of distance to get the risk score
64
9
65
9
        // don't forget to clamp at risk score
66
9
        riskSlice = minimumRiskScoreAtClamp - (logScale * std::log10(dist));
67
9
        if (riskSlice > minimumRiskScoreAtClamp) {
68
0
          // possible as the passed in logScale could be a negative
69
0
          riskSlice = minimumRiskScoreAtClamp;
70
0
        }
71
9
        if (riskSlice < 0.0) {
72
7
          riskSlice = 0.0; // cannot have a negative slice
73
7
        }
74
9
      }
75
10
      riskSlice *= t;
76
10
      
77
10
      // add it to the risk score
78
10
      riskScore += riskSlice;
79
10
    }
80
11
81
11
    // return current full risk score
82
11
    return riskScore;
83
11
  }
84
85
0
  void reset() {
86
0
    run = 1;
87
0
    riskScore = 0.0;
88
0
    nMinusOne = -1.0;
89
0
    n = -1.0;
90
0
  }
91
92
private:
93
  int run;
94
95
  double timeScale;
96
  double distanceScale;
97
  double minimumDistanceClamp;
98
  double minimumRiskScoreAtClamp;
99
  double logScale;
100
101
  double nMinusOne; // distance of n-1
102
  double n; // distance of n
103
  long timeMinusOne; // time of n-1
104
  long time; // time of n
105
106
  double riskScore;
107
};
108
109
}
110
}
111
}
112
}
113
114
#endif