Every number carries the method that produced it

Ten published ways of computing one jump height disagree by a median 3.51 cm on 244 real trials. The training effect the source study was built to detect is 1.98 cm. plateforce records which one you used.

library(plateforce)

A trace, and the rate it was recorded at

A trial is a vector of vertical ground reaction force in newtons, and the rate it was recorded at. The rate has no default: guessing it scales every velocity, displacement, impulse and rate of force development by the ratio of the two rates.

trial <- pf_trial(rep(700, 1200), sample_rate_hz = 1200)
trial
#> 1200 samples at 1200 Hz, 1 s
#> sentinel convention none, 0 samples matching it, 0 samples carrying no number

Reading from a file works the same way, through pf_read_force_file(), which states back the delimiter it used, the column it read as force, the rows it read, the samples that matched the sentinel convention and the samples that carried no number at all. The last two are counted apart because the zero convention a vendor writes for a missing measurement is also the correct reading of an unloaded plate, so on a jump trace it matches the whole flight phase.

Naming the three rules

An analysis names the rule that establishes system weight, the rule that places the start of the jump, and the rule that places the instant of takeoff. Each is a registry identifier.

head(pf_bindings(), 4)
#>                                 id                     slot
#> 1                      filter.none conditioned_force_signal
#> 2             bwepoch.fixed_window                 weighing
#> 3 bwepoch.adaptive_lowest_variance                 weighing
#> 4         bwepoch.manual_placement                 weighing
#>                  construct
#> 1 conditioned_force_signal
#> 2            system_weight
#> 3            system_weight
#> 4            system_weight
#>                                                   title composed_from
#> 1 No conditioning before event detection or integration          <NA>
#> 2            Fixed window at the start of the recording          <NA>
#> 3                      Quietest window in the recording          <NA>
#> 4                                 Window placed by hand          <NA>
result <- analyse_countermovement_jump(
  trial,
  weighing = "bwepoch.fixed_window",
  onset = "onset.threshold.noise_relative",
  takeoff = "takeoff.threshold.absolute_force"
)

This trace is a person standing still, so the landmark rules have nothing to find, and each one says so by name and by parameter rather than returning a number anyway.

result@warnings
#> [1] "onset.threshold.noise_relative(k = 5) has no band to search: dispersion is 0 N and the threshold falls at 700 N"
#> [2] "takeoff.threshold.absolute_force(threshold_newtons = 20) found no crossing within the search bound of 1 s"

Reading a value, and what produced it

weight <- pf_value(result, "system_weight_newtons")
weight
#> 700 N  system_weight_newtons
#> bwepoch.fixed_window

The number is @value. Everything that produced it is @provenance, and the rules upstream of it are @depends_on, each with the parameters it read and where each value came from.

chain <- weight@provenance@depends_on
chain[[1]]@method_id
#> [1] "filter.none"
chain[[1]]@parameters
#> [1] name   value  source
#> <0 rows> (or 0-length row.names)

assumed means the rule supplied that value because the caller did not. State one and it is recorded as stated:

stated <- analyse_countermovement_jump(
  trial,
  weighing = "bwepoch.fixed_window",
  weighing_parameters = list(duration = 0.5),
  onset = "onset.threshold.noise_relative",
  takeoff = "takeoff.threshold.absolute_force"
)
bound <- pf_value(stated, "system_weight_newtons")@provenance@parameters
bound[bound[["name"]] == "duration", ]
#>       name value source
#> 1 duration   0.5 stated

Reading a shortened property name is an error rather than a neighbouring property’s value, and putting the object into arithmetic asks you to name the number:

weight + 1
#> Error:
#> ! a measured value carries the method that produced it. @value is the number.
weight@value
#> [1] 700

When a rule declines

A rule that cannot answer raises a condition classed by its code, so you branch on the fields rather than on the sentence.

condition <- tryCatch(
  analyse_countermovement_jump(
    trial,
    weighing = "bwepoch.fixed_window",
    onset = "onset.not.a.rule",
    takeoff = "takeoff.threshold.absolute_force"
  ),
  plateforce_refusal = identity
)
class(condition)
#> [1] "plateforce_method_not_implemented" "plateforce_refusal"               
#> [3] "plateforce_error"                  "error"                            
#> [5] "condition"
condition[["code"]]
#> [1] "method_not_implemented"

Read a field with [[, which matches the whole name. condition$method is an error here, because $ on a list matches a shortened name without saying so.

The registry

registry <- pf_registry()
registry@census
#>            population count genuine_debates can_find_wrong_event
#> 1          constructs    65              NA                   NA
#> 2 computation_entries   265             128                    5
#> 3    protocol_entries     8              NA                   NA
#> 4      preset_entries     2              NA                   NA

The populations are counted apart and never added together, and each derived count sits beside the population it was taken over. One entry reads out in full:

entry <- pf_entry("onset.threshold.noise_relative")
entry[["construct"]]
#> [1] "movement_onset"
entry[["title"]]
#> [1] "Noise-relative threshold, k standard deviations of the reference epoch"