MedSignals / Unified Signals
MedSignals is an internal class in MedRepository that defines signal types and manages .signals
files—dictionaries mapping signal names to their properties. Each MedRepository instance has a sigs
object for basic .signals
operations. All signal definitions are found in MedSignals.h
.
When initializing a repository, one of the first steps is to read the signals configuration file (specified in the repository config) and set up all signal definitions.
What is a signal?
A signal type is a class defined in MedSignals.h
and acts as a placeholder for signals. Signals represent actual data stored in the repository, each with a specific type. For example:
- BYEAR, GENDER, TRAIN: Store a single float value, typically using the
SVal
type, or as a generic signal with one integer value channel: "V(i)" - Hemoglobin, Creatinine: Store a date and a float value, using
SDateVal
orSTimeVal
, or as a generic signal with one integer time channel and one float value channel: "T(i),V(f)" - BP: Stores a date and two short values (diastolic and systolic blood pressure), using
SDateShort2
, or as a generic signal: "T(i),V(s,s)"
Each signal has several properties, defined in the SignalInfo
class:
- name: Signal name
- type: Type code (from the
SigType
enum) or a generic type string. You can useget_signal_generic_spec()
onUniversalSigVec
to get its generic signal string representation. - sid: Unique integer signal ID from the signals config file, used for fast indexing and efficient access. Maximum SID is
MAX_SID_NUM
(currently 100,000). - bytes_len: Number of bytes needed to store one element.
- n_time_channels: Number of time channels.
- n_val_channels: Number of value channels.
Signals must currently have a fixed size.
Unified Signals - Part I
Most medical record signals can be described as having zero or more time channels and zero or more value channels. Examples:
- BYEAR: 0 time channels, 1 float value channel
- Creatinine: 1 integer time channel, 1 float value channel
- BP: 1 integer time channel, 2 float value channels
- DM_Registry: 2 integer time channels, 1 int/char value channel
When time channels are integers and value channels are floats, signals can be accessed in a unified way, regardless of their type. This allows for generalized code in components like RepProcessors
and FeatureGenerators
in MedProcessTools.
See Part II for usage examples.
Current Signal Types
All signal types are defined in MedSignals.h
. Available types include:
Signal Type | Time Channels | Value Channels | Placeholders | Example Signals |
---|---|---|---|---|
SVal | 0 | 1 | float | BYEAR, TRAIN, GENDER |
SDateVal | 1 | 1 | int : float | Hemoglobin, Creatinine |
STimeVal | 1 | 1 | long long : float | Creatinine (mimic) |
SDateRangeVal | 2 | 1 | int, int : float | DM_Registry |
STimeRangeVal | 2 | 1 | long long, long long : float | (mimic) |
STimeStamp | 0 | 1 | : long long | (mimic) |
SDateVal2 | 1 | 2 | int : float, unsigned short | Drugs (MHS) |
STimeLongVal | 1 | 1 | long long : long long | (mimic) |
SDateShort2 | 1 | 2 | int : short, short | BP |
SValShort2 | 0 | 2 | : short, short | (mimic) |
SValShort4 | 0 | 4 | : short, short, short, short | (mimic) |
Adding a New Signal Type
To add a new legacy signal type:
- Add an enum value for the type (used for encoding in the signals file).
- Define the signal class and its methods.
- Update
MedConvert
to read the new signal type (add parsing logic if needed). - Make sure the new signal class inherits from
UnifiedSig
for unified signal compatibility. - Implement these methods:
-
n_time_channels()
-n_val_channels()
-time_unit()
-int Time(int chan)
-float Val(int chan)
-SetVal(chan, _val)
-Set(int *times, float *vals)
- Comparison operators (<
,==
) - Output operator (<<
)
Unified Signals - Part II
To work with unified signals, use the UniversalSigVec
(usv
) class. Instead of the standard get()
method, use uget()
to load signal data into a usv
object. Key features:
- Initialize for a specific signal type using only the enum.
- Use
uget()
to load data (no copies; uses pointers and virtual functions). - Access any time or value channel uniformly across all signal types.
This lets you write type-independent code. Initialization has a performance cost, but repeated use with the same type is efficient.
Example Usage
Signals Config File
For details on the signals file