TofuPilotTofuPilot

Multi-Dimensional

Record multi-dimensional measurement data with axis validators and aggregations for complex sensor and signal analysis in TofuPilot.

WiFi Enabled
True
x==True
Pass
Output Voltage
Pass
Output Voltage
5.02V
4.8<x<5.2
Pass

You can create a multi-dimensional measurement with measurements:

measurements:
  - name: Output Voltage
    title: Output Voltage
    x_axis: 
      legend: Time
      unit: ms
    y_axis: 
      - legend: Voltage
        unit: V

You can set the measurement value in your Python phase using the builder pattern:

def measure_voltage(measurements, dmm):
    times = []
    voltages = []

    for t in range(0, 201, 5):
        times.append(t)
        voltages.append(dmm.read_voltage())

    measurements.output_voltage.x_axis = times 
    measurements.output_voltage.y_axis.voltage = voltages 

Definition

Measurement

You can configure the measurement name and metadata.

PropertyTypeRequiredDescription
keystringNoUnique identifier for the measurement within the phase
namestringYesDisplay name (1-100 characters)
descriptionstringNoDetailed description (max 50,000 characters)
titlestringNoChart title
x_axisobjectYesX-axis specification
y_axisarrayYesArray of Y-axis specifications (one or more)

TofuPilot auto-generates the key from name (snake_case) if not specified, and uses it for Python access (e.g., measurements.frequency_response).

Axis

Each axis (x_axis or y_axis item) has the following properties:

PropertyTypeRequiredDescription
keystringNoPython identifier for axis (auto-generated from legend if not set)
legendstringNoAxis label for chart legend
unitstringNoAxis unit (e.g., "Hz", "V", "dB")
descriptionstringNoAxis description
validatorsarrayNoValidators for axis data
aggregationsarrayNoAggregations for axis data

Validators

You can add validators to each axis to check individual data points.

y_axis:
  - legend: Voltage
    unit: V
    validators: 
      - operator: "=="
        expected_value: [3.0, 3.1, 3.0, 3.1] 

Axis validators only support the == and != operators with an array of expected values matching the data length. TofuPilot will compare each data point against the corresponding expected value and set the outcome to Fail if any point fails.

Aggregations

You can add aggregations to each axis to validate statistical properties.

y_axis:
  - legend: Voltage
    unit: V
    aggregations: 
      - type: mean
        validators: 
          - operator: ">="
            expected_value: 2.9
          - operator: "<="
            expected_value: 3.1

TofuPilot will validate the aggregation value against the specified criteria. You must set the aggregation value from Python. See Aggregations for details.

Examples

Multi-Channel Waveform

We will capture waveforms from multiple channels simultaneously:

main:
  - name: Waveform Capture
    python: capture_waveform
    measurements:
      - name: Output Waveform
        description: Dual-channel oscilloscope capture
        title: Output Waveform
        x_axis:
          legend: Time
          unit: ms
        y_axis:
          - legend: Channel 1
            key: channel_1
            unit: V
          - legend: Channel 2
            key: channel_2
            unit: V
def capture_waveform(measurements, log, scope):
    log.info("Capturing waveform")

    scope.trigger()
    data = scope.get_waveform()

    measurements.output_waveform.x_axis = data['time']
    measurements.output_waveform.y_axis.channel_1 = data['channel1']
    measurements.output_waveform.y_axis.channel_2 = data['channel2']

    log.info(f"Captured {len(data['time'])} samples")

Combining Validators and Aggregations

We will measure voltage over time and validate both individual readings and overall statistics:

main:
  - name: Voltage Monitoring
    python: measure_voltage
    measurements:
      - name: Output Voltage
        description: Voltage monitoring with range and statistical validation
        title: Output Voltage
        x_axis:
          legend: Time
          unit: ms
        y_axis:
          - legend: Voltage
            unit: V
            aggregations:
              - type: min
                validators:
                  - operator: ">="
                    expected_value: 0
              - type: max
                validators:
                  - operator: "<="
                    expected_value: 5
              - type: mean
                validators:
                  - operator: ">="
                    expected_value: 2.9
                  - operator: "<="
                    expected_value: 3.1
def measure_voltage(measurements, log, dmm):
    log.info("Monitoring voltage over time")

    times = []
    voltages = []

    for t in range(0, 201, 5):
        times.append(t)
        voltages.append(dmm.read_voltage())

    measurements.output_voltage.x_axis = times
    measurements.output_voltage.y_axis.voltage = voltages

    aggs = measurements.output_voltage.y_axis.voltage.aggregations
    aggs.min = min(voltages)
    aggs.max = max(voltages)
    aggs.mean = sum(voltages) / len(voltages)

    log.info(f"Captured {len(times)} samples")

Range validation (0-5V) is done via min/max aggregations since axis validators only support == and !=. The mean aggregation validates overall statistics (2.9-3.1V). The measurement fails if any aggregation validator fails.

How is this guide?