Measures and data
Where in the repo
Section titled “Where in the repo”| File | What is in it |
|---|---|
domain/core/data.dart |
FileData, CompletedAppTask |
domain/core/data_types.dart |
CamsDataTypes: the CAMS data type registry |
domain/core/sampling_configurations.dart |
How often and how long a measure samples |
Measures
Section titled “Measures”A Measure defines what to measure. A measure specify the type of data to collect, which on runtime maps to a specific probe that can collect this type of data.
Since CAMS follows a reactive programming model, all sampled data is collected in streams by listening to the underlying sensors. This is configured using the Measure class.
However, some probes need to ‘poll’ data, and such probes need to be configured with a sampling frequency.
For example, the MemoryProbe needs to be configured with a sampling frequency. For this purpose, the IntervalSamplingConfiguration is used in the sampling schema (see below).
This low-level configuration is, however, often irrelevant to most of the users of CAMS and can therefore be handled via a so-called SamplingConfiguration. In the code listing below, the common sampling schema is used to get a set of measures with the most ‘common’ configuration. Sampling schemes are further described below.
Measure type format
Section titled “Measure type format”The dataType property of a Measure specify what type of data to collect.
The string version is typically a namespace + name. CAMS-native measure types have the namespace dk.cachet.carp and the name is the measure type:
dk.cachet.carp.<type>The different types is specified in the tables below.
Event-based vs. one-time measures
Section titled “Event-based vs. one-time measures”Most measures are event-based (EB), i.e., once triggered and started, they continuously sample data from their sensor until explicitly stopped. For example, collecting a step event every time a step is detected on the phone. However, some measures are one-time (OT), i.e., sampling one piece of data when triggered. For example, collecting weather data from the Open Weather API.
It is important to know the type (EB vs. OT) of a measure since an event-based measure can be started and run until stopped, whereas a one-time measure needs to be triggered to sample data. This can, for example, be done periodically using appropriate triggers, like the PeriodicTrigger.
The difference when specifying the study protocol is illustrated below. The first task added to the protocol contains a one-time measure (device info), which is triggered only once. The second task contains a set of event-based measures that are triggered to start immediately and keep sampling data based on events. The third task collects weather (one-time measure) periodically every 5 minutes.
// Collect device info only once, when this study is deployed. protocol.addTaskControl( OneTimeTrigger(), BackgroundTask( measures: [Measure(type: DeviceSamplingPackage.DEVICE_INFORMATION)]), phone, );
// Immediately start collecting step count, ambient light, screen activity, and // battery level events. All event-based measures. protocol.addTaskControl( ImmediateTrigger(), BackgroundTask(measures: [ Measure(type: SensorSamplingPackage.STEP_EVENT), Measure(type: SensorSamplingPackage.AMBIENT_LIGHT), Measure(type: DeviceSamplingPackage.SCREEN_EVENT), Measure(type: DeviceSamplingPackage.BATTERY_STATE), ]), phone, );
// Add a background task that collects weather every 5 minutes. protocol.addTaskControl( PeriodicTrigger(period: Duration(minutes: 5)), BackgroundTask( measures: [Measure(type: ContextSamplingPackage.WEATHER)]), weatherService);Each SamplingPackage provides a list of what types of measures it supports using the dataTypes property.
Each sampling package also comes with a default sampling schema for each of its measure types.
Sampling configuration and schemas
Section titled “Sampling configuration and schemas”CAMS comes with a set of default sampling configurations for all measures. These configurations are collected in DataTypeSamplingScheme schemas for each sampling package.
For example, the SensorSamplingPackage provides a map of default samplingSchemes for the measures included in this package.
However, if you want to change these default configurations, they can be overridden.
For example, the default configuration of the light measure is 10 seconds sampling every 5 minutes. This configuration can be “overridden” using the overrideSamplingConfiguration property of a measure:
// Override the sampling configuration of the light measure in the protocol. protocol.addTaskControl( ImmediateTrigger(), BackgroundTask( measures: [ Measure(type: SensorSamplingPackage.AMBIENT_LIGHT) ..overrideSamplingConfiguration = PeriodicSamplingConfiguration( interval: const Duration(minutes: 10), duration: const Duration(seconds: 20), ), ], ), phone, );Measurements and data
Section titled “Measurements and data”CAMS models data according to the data sub-system of the CARP Core domain model. Data collected during sampling is modeled as a Measurement, which holds a Data object of a specific DataType.
In CAMS, all data objects are of type Data. For example, the BatteryState holds the state of the phone’s battery, like battery level and charging status.
A data object is either measured at a point in time or a time span.
All measurement and data objects can be serialized to/from JSON:
The sensorStartTime property is the timestamp of the measurement (in microseconds) and the __type property holds the data type.
{ "sensorStartTime": 1700082464783244, "data": { "__type": "dk.cachet.carp.batterystate", "batteryLevel": 92, "batteryStatus": "charging" }}Since ambient light is measured over a time period, both sensorStartTime and sensorEndTime is specified.
{ "sensorStartTime": 1700082626178562, "sensorEndTime": 1700082636184268, "data": { "__type": "dk.cachet.carp.ambientlight", "meanLux": 20.76923076923077, "stdLux": 0.6965680875490359, "minLux": 20, "maxLux": 22 }The list of measure types you can use is on Available packages.