Conditioning API¶
Auto-generated from docstrings.
ecgen.conditioning.composite¶
Combining several field encoders into one :class:~ecgen.types.ConditionOutput,
with per-field condition dropout (for classifier-free guidance).
CompositeConditioner
¶
Bases: Module
Encodes condition fields into the vector / tokens / dense slots.
- vector encoders are projected to
vector_dimand summed; - token encoders are projected to
token_dimand concatenated along N; - dense encoders are concatenated along channels.
Config (also stored in model hyperparameters)::
conditioning:
vector_dim: 256
token_dim: 256
encoders:
- {field: measurements, name: numeric, params: {num_features: 9}}
- {field: obs, name: masked_signal, params: {num_leads: 12}}
dropout: {measurements: 0.1} # per-field drop probability in training
A dropped or absent field is replaced by a learned null embedding
(vector: one [vector_dim] row per field; tokens: one null token;
dense: everything unobserved). The same null is used for the
unconditional pass of classifier-free guidance (drop="all").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
encoders
|
Sequence[Mapping[str, Any]]
|
Specs |
required |
vector_dim
|
int
|
Size of the combined global vector. |
256
|
token_dim
|
int
|
Size of each token. |
256
|
dropout
|
Optional[Mapping[str, float]]
|
Per-field drop probability during training. |
None
|
Source code in src/ecgen/conditioning/composite.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | |
forward
¶
forward(cond: Optional[Mapping[str, Tensor]] = None, cond_missing: Optional[Mapping[str, Tensor]] = None, obs: Optional[Tensor] = None, obs_mask: Optional[Tensor] = None, batch_size: Optional[int] = None, drop: Drop = None) -> ConditionOutput
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cond
|
Optional[Mapping[str, Tensor]]
|
Normalized condition fields; a missing key means "not given". |
None
|
cond_missing
|
Optional[Mapping[str, Tensor]]
|
Per-field missing masks. |
None
|
obs
|
Optional[Tensor]
|
Partially observed ECG |
None
|
obs_mask
|
Optional[Tensor]
|
Mask of |
None
|
batch_size
|
Optional[int]
|
Needed when no field is given at all. |
None
|
drop
|
Drop
|
|
None
|
Source code in src/ecgen/conditioning/composite.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | |
build_conditioner
¶
None / empty spec → None (unconditional).
ecgen.conditioning.encoders¶
Field encoders: one condition field → one :class:ConditionOutput slot.
Each encoder declares slot ("vector", "tokens" or "dense") and
out_dim (feature size, or channels for dense). forward gets the field's
value and its missing mask (None if the field has none) and returns:
- vector:
[B, out_dim] - tokens:
([B, N, out_dim], mask [B, N] bool) - dense:
[B, out_dim, T]
CategoricalEncoder
¶
Bases: FieldEncoder
Single class label [B] (int) → embedding [B, dim].
A missing label (mask True, or value < 0) maps to a learned
"unknown" embedding.
Source code in src/ecgen/conditioning/encoders.py
MultiLabelEncoder
¶
Bases: FieldEncoder
Multi-hot labels [B, L] → [B, dim] (linear projection, SSSD-ECG style),
or with as_tokens=True one token per present label for cross-attention.
Missing labels (mask [B, L]) are treated as absent.
Source code in src/ecgen/conditioning/encoders.py
NumericEncoder
¶
Bases: FieldEncoder
Normalized numeric features [B, F] with a missing mask → [B, dim].
The MLP sees (value * observed, missing), so missingness is explicit.
With as_tokens=True each feature becomes one token
value * w_f + b_f (or a learned missing token), for cross-attention.
Source code in src/ecgen/conditioning/encoders.py
FourierScalarEncoder
¶
Bases: FieldEncoder
Numeric features [B, F] → random Fourier features → MLP [B, dim].
Source code in src/ecgen/conditioning/encoders.py
MaskedSignalEncoder
¶
Bases: FieldEncoder
Partially observed ECG → dense [B, 2C, T] = [x * mask, mask].
Reads obs / obs_mask (not a cond field). With channels set,
a 1x1 conv projects to that many channels.
Source code in src/ecgen/conditioning/encoders.py
ecgen.nn.injection¶
Layers that inject a condition into a backbone.
All modulation layers are zero-initialised, so a freshly built conditional network computes exactly what its unconditional counterpart would; the condition's influence is learned from there.
Shapes: signals/feature maps are [B, C, T], global conditions [B, D],
token conditions [B, N, D].
ConcatInput
¶
Bases: Module
Module form of :func:concat_dense; out_channels = in_channels + cond_channels.
Source code in src/ecgen/nn/injection.py
FiLM
¶
Bases: Module
h * (1 + gamma(c)) + beta(c) per channel.
Source code in src/ecgen/nn/injection.py
AdaGN
¶
Bases: Module
GroupNorm, then FiLM from the condition (zero-initialised, so it starts as plain GroupNorm).
Source code in src/ecgen/nn/injection.py
AdaLNZero
¶
Bases: Module
DiT-style adaptive LayerNorm for [B, N, D] tokens.
forward returns (modulated_x, gate); the block adds
gate * f(modulated_x) to its residual. Gates start at 0.
Source code in src/ecgen/nn/injection.py
AddToTimeEmb
¶
Bases: Module
Project a global condition and add it to the time embedding.
Source code in src/ecgen/nn/injection.py
CrossAttention1d
¶
Bases: Module
Feature map [B, C, T] attends to condition tokens [B, N, D].
Residual: x + out(attn(norm(x), tokens)), with out zero-initialised.
Source code in src/ecgen/nn/injection.py
concat_dense
¶
ConcatInput: stack time-aligned conditions onto the input channels.
Source code in src/ecgen/nn/injection.py
ecgen.nn.embeddings¶
Embeddings for diffusion time steps and continuous scalars.
TimestepEmbedding
¶
Bases: Module
Sinusoidal embedding followed by a 2-layer MLP (DDPM / ADM style).
Source code in src/ecgen/nn/embeddings.py
FourierFeatures
¶
Bases: Module
Random Fourier features of scalars: [B, F] -> [B, F * 2 * n_freqs].
Frequencies are fixed (a buffer), drawn once with a fixed seed so models built twice from the same config are identical.
Source code in src/ecgen/nn/embeddings.py
sinusoidal_embedding
¶
Transformer-style sinusoidal embedding of (possibly fractional) positions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t
|
Tensor
|
|
required |
dim
|
int
|
Embedding size. |
required |
Returns:
| Type | Description |
|---|---|
Tensor
|
|
Source code in src/ecgen/nn/embeddings.py
ecgen.data.masks¶
Observation masks for partial-ECG conditioning (lead reconstruction, imputation, forecasting).
A mask generator is called once per sample with the signal shape and returns
an obs_mask [C, T] float tensor, 1 = observed. The data module attaches
it to the batch (ECGBatch.obs_mask); models condition on
signal * obs_mask and (optionally) compute the loss on the unobserved part.
Config (data.masks)::
masks: {name: lead_subset, params: {keep: [[I], [I, II], [II, V1]]}}
masks:
name: mixture
params:
components:
- {weight: 0.5, name: lead_subset, params: {keep: [[I]]}}
- {weight: 0.3, name: time_span, params: {min_frac: 0.1, max_frac: 0.5}}
- {weight: 0.2, name: none}
MaskGenerator
¶
Base class; subclasses implement :meth:__call__.
Source code in src/ecgen/data/masks.py
FullyObserved
¶
Bases: MaskGenerator
Everything observed (also: the "unconditional" branch of a mixture).
Source code in src/ecgen/data/masks.py
FullyUnobserved
¶
Bases: MaskGenerator
Nothing observed: plain generation, when mixed with partial masks.
Source code in src/ecgen/data/masks.py
LeadSubset
¶
Bases: MaskGenerator
Observe whole leads.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keep
|
Optional[Sequence[Sequence[str]]]
|
List of lead-name lists; one is chosen uniformly per sample
(e.g. |
None
|
min_leads
|
int
|
Smallest random subset. |
1
|
max_leads
|
int
|
Largest random subset. |
3
|
Source code in src/ecgen/data/masks.py
TimeSpan
¶
Bases: MaskGenerator
Hide n_spans contiguous segments (all leads) covering min_frac..max_frac
of the record in total — imputation.
Source code in src/ecgen/data/masks.py
Forecast
¶
Bases: MaskGenerator
Observe the first min_frac..max_frac of the record; predict the rest.
Source code in src/ecgen/data/masks.py
RandomPoints
¶
Bases: MaskGenerator
Each sample point observed independently with probability p_observed.
Source code in src/ecgen/data/masks.py
Mixture
¶
Bases: MaskGenerator
Pick one component per sample with probability proportional to weight.
Source code in src/ecgen/data/masks.py
build_mask
¶
Build a mask generator from {name | target, params} (weight is ignored).