Short version: in regulation mode you do not call calibrate() — the runtime learns each channel’s drive direction from your measurements automatically. calibrate() exists for optimization mode, where there is no per-channel sensitivity probe.
At the start of a regulation session the runtime spends a few rounds applying a small probe to each control and measuring which way the observable moves. It then drives every channel using the measured sign and magnitude. Reversed polarity, negative gain, per-channel sign differences, and targets that cross zero are all handled with no extra code — the only requirement is local monotonicity over your operating range. See Regulation & tracking for the worked example.
In optimization mode the runtime steers the configuration toward an elite-weighted target in measurement space; it does not run a per-channel drive-direction probe. If your control→observable map is sign-flipped relative to the default contract (the default assumes a response like -0.5·sin(φ)), a one-time calibration lets the optimizer step the right way. Call it once, before start():
copyfrom swc import SWCOptimizer
opt = SWCOptimizer(license_key="EVAL-...", n=N) # optimization mode (default)
# Probe each control +/- eps once and record which way the measured
# statistic actually moves. Use the cleanest measurement you can afford.
signs = opt.calibrate(measure=lambda x: read_output(x), x0=start_config)
print("per-channel drive signs:", signs) # e.g. [1.0, -1.0, 1.0, 1.0]
x = opt.start(start_config)
for _ in range(rounds):
x = opt.step(read_output(x), score=objective(x))
opt.end()calibrate(measure, x0, eps=0.10, conf_thresh=0.12) → list of per-channel signs (+1.0 or -1.0).
Returns the detected signs in both modes; applies them only in optimization mode. In regulation mode the return value is informational and the loop ignores it.
If you are unsure whether the runtime is the right tool at all, run the envelope check first.