# `Monty.Frameworks.Models.EvidenceMatching.FeatureEvidence.Calculator.FeatureEvidenceCalculator`
[🔗](https://github.com/d-led/ex.tbp.monty/blob/v0.1.0/packages/ex_tbp_monty_core/lib/monty/frameworks/models/evidence_matching/feature_evidence/calculator/feature_evidence_calculator.ex#L1)

What a feature-evidence calculator has to be able to do.

Mirrors
`tbp/monty/frameworks/models/evidence_matching/feature_evidence/calculator.py::FeatureEvidenceCalculator`,
which is a `Protocol`: any object with a `calculate` of this shape can be used
as one. In Elixir that is a behaviour, and the hypotheses updater takes the
calculator as a module, so an experiment can substitute its own — Monty's
dependency injection, kept.

## Shapes

`channel_feature_array` is one row per node, one column per stored feature
value; `channel_feature_order` names the features in the order their columns
appear. A multi-valued feature (`hsv` with three values) occupies three
columns, and how many is read from the *query* features' values — that is the
only place the length is written down, exactly as in Python.

`pose_vectors` and `pose_fully_defined` are not feature evidence: they are
compared as poses elsewhere and occupy no columns here.

# `feature_values`

```elixir
@type feature_values() :: number() | [number()]
```

# `row`

```elixir
@type row() :: [float() | nil]
```

# `tolerance`

```elixir
@type tolerance() :: number() | [number()]
```

# `calculate`

```elixir
@callback calculate(
  channel_feature_array :: [row()],
  channel_feature_order :: [String.t()],
  channel_feature_weights :: %{optional(String.t()) =&gt; number()},
  channel_query_features :: %{optional(String.t()) =&gt; feature_values()},
  channel_tolerances :: %{optional(String.t()) =&gt; tolerance()}
) :: [float() | nil]
```

Evidence in `[0, 1]` for every node in the graph, or `nil` where a node's
stored values are missing.

`nil` is this port's NaN: a value that is not a number is not a score, and
callers must decide what a node without data means rather than have a
comparison quietly go one way.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
