Skip to content

Commit

Permalink
Add EDA data type and documentation on the process
Browse files Browse the repository at this point in the history
  • Loading branch information
Whathecode committed Oct 7, 2022
1 parent a650b1e commit 0b843c0
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ object CarpDataTypes : DataTypeMetaDataMap()
*/
val NON_GRAVITATIONAL_ACCELERATION = add( NON_GRAVITATIONAL_ACCELERATION_TYPE_NAME, "Acceleration without gravity", DataTimeType.POINT )

internal const val EDA_TYPE_NAME = "$CARP_NAMESPACE.eda"
/**
* Single-channel electrodermal activity, represented as skin conductance.
*/
val EDA = add( EDA_TYPE_NAME, "Electrodermal activity", DataTimeType.POINT )

internal const val ACCELERATION_TYPE_NAME = "$CARP_NAMESPACE.acceleration"
/**
* Rate of change in velocity, including gravity, along perpendicular x, y, and z axes in the device's coordinate system.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dk.cachet.carp.common.application.data

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable


/**
* Holds single-channel electrodermal activity (EDA) data, represented as skin conductance.
* Among others, also known as galvanic skin response (GSR) and skin conductance response/level.
*/
@Serializable
@SerialName( CarpDataTypes.EDA_TYPE_NAME )
data class EDA( val microSiemens: Double ) : Data
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ val COMMON_SERIAL_MODULE = SerializersModule {
subclass( AngularVelocity::class )
subclass( CompletedTask::class )
subclass( ECG::class )
subclass( EDA::class )
subclass( Geolocation::class )
subclass( HeartRate::class )
subclass( NonGravitationalAcceleration::class )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ val commonInstances = listOf(
AngularVelocity( 42.0, 42.0, 42.0 ),
CompletedTask( "Task", null ),
ECG( 42.0 ),
EDA( 42.0 ),
Geolocation( 42.0, 42.0 ),
HeartRate( 60 ),
NoData,
Expand Down
27 changes: 14 additions & 13 deletions docs/carp-common.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,20 @@ When a data type describes data over the course of a time interval, the time int

All the built-in data types belong to the namespace: **dk.cachet.carp**.

| Name | Description |
| --- | --- |
| [geolocation](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/Geolocation.kt) | Geographic location data, representing longitude and latitude. |
| [stepcount](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/StepCount.kt) | The number of steps a participant has taken in a specified time interval. |
| [ecg](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/ECG.kt) | Electrocardiogram data of a single lead. |
| [heartrate](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/HeartRate.kt) | Number of heart contractions (beats) per minute. |
| [interbeatinterval](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/InterbeatInterval.kt) | The time interval between two consecutive heartbeats. |
| [sensorskincontact](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/SensorSkinContact.kt) | Whether a sensor requiring contact with skin is making proper contact at a specific point in time. |
| [nongravitationalacceleration](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/NonGravitationalAcceleration.kt) | Acceleration excluding gravity along perpendicular x, y, and z axes. |
| [angularvelocity](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/AngularVelocity.kt) | Rate of rotation around perpendicular x, y, and z axes. |
| [signalstrength](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/SignalStrength.kt) | The received signal strength of a wireless device. |
| [triggeredtask](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/TriggeredTask.kt) | A task which was started or stopped by a trigger, referring to identifiers in the study protocol. |
| [completedtask](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/CompletedTask.kt) | An interactive task which was completed over the course of a specified time interval. |
| Name | Description |
|---------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------|
| [geolocation](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/Geolocation.kt) | Geographic location data, representing longitude and latitude. |
| [stepcount](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/StepCount.kt) | The number of steps a participant has taken in a specified time interval. |
| [ecg](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/ECG.kt) | Electrocardiogram data of a single lead. |
| [heartrate](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/HeartRate.kt) | Number of heart contractions (beats) per minute. |
| [interbeatinterval](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/InterbeatInterval.kt) | The time interval between two consecutive heartbeats. |
| [sensorskincontact](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/SensorSkinContact.kt) | Whether a sensor requiring contact with skin is making proper contact at a specific point in time. |
| [nongravitationalacceleration](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/NonGravitationalAcceleration.kt) | Acceleration excluding gravity along perpendicular x, y, and z axes. |
| [eda](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/EDA.kt) | Single-channel electrodermal activity, represented as skin conductance. |
| [angularvelocity](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/AngularVelocity.kt) | Rate of rotation around perpendicular x, y, and z axes. |
| [signalstrength](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/SignalStrength.kt) | The received signal strength of a wireless device. |
| [triggeredtask](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/TriggeredTask.kt) | A task which was started or stopped by a trigger, referring to identifiers in the study protocol. |
| [completedtask](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/CompletedTask.kt) | An interactive task which was completed over the course of a specified time interval. |

## Device configurations

Expand Down
30 changes: 30 additions & 0 deletions docs/development-checklists.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,33 @@ These generated test resources will be used to verify the migrations (step 3) of
5. Update the affected JSON schemas. At a minimum you will need to change the request object's API version (e.g., `StudyServiceRequest.json`).
These schemas are useful for non-Kotlin clients.
If you forget to do this, `JsonSchemasTest` will fail; this test validates generated JSON output, known to be correct, using the schemas.

## Add a new measure data type

Keep in mind that CARP data types should be device-agnostic.
The goal is that they can be reused for devices by different vendors.
They act as a common data format.
Therefore, don't include device-specific information in new [`Data`](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/application/data/Data.kt) types.

If device-specific data is needed, infrastructures built using CARP Core can still specify these in their own codebase.
Furthermore, all [extendable domain objects](../docs/carp-protocols.md#extending-domain-objects) can be uploaded to CARP backends that [use the recommended CARP serializers](../docs/serialization.md#unknownpolymorphicserializer-deserializing-unknown-types);
they don't need the types at compile time or runtime, although then the data won't be validated on upload.

Failing tests and static code analysis (`detektPasses`) will guide you to make sure newly introduced data types are immutable, serializable, registered, and tested.
But, below are the necessary steps to follow:

1. Add data type meta data to `CarpDataTypes`, following the template of existing data types.
2. Add a new class extending from `Data` (or object in case the measure contains no data) to the `dk.cachet.carp.common.application.data` namespace in the `carp.common` subsystem (e.g., `AngularVelocity`).
- Make sure to name the class after the collected _data_, and not the _sensor_ which collects the data (e.g., `AngularVelocity` vs `Gyro`).
- Add clear KDoc documentation on how the data should be interpreted.
For data fields, use/document SI units wherever appropriate, and choose sufficiently precise units so that no data is lost when unit conversions from raw data to the `Data` are done.
- Ensure that the class is immutable (contains no mutable fields) and is a `data class` or `object`.
- Make the class serializable using `kotlinx.serialization`.
For basic types, this should be as easy as marking it as `@Serializable`.
- Specify `@SerialName` using the data type specified in step 1.
3. Register the new data type for polymorphic serialization in [`COMMON_SERIAL_MODULE`](../carp.common/src/commonMain/kotlin/dk/cachet/carp/common/infrastructure/serialization/Serialization.kt).
4. Add a test instance of the new `Data` type to [`commonInstances`](../carp.common/src/commonTest/kotlin/dk/cachet/carp/common/application/TestInstances.kt).
5. Include the data type [in the README](../docs/carp-common.md#data-types).
6. Add a JSON schema in [`rpc/schemas/common/data`](../rpc/schemas/common/data) corresponding to the class name (e.g., `AngularVelocity.json`).
- _Warning_: the presence or validity of this schema [is not yet tested](https://github.com/imotions/carp.core-kotlin/issues/404).
It is recommended to serialize an instance of the new data type (e.g., by running a slightly modified polymorphic serialization test in `DataSerializationTest`) and [validate the output manually for now](https://www.jsonschemavalidator.net/).
10 changes: 10 additions & 0 deletions rpc/schemas/common/data/EDA.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"type": "object",
"properties": {
"__type": { "const": "dk.cachet.carp.eda" },
"microSiemens": { "type": "number" }
},
"required": [ "__type", "microSiemens" ],
"additionalProperties": false
}

0 comments on commit 0b843c0

Please sign in to comment.