tnfr 4.3.0__py3-none-any.whl → 4.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tnfr might be problematic. Click here for more details.

tnfr/__init__.py CHANGED
@@ -8,10 +8,10 @@ Ecuación nodal:
8
8
  ∂EPI/∂t = νf · ΔNFR(t)
9
9
  """
10
10
 
11
- __version__ = "4.3.0"
11
+ __version__ = "4.5.1"
12
12
 
13
13
  # Re-exports de la API pública
14
- from .dynamics import step, run, set_delta_nfr_hook, validate_canon
14
+ from .dynamics import step, run, set_delta_nfr_hook, validate_canon
15
15
  from .ontosim import preparar_red
16
16
  from .observers import attach_standard_observer, coherencia_global, orden_kuramoto
17
17
  from .gamma import GAMMA_REGISTRY, eval_gamma, kuramoto_R_psi
@@ -22,23 +22,44 @@ from .sense import (
22
22
  push_sigma_snapshot, sigma_series, sigma_rose,
23
23
  register_sigma_callback,
24
24
  )
25
- from .metrics import (
26
- register_metrics_callbacks,
27
- Tg_global, Tg_by_node,
28
- latency_series, glifogram_series,
29
- glyph_top, glyph_dwell_stats, export_history,
30
- )
25
+ from .metrics import (
26
+ register_metrics_callbacks,
27
+ Tg_global, Tg_by_node,
28
+ latency_series, glifogram_series,
29
+ glyph_top, glyph_dwell_stats, export_history,
30
+ )
31
+ from .operators import aplicar_remesh_red_topologico
31
32
  from .trace import register_trace
32
33
  from .program import play, seq, block, target, wait, THOL, TARGET, WAIT, ejemplo_canonico_basico
33
34
  from .cli import main as cli_main
34
35
  from .scenarios import build_graph
35
36
  from .presets import get_preset
36
37
  from .types import NodeState
38
+ from .structural import (
39
+ create_nfr,
40
+ Operador,
41
+ Emision,
42
+ Recepcion,
43
+ Coherencia,
44
+ Disonancia,
45
+ Acoplamiento,
46
+ Resonancia,
47
+ Silencio,
48
+ Expansion,
49
+ Contraccion,
50
+ Autoorganizacion,
51
+ Mutacion,
52
+ Transicion,
53
+ Recursividad,
54
+ OPERADORES,
55
+ validate_sequence,
56
+ run_sequence,
57
+ )
37
58
 
38
59
 
39
60
  __all__ = [
40
- "preparar_red",
41
- "step", "run", "set_delta_nfr_hook", "validate_canon",
61
+ "preparar_red",
62
+ "step", "run", "set_delta_nfr_hook", "validate_canon",
42
63
 
43
64
  "attach_standard_observer", "coherencia_global", "orden_kuramoto",
44
65
  "GAMMA_REGISTRY", "eval_gamma", "kuramoto_R_psi",
@@ -51,11 +72,19 @@ __all__ = [
51
72
  "register_trace",
52
73
  "Tg_global", "Tg_by_node",
53
74
  "latency_series", "glifogram_series",
54
- "glyph_top", "glyph_dwell_stats",
55
- "export_history",
75
+ "glyph_top", "glyph_dwell_stats",
76
+ "export_history",
77
+ "aplicar_remesh_red_topologico",
56
78
  "play", "seq", "block", "target", "wait", "THOL", "TARGET", "WAIT",
57
79
  "cli_main", "build_graph", "get_preset", "NodeState",
58
80
  "ejemplo_canonico_basico",
81
+ "create_nfr",
82
+ "Operador", "Emision", "Recepcion", "Coherencia", "Disonancia",
83
+ "Acoplamiento", "Resonancia", "Silencio", "Expansion", "Contraccion",
84
+ "Autoorganizacion", "Mutacion", "Transicion", "Recursividad",
85
+ "OPERADORES", "validate_sequence", "run_sequence",
59
86
  "__version__",
60
87
  ]
61
88
 
89
+
90
+
tnfr/cli.py CHANGED
@@ -26,6 +26,7 @@ from .dynamics import step, _update_history, default_glyph_selector, parametric_
26
26
  from .gamma import GAMMA_REGISTRY
27
27
  from .scenarios import build_graph
28
28
  from .presets import get_preset
29
+ from .config import apply_config
29
30
 
30
31
 
31
32
  def _save_json(path: str, data: Any) -> None:
@@ -91,8 +92,16 @@ def _attach_callbacks(G: nx.Graph) -> None:
91
92
 
92
93
  def cmd_run(args: argparse.Namespace) -> int:
93
94
  G = build_graph(n=args.nodes, topology=args.topology, seed=args.seed)
95
+ if getattr(args, "config", None):
96
+ apply_config(G, args.config)
94
97
  _attach_callbacks(G)
95
98
  validate_canon(G)
99
+ if args.dt is not None:
100
+ G.graph["DT"] = float(args.dt)
101
+ if args.integrator is not None:
102
+ G.graph["INTEGRATOR_METHOD"] = str(args.integrator)
103
+ if getattr(args, "remesh_mode", None):
104
+ G.graph["REMESH_MODE"] = str(args.remesh_mode)
96
105
  gcanon = dict(DEFAULTS["GRAMMAR_CANON"])
97
106
  gcanon.update(_args_to_dict(args, prefix="grammar."))
98
107
  if hasattr(args, "grammar_canon") and args.grammar_canon is not None:
@@ -120,10 +129,25 @@ def cmd_run(args: argparse.Namespace) -> int:
120
129
  if args.export_history_base:
121
130
  export_history(G, args.export_history_base, fmt=args.export_format)
122
131
 
132
+ # Resúmenes rápidos (si están activados)
133
+ if G.graph.get("COHERENCE", DEFAULTS["COHERENCE"]).get("enabled", True):
134
+ Wstats = G.graph.get("history", {}).get(
135
+ G.graph.get("COHERENCE", DEFAULTS["COHERENCE"]).get("stats_history_key", "W_stats"), []
136
+ )
137
+ if Wstats:
138
+ print("[COHERENCE] último paso:", Wstats[-1])
139
+ if G.graph.get("DIAGNOSIS", DEFAULTS["DIAGNOSIS"]).get("enabled", True):
140
+ last_diag = G.graph.get("history", {}).get(
141
+ G.graph.get("DIAGNOSIS", DEFAULTS["DIAGNOSIS"]).get("history_key", "nodal_diag"), []
142
+ )
143
+ if last_diag:
144
+ sample = list(last_diag[-1].values())[:3]
145
+ print("[DIAGNOSIS] ejemplo:", sample)
146
+
123
147
  if args.summary:
124
148
  tg = Tg_global(G, normalize=True)
125
149
  lat = latency_series(G)
126
- print("Top glifos por Tg:", glyph_top(G, k=5))
150
+ print("Top operadores por Tg:", glyph_top(G, k=5))
127
151
  if lat["value"]:
128
152
  print("Latencia media:", sum(lat["value"]) / max(1, len(lat["value"])) )
129
153
  return 0
@@ -131,8 +155,16 @@ def cmd_run(args: argparse.Namespace) -> int:
131
155
 
132
156
  def cmd_sequence(args: argparse.Namespace) -> int:
133
157
  G = build_graph(n=args.nodes, topology=args.topology, seed=args.seed)
158
+ if getattr(args, "config", None):
159
+ apply_config(G, args.config)
134
160
  _attach_callbacks(G)
135
161
  validate_canon(G)
162
+ if args.dt is not None:
163
+ G.graph["DT"] = float(args.dt)
164
+ if args.integrator is not None:
165
+ G.graph["INTEGRATOR_METHOD"] = str(args.integrator)
166
+ if getattr(args, "remesh_mode", None):
167
+ G.graph["REMESH_MODE"] = str(args.remesh_mode)
136
168
  gcanon = dict(DEFAULTS["GRAMMAR_CANON"])
137
169
  gcanon.update(_args_to_dict(args, prefix="grammar."))
138
170
  if hasattr(args, "grammar_canon") and args.grammar_canon is not None:
@@ -165,8 +197,16 @@ def cmd_sequence(args: argparse.Namespace) -> int:
165
197
 
166
198
  def cmd_metrics(args: argparse.Namespace) -> int:
167
199
  G = build_graph(n=args.nodes, topology=args.topology, seed=args.seed)
200
+ if getattr(args, "config", None):
201
+ apply_config(G, args.config)
168
202
  _attach_callbacks(G)
169
203
  validate_canon(G)
204
+ if args.dt is not None:
205
+ G.graph["DT"] = float(args.dt)
206
+ if args.integrator is not None:
207
+ G.graph["INTEGRATOR_METHOD"] = str(args.integrator)
208
+ if getattr(args, "remesh_mode", None):
209
+ G.graph["REMESH_MODE"] = str(args.remesh_mode)
170
210
  G.graph.setdefault("GRAMMAR_CANON", DEFAULTS["GRAMMAR_CANON"]).update({"enabled": bool(args.grammar_canon)})
171
211
  G.graph["glyph_selector"] = default_glyph_selector if args.selector == "basic" else parametric_glyph_selector
172
212
  G.graph["GAMMA"] = {
@@ -205,10 +245,14 @@ def main(argv: Optional[List[str]] = None) -> int:
205
245
  p_run.add_argument("--steps", type=int, default=200)
206
246
  p_run.add_argument("--seed", type=int, default=1)
207
247
  p_run.add_argument("--preset", type=str, default=None)
248
+ p_run.add_argument("--config", type=str, default=None)
249
+ p_run.add_argument("--dt", type=float, default=None)
250
+ p_run.add_argument("--integrator", choices=["euler", "rk4"], default=None)
208
251
  p_run.add_argument("--save-history", dest="save_history", type=str, default=None)
209
252
  p_run.add_argument("--export-history-base", dest="export_history_base", type=str, default=None)
210
253
  p_run.add_argument("--export-format", dest="export_format", choices=["csv", "json"], default="json")
211
254
  p_run.add_argument("--summary", action="store_true")
255
+ p_run.add_argument("--remesh-mode", choices=["knn", "mst", "community"], default=None)
212
256
  p_run.add_argument("--no-canon", dest="grammar_canon", action="store_false", default=True, help="Desactiva gramática canónica")
213
257
  p_run.add_argument("--grammar.enabled", dest="grammar_enabled", type=_str2bool, default=None)
214
258
  p_run.add_argument("--grammar.zhir_requires_oz_window", dest="grammar_zhir_requires_oz_window", type=int, default=None)
@@ -230,9 +274,13 @@ def main(argv: Optional[List[str]] = None) -> int:
230
274
  p_seq.add_argument("--seed", type=int, default=1)
231
275
  p_seq.add_argument("--preset", type=str, default=None)
232
276
  p_seq.add_argument("--sequence-file", type=str, default=None)
277
+ p_seq.add_argument("--config", type=str, default=None)
278
+ p_seq.add_argument("--dt", type=float, default=None)
279
+ p_seq.add_argument("--integrator", choices=["euler", "rk4"], default=None)
233
280
  p_seq.add_argument("--save-history", dest="save_history", type=str, default=None)
234
281
  p_seq.add_argument("--export-history-base", dest="export_history_base", type=str, default=None)
235
282
  p_seq.add_argument("--export-format", dest="export_format", choices=["csv", "json"], default="json")
283
+ p_seq.add_argument("--remesh-mode", choices=["knn", "mst", "community"], default=None)
236
284
  p_seq.add_argument("--gamma-type", choices=list(GAMMA_REGISTRY.keys()), default="none")
237
285
  p_seq.add_argument("--gamma-beta", type=float, default=0.0)
238
286
  p_seq.add_argument("--gamma-R0", type=float, default=0.0)
@@ -251,12 +299,16 @@ def main(argv: Optional[List[str]] = None) -> int:
251
299
  p_met.add_argument("--topology", choices=["ring", "complete", "erdos"], default="ring")
252
300
  p_met.add_argument("--steps", type=int, default=300)
253
301
  p_met.add_argument("--seed", type=int, default=1)
302
+ p_met.add_argument("--dt", type=float, default=None)
303
+ p_met.add_argument("--integrator", choices=["euler", "rk4"], default=None)
254
304
  p_met.add_argument("--no-canon", dest="grammar_canon", action="store_false", default=True, help="Desactiva gramática canónica")
255
305
  p_met.add_argument("--selector", choices=["basic", "param"], default="basic")
256
306
  p_met.add_argument("--gamma-type", choices=list(GAMMA_REGISTRY.keys()), default="none")
257
307
  p_met.add_argument("--gamma-beta", type=float, default=0.0)
258
308
  p_met.add_argument("--gamma-R0", type=float, default=0.0)
309
+ p_met.add_argument("--remesh-mode", choices=["knn", "mst", "community"], default=None)
259
310
  p_met.add_argument("--save", type=str, default=None)
311
+ p_met.add_argument("--config", type=str, default=None)
260
312
  p_met.set_defaults(func=cmd_metrics)
261
313
 
262
314
  args = p.parse_args(argv)
tnfr/config.py ADDED
@@ -0,0 +1,41 @@
1
+ """Carga e inyección de configuraciones externas.
2
+
3
+ Permite definir parámetros en JSON o YAML y aplicarlos sobre ``G.graph``
4
+ reutilizando :func:`tnfr.constants.inject_defaults`.
5
+ """
6
+
7
+ from __future__ import annotations
8
+ from typing import Any, Dict
9
+ import json
10
+
11
+ try: # pragma: no cover - dependencia opcional
12
+ import yaml # type: ignore
13
+ except Exception: # pragma: no cover
14
+ yaml = None
15
+
16
+ from .constants import inject_defaults
17
+
18
+
19
+ def load_config(path: str) -> Dict[str, Any]:
20
+ """Lee un archivo JSON/YAML y devuelve un ``dict`` con los parámetros."""
21
+ with open(path, "r", encoding="utf-8") as f:
22
+ text = f.read()
23
+ if path.endswith((".yaml", ".yml")):
24
+ if not yaml: # pragma: no cover - fallo en entorno sin pyyaml
25
+ raise RuntimeError("pyyaml no está instalado")
26
+ data = yaml.safe_load(text)
27
+ else:
28
+ data = json.loads(text)
29
+ if not isinstance(data, dict):
30
+ raise ValueError("El archivo de configuración debe contener un objeto")
31
+ return data
32
+
33
+
34
+ def apply_config(G, path: str) -> None:
35
+ """Inyecta parámetros desde ``path`` sobre ``G.graph``.
36
+
37
+ Se reutiliza :func:`inject_defaults` para mantener la semántica de los
38
+ *defaults* canónicos.
39
+ """
40
+ cfg = load_config(path)
41
+ inject_defaults(G, cfg, override=True)
tnfr/constants.py CHANGED
@@ -11,8 +11,10 @@ from typing import Dict, Any
11
11
  # Parámetros canónicos
12
12
  # -------------------------
13
13
  DEFAULTS: Dict[str, Any] = {
14
- # Discretización
15
- "DT": 1.0,
14
+ # Discretización
15
+ "DT": 1.0,
16
+ "INTEGRATOR_METHOD": "euler",
17
+ "DT_MIN": 0.1,
16
18
 
17
19
  # Rango de EPI (estructura primaria)
18
20
  "EPI_MIN": -1.0,
@@ -43,9 +45,10 @@ DEFAULTS: Dict[str, Any] = {
43
45
  "INIT_VF_CLAMP_TO_LIMITS": True,
44
46
 
45
47
 
46
- # Mezcla para ΔNFR (campo nodal)
47
- # phase: dispersión de fase local; epi: gradiente de EPI; vf: desajuste de νf
48
- "DNFR_WEIGHTS": {"phase": 0.34, "epi": 0.33, "vf": 0.33},
48
+ # Mezcla para ΔNFR (campo nodal)
49
+ # phase: dispersión de fase local; epi: gradiente de EPI; vf: desajuste de νf;
50
+ # topo: término topológico (p. ej., centralidad). Pesos se normalizan.
51
+ "DNFR_WEIGHTS": {"phase": 0.34, "epi": 0.33, "vf": 0.33, "topo": 0.0},
49
52
 
50
53
  # Índice de sentido Si = α·νf_norm + β·(1 - disp_fase) + γ·(1 - |ΔNFR|/max)
51
54
  "SI_WEIGHTS": {"alpha": 0.34, "beta": 0.33, "gamma": 0.33},
@@ -76,7 +79,7 @@ DEFAULTS: Dict[str, Any] = {
76
79
  "REMESH_COOLDOWN_VENTANA": 20, # pasos mínimos entre RE’MESH
77
80
  "REMESH_COOLDOWN_TS": 0.0, # cooldown adicional por tiempo simulado
78
81
  # Gating adicional basado en observadores (conmutador + ventana)
79
- "REMESH_REQUIRE_STABILITY": False, # si True, exige ventana de estabilidad multi-métrica
82
+ "REMESH_REQUIRE_STABILITY": True, # si True, exige ventana de estabilidad multi-métrica
80
83
  "REMESH_STABILITY_WINDOW": 25, # tamaño de ventana para evaluar estabilidad
81
84
  "REMESH_MIN_PHASE_SYNC": 0.85, # media mínima de sincronía de fase en ventana
82
85
  "REMESH_MAX_GLYPH_DISR": 0.35, # media máxima de carga glífica disruptiva en ventana
@@ -84,6 +87,8 @@ DEFAULTS: Dict[str, Any] = {
84
87
  "REMESH_MIN_KURAMOTO_R": 0.80, # R de Kuramoto mínimo en ventana
85
88
  "REMESH_MIN_SI_HI_FRAC": 0.50, # fracción mínima de nodos con Si alto
86
89
  "REMESH_LOG_EVENTS": True, # guarda eventos y metadatos del RE’MESH
90
+ "REMESH_MODE": "knn", # modo de remallado topológico
91
+ "REMESH_COMMUNITY_K": 2, # conexiones por comunidad
87
92
 
88
93
  # RE’MESH: memoria τ y mezcla α (global/local)
89
94
  "REMESH_TAU": 8, # compatibilidad: tau global por defecto
@@ -91,23 +96,37 @@ DEFAULTS: Dict[str, Any] = {
91
96
  "REMESH_TAU_LOCAL": 4, # pasos hacia atrás (escala local)
92
97
  "REMESH_ALPHA": 0.5, # mezcla con pasado
93
98
  "REMESH_ALPHA_HARD": False, # si True ignora GLYPH_FACTORS['REMESH_alpha']
99
+
100
+ # Soporte y norma de la EPI
101
+ "EPI_SUPPORT_THR": 0.05, # umbral para Supp(EPI)
102
+
103
+ # U'M — compatibilidad mínima para crear/reforzar enlaces funcionales
104
+ "UM_COMPAT_THRESHOLD": 0.75,
94
105
 
95
- # Histéresis glífica
96
- "GLYPH_HYSTERESIS_WINDOW": 7,
97
-
98
- # Margen de histéresis del selector (cuánto "aguanta" sin cambiar glifo si está cerca de un umbral)
99
- "GLYPH_SELECTOR_MARGIN": 0.05,
106
+ # Histéresis glífica
107
+ "GLYPH_HYSTERESIS_WINDOW": 7,
108
+
109
+ # Lags máximos sin emisión (A’L) y recepción (E’N)
110
+ "AL_MAX_LAG": 5,
111
+ "EN_MAX_LAG": 3,
112
+
113
+ # Margen de histéresis del selector (cuánto "aguanta" sin cambiar glifo si está cerca de un umbral)
114
+ "GLYPH_SELECTOR_MARGIN": 0.05,
100
115
 
101
- # Ventana para estimar la carga glífica en history/plots
116
+ # Ventana para estimar la carga glífica en history/plots
102
117
  "GLYPH_LOAD_WINDOW": 50,
103
-
104
- # Tamaño de ventana para coherencia promedio W̄
105
- "WBAR_WINDOW": 25,
106
-
107
- # Factores suaves por glifo (operadores)
118
+
119
+ # Tamaño de ventana para coherencia promedio W̄
120
+ "WBAR_WINDOW": 25,
121
+
122
+ # Adaptación de frecuencia estructural por coherencia
123
+ "VF_ADAPT_TAU": 5, # pasos estables antes de ajustar νf
124
+ "VF_ADAPT_MU": 0.1, # velocidad de ajuste hacia la media vecinal
125
+
126
+ # Factores suaves por glifo (operadores)
108
127
  "GLYPH_FACTORS": {
109
- "AL_boost": 0.05, # A’L — pequeña emisión
110
- "EN_mix": 0.25, # E’N — mezcla con vecindad
128
+ "AL_boost": 0.05, # A’L — pequeña emisión
129
+ "EN_mix": 0.25, # E’N — mezcla con vecindad
111
130
  "IL_dnfr_factor": 0.7, # I’L — reduce ΔNFR
112
131
  "OZ_dnfr_factor": 1.3, # O’Z — aumenta ΔNFR
113
132
  "UM_theta_push": 0.25, # U’M — empuje adicional de fase local
@@ -116,17 +135,19 @@ DEFAULTS: Dict[str, Any] = {
116
135
  "VAL_scale": 1.15, # VA’L — expande EPI
117
136
  "NUL_scale": 0.85, # NU’L — contrae EPI
118
137
  "THOL_accel": 0.10, # T’HOL — acelera (seg. deriv.) si hay umbral
119
- "ZHIR_theta_shift": 1.57079632679, # Z’HIR — desplazamiento ~π/2
120
- "NAV_jitter": 0.05, # NA’V — pequeña inestabilidad creativa
121
- "REMESH_alpha": 0.5, # REMESHmezcla si no se usa REMESH_ALPHA
122
- },
138
+ "ZHIR_theta_shift": 1.57079632679, # Z’HIR — desplazamiento ~π/2
139
+ "NAV_jitter": 0.05, # NA’V — pequeña inestabilidad creativa
140
+ "NAV_eta": 0.5, # NAVpeso de convergencia hacia νf
141
+ "REMESH_alpha": 0.5, # RE’MESH — mezcla si no se usa REMESH_ALPHA
142
+ },
123
143
 
124
144
  # Umbrales para el selector glífico por defecto
125
145
  "GLYPH_THRESHOLDS": {"hi": 0.66, "lo": 0.33, "dnfr": 1e-3},
126
146
 
127
147
  # Comportamiento NA’V
128
- "NAV_RANDOM": True, # si True, usa jitter aleatorio en [-j, j]; si False, jitter determinista por signo
129
- "RANDOM_SEED": 0, # semilla base para reproducibilidad del jitter
148
+ "NAV_RANDOM": True, # si True, usa jitter aleatorio en [-j, j]; si False, jitter determinista por signo
149
+ "NAV_STRICT": False, # si True, fuerza ΔNFR νf (sin mezcla)
150
+ "RANDOM_SEED": 0, # semilla base para reproducibilidad del jitter
130
151
 
131
152
  # Modo ruido para O’Z
132
153
  "OZ_NOISE_MODE": False, # si True, añade ruido aditivo en ΔNFR
@@ -174,6 +195,41 @@ DEFAULTS.setdefault("GRAMMAR_CANON", {
174
195
  "thol_close_dnfr": 0.15, # si el campo calma, cerramos con SH’A/NU’L
175
196
  "si_high": 0.66, # umbral para elegir NU’L vs SH’A al cerrar
176
197
  })
198
+
199
+ # --- Coherencia (W) ---
200
+ DEFAULTS.setdefault("COHERENCE", {
201
+ "enabled": True,
202
+ "scope": "neighbors", # "neighbors" | "all"
203
+ "weights": {
204
+ "phase": 0.34,
205
+ "epi": 0.33,
206
+ "vf": 0.20,
207
+ "si": 0.13,
208
+ },
209
+ "self_on_diag": True, # W_ii = 1.0
210
+ "store_mode": "sparse", # "sparse" | "dense"
211
+ "threshold": 0.0,
212
+ "history_key": "W_sparse",
213
+ "Wi_history_key": "W_i",
214
+ "stats_history_key": "W_stats",
215
+ })
216
+
217
+ # --- Diagnóstico nodal ---
218
+ DEFAULTS.setdefault("DIAGNOSIS", {
219
+ "enabled": True,
220
+ "window": 16,
221
+ "history_key": "nodal_diag",
222
+ "stable": {"Rloc_hi": 0.80, "dnfr_lo": 0.20, "persist": 3},
223
+ "dissonance": {"Rloc_lo": 0.40, "dnfr_hi": 0.50, "persist": 3},
224
+ "transition": {"persist": 2},
225
+ "compute_symmetry": True,
226
+ "include_typology": False,
227
+ "advice": {
228
+ "stable": ["Coherencia", "Acoplamiento", "Resonancia"],
229
+ "transition": ["Transición", "Resonancia", "Autoorganización"],
230
+ "dissonant": ["Silencio", "Contracción", "Mutación"],
231
+ },
232
+ })
177
233
 
178
234
 
179
235
  # -------------------------
@@ -212,6 +268,7 @@ ALIAS_VF = ("νf", "nu_f", "nu-f", "nu", "freq", "frequency")
212
268
  ALIAS_THETA = ("θ", "theta", "fase", "phi", "phase")
213
269
  ALIAS_DNFR = ("ΔNFR", "delta_nfr", "dnfr")
214
270
  ALIAS_EPI = ("EPI", "psi", "PSI", "value")
271
+ ALIAS_EPI_KIND = ("EPI_kind", "epi_kind", "source_glifo")
215
272
  ALIAS_SI = ("Si", "sense_index", "S_i", "sense", "meaning_index")
216
273
  ALIAS_dEPI = ("dEPI_dt", "dpsi_dt", "dEPI", "velocity")
217
274
  ALIAS_D2EPI = ("d2EPI_dt2", "d2psi_dt2", "d2EPI", "accel")