circust.fitting¶
FMM¶
circust/fitting/fmm.py¶
Frecuency Modulated Mobius (FMM) — ajuste ritmico de un solo componente.
Modelo matematico¶
y(t) = M + A * cos(beta + 2*atan(omega*tan((t - alpha)/2)))
El termino interno Phi(t) = beta + 2*atan(omega*tan((t - alpha)/2)) es una transformacion de Mobius del circulo. Cuando omega = 1 se reduce a un simple desfase. Cuando omega -> 0 la forma de onda se aproxima a un coseno (Cosinor). La ventaja clave sobre Cosinor es que omega controla la asimetria de la forma de onda: el modelo puede representar picos asimetricos presentes en datos circadianos reales.
Parametros¶
M mesor — nivel medio A amplitud — siempre > 0 alpha — localizacion de la region del pico en [0, 2*pi) beta — parametro de forma en [0, 2*pi) omega — asimetria en (0, omegaMax]
Algoritmo de estimacion¶
- Paso 1 — Busqueda en rejilla
Para cada combinacion (alpha, omega) en una rejilla, se fijan esos dos parametros y se estiman M, A, beta por OLS sobre el eje temporal transformado por Mobius. Se selecciona el candidato con menor RSS que tambien satisfaga las restricciones de estabilidad de amplitud.
- Paso 2 — Refinamiento Nelder-Mead
Se pule la estimacion del Paso 1 minimizando el RSS sobre los cinco parametros simultaneamente, sujeto a las mismas restricciones de estabilidad (puntos infactibles devuelven infinito).
Los Pasos 1+2 se repiten num_reps veces, cada vez estrechando la
rejilla alrededor de la mejor estimacion anterior.
Devuelve¶
- FitResult
Claves de
params:M,A,alpha,beta,omega
- class circust.fitting.fmm.FMMModel(length_alpha_grid=48, length_omega_grid=24, omega_max=1.0, num_reps=3)[source]¶
Bases:
RhythmModelAjustador ritmico FMM (Frecuency Modulated Mobius).
Ajusta y(t) = M + A*cos(beta + 2*atan(omega*tan((t - alpha)/2))) usando un algoritmo de dos pasos: busqueda en rejilla + Nelder-Mead.
- Parameters:
length_alpha_grid (
int) – Numero de valores de alpha en la rejilla. Valor R por defecto: 48.length_omega_grid (
int) – Numero de valores de omega en la rejilla. Valor R por defecto: 24.omega_max (
float) – Cota superior de omega. Valor R por defecto: 1.0.num_reps (
int) – Numero de iteraciones de refinamiento de rejilla. Valor R por defecto: 3.
Example
>>> import numpy as np >>> from circust.fitting.fmm import FMMModel >>> >>> t = np.linspace(0, 2*np.pi, 50, endpoint=False) >>> data = 0.3 + 0.6 * np.cos(t - 1.2) + np.random.normal(0, 0.05, 50) >>> result = FMMModel().fit(data, t) >>> print(result.summary())
- static peak_time(alpha, beta, omega)[source]¶
Tiempo de pico del modelo FMM — formula compUU de R.
t_U = alpha + 2*atan2((1/omega)*sin(-beta/2), cos(-beta/2)) mod 2*pi
- Return type:
float- Parameters:
alpha (float)
beta (float)
omega (float)
- fit(data, time_points)[source]¶
Ajusta el modelo FMM a
data.- Parameters:
data (
ndarray) – Valores de expresion observados (normalizados a [-1, 1]).time_points (
ndarray) – Eje temporal circular en [0, 2*pi), tipicamenteCPCAResult.circular_scale.
- Returns:
Claves de
params:M,A,alpha,beta,omega- Return type:
Cosinor¶
circust/fitting/cosinor.py¶
Modelo ritmico Cosinor — ajuste sinusoidal por minimos cuadrados.
Modelo matematico¶
y(t) = M + A * cos(t - phi)
donde
M mesor — nivel medio de la senal A amplitud — mitad del rango pico-a-valle phi acrofase — tiempo de pico en [0, 2*pi)
Esta es la formulacion estandar en la literatura circadiana: phi es directamente el tiempo de pico (t_peak = phi), lo que hace la interpretacion de los parametros inmediata.
El modelo se ajusta por OLS reescribiendolo como regresion lineal:
- y = M + b*cos(t) + g*sin(t)
= M + A*cos(t - phi)
con b = A*cos(phi), g = A*sin(phi), de modo que
A = sqrt(b**2 + g**2) phi = atan2(g, b) mod 2*pi
Nota: la formulacion anterior de CIRCUST usaba cos(t + phi), donde el pico era -phi mod 2*pi. Esta formulacion es equivalente matematicamente (mismos valores ajustados, mismo R2) pero phi tiene signo opuesto.
- class circust.fitting.cosinor.CosinorModel[source]¶
Bases:
RhythmModelModelo Cosinor de un solo componente.
Ajusta y(t) = M + A*cos(t - phi) por minimos cuadrados ordinarios.
Es el mas rapido de los modelos ritmicos — O(n) — y se usa tanto como test de ritmicidad independiente como estimador de parametros iniciales dentro de FMM.
Example
>>> import numpy as np >>> from circust.fitting.cosinor import CosinorModel >>> >>> t = np.linspace(0, 2*np.pi, 50, endpoint=False) >>> data = 0.3 + 0.6 * np.cos(t - 1.2) + np.random.normal(0, 0.05, 50) >>> result = CosinorModel().fit(data, t) >>> print(result.summary())
- static peak_time(phi)[source]¶
Tiempo de pico del modelo Cosinor.
- Return type:
float- Parameters:
phi (float)
- El maximo de M + A*cos(t - phi) ocurre cuando t - phi = 0:
t_peak = phi
- fit(data, time_points)[source]¶
Ajusta el modelo Cosinor a
data.- Parameters:
data (
ndarray) – Valores de expresion observados (normalizados a [-1, 1]).time_points (
ndarray) – Eje temporal circular en [0, 2*pi).
- Returns:
Claves de
params:M,A,phiphies directamente el tiempo de pico en [0, 2*pi).- Return type:
ORI (Isotonic Regression Circular)¶
circust/fitting/ori.py¶
Modelo ritmico ORI — regresion isotonica circular unimodal (no parametrica).
Referencia¶
Larriba, Rueda & Fernandez (2016). «Identification of rhythmic genes in complex biological datasets and application to the study of human circadian system gene expression.» Statistical Applications in Genetics and Molecular Biology, 15(3), 205-223.
Modelo matematico¶
Dado un perfil de expresion genica ordenado por tiempo circular, el modelo ORI busca el mejor ajuste de forma subida-bajada (un pico, un valle) mediante el Algoritmo Pool-Adjacent-Violators (PAVA).
- Para cada par candidato (L=valle, U=pico) de extremos locales se ajusta:
Un PAVA creciente de L a U (circularmente).
Un PAVA decreciente de U a L (circularmente).
Se selecciona el par (L_opt, U_opt) que minimiza el MSE del ajuste unimodal resultante. La puntuacion de ritmicidad es:
R2_ORI = 1 - MSE_unimodal / MSE_plano
donde MSE_plano = Var(datos) es el error del modelo nulo (media constante).
Algoritmo PAVA (Pool-Adjacent-Violators)¶
Complejidad: O(n) tiempo, O(n) espacio.
Dado un vector de observaciones y con pesos w, produce el vector y_hat que minimiza sum w_i (y_i - y_hat_i)^2 sujeto a restricciones de monotonia (creciente o decreciente).
Aceleracion¶
Cuando Numba esta disponible, las funciones criticas (PAVA, busqueda de pares L-U) se compilan JIT a codigo maquina, obteniendo ~20-50x de aceleracion dado que el bucle (L, U) x PAVA es O(n^3) por gen.
- circust.fitting.ori.pava_increasing(y, w=None)[source]¶
Regresion isotonica creciente mediante PAVA.
Complejidad: O(n) tiempo, O(n) espacio.
- Parameters:
y (
ndarray) – Valores observados.w (
ndarray|None) – Pesos positivos. Si es None, pesos uniformes.
- Return type:
ndarray
- circust.fitting.ori.pava_decreasing(y, w=None)[source]¶
Regresion isotonica decreciente.
Equivalente a negar y, ejecutar
pava_increasing, y negar de vuelta.- Return type:
ndarray- Parameters:
y (ndarray)
w (ndarray | None)
- circust.fitting.ori.find_local_extrema(v)[source]¶
Encuentra minimos locales (valles) y maximos locales (picos) usando vecinos circulares.
Un punto i es un maximo local si v[i-1] <= v[i] Y v[i] >= v[i+1], con indices envolventes circulares. Minimos definidos simetricamente.
- Parameters:
v (
ndarray)- Return type:
tuple[ndarray,ndarray]- Returns:
candL (array int — indices de minimos locales (valles).)
candU (array int — indices de maximos locales (picos).)
- circust.fitting.ori.circular_unimodal_fit(v)[source]¶
Ajusta una regresion isotonica circular unimodal (subida-bajada).
Busca sobre todos los pares candidatos (valle, pico) — minimos y maximos locales de v — para encontrar el par (L, U) que produce el menor MSE al ajustar un PAVA creciente de L->U y un PAVA decreciente de U->L (circularmente).
- Parameters:
v (
ndarray) – Valores de expresion genica ordenados por tiempo circular.- Return type:
tuple[ndarray,float,int,int] |None- Returns:
fitted (array (n,) — valores ajustados.)
mse (float — error cuadratico medio.)
L_opt (int — indice del valle optimo (base 0).)
U_opt (int — indice del pico optimo (base 0).)
None si no se encuentra un ajuste valido.
- class circust.fitting.ori.ORIModel[source]¶
Bases:
RhythmModelModelo de ritmicidad no parametrica basado en regresion isotonica circular unimodal (ORI / ORIOS).
A diferencia de Cosinor y FMM, este modelo no asume una forma de onda parametrica. Busca la mejor forma subida-bajada (unimodal) compatible con restricciones de monotonia impuestas por PAVA.
Los “parametros” del modelo son los indices del valle (L_opt) y pico (U_opt) optimos; el R2 compara contra el modelo plano.
Example
>>> import numpy as np >>> from circust.fitting.ori import ORIModel >>> >>> t = np.linspace(0, 2*np.pi, 50, endpoint=False) >>> data = 0.3 + 0.6 * np.cos(t - 1.2) + np.random.normal(0, 0.05, 50) >>> result = ORIModel().fit(data, t) >>> print(result.r2) >>> print(result.summary())
- static peak_time(U_opt, time_points)[source]¶
Tiempo de pico del modelo ORI.
El pico se localiza en la posicion U_opt del vector ordenado circularmente. El tiempo de pico es
time_points[U_opt].- Return type:
float- Parameters:
U_opt (int)
time_points (ndarray)
- fit(data, time_points)[source]¶
Ajusta el modelo ORI a
data.- Parameters:
data (
ndarray) – Valores de expresion ordenados por el tiempo circular preliminar.time_points (
ndarray) – Eje temporal circular en [0, 2*pi), producido por CPCA.
- Returns:
Claves de
params:L_opt,U_opt.L_opt : indice del valle optimo (base 0)
U_opt : indice del pico optimo (base 0)
peak_time=time_points[U_opt].r2= R2_ORI = 1 - MSE_unimodal / MSE_plano.- Return type:
Clase base RhythmModel¶
Interfaz compartida para todos los modelos de ajuste ritmico del pipeline CIRCUST.
Nota de diseno¶
FitResult es un contenedor de datos puro: almacena todo lo que fit()
produce, incluido el tiempo de pico precalculado por el modelo. Asi el
resultado es autosuficiente — nadie necesita llamar al modelo despues de
obtenerlo.
La logica especifica de cada modelo vive exclusivamente en RhythmModel y
sus subclases:
fit()— abstracto, produce un FitResult con peak_time ya calculado.
Para el calculo del pico con floats sueltos (reparametrizacion manual) cada
modelo expone un metodo estatico auxiliar, p.ej. FMMModel.peak_time().
- class circust.fitting.rhythm_model.FitResult(fitted, params, peak_time, r2, residuals, residuals_std, sse, model_name)[source]¶
Bases:
objectResultado de cualquier modelo de ajuste ritmico.
- Variables:
fitted (np.ndarray, dim (n_muestras,)) – Valores predichos por el modelo en cada punto temporal.
params (dict) –
Parametros estimados del modelo.
- Claves Cosinor
M,A,phi M : mesor (nivel medio)
A : amplitud
phi : acrofase en [0, 2*pi)
- Claves FMM
M,A,alpha,beta,omega M : mesor
A : amplitud
alpha : parametro de localizacion en [0, 2*pi)
beta : parametro de forma en [0, 2*pi)
omega : parametro de asimetria en (0, 1]
- Claves Cosinor
peak_time (float) – Tiempo de pico en [0, 2*pi), precalculado por el modelo al hacer fit(). Cosinor: phi mod 2*pi (phi es directamente el tiempo de pico). FMM: formula compUU — alpha + 2*atan2(…) mod 2*pi.
r2 (float) – Coeficiente de determinacion R-cuadrado = 1 - SS_res / SS_tot.
residuals (np.ndarray, forma (n_muestras,)) – Residuos brutos: datos - ajustado.
residuals_std (np.ndarray, forma (n_muestras,)) – Residuos estandarizados: (residuos - media) / desv_std.
sse (float) – Suma de errores al cuadrado.
model_name (str) –
"cosinor"o"fmm".
- Parameters:
fitted (ndarray)
params (dict)
peak_time (float)
r2 (float)
residuals (ndarray)
residuals_std (ndarray)
sse (float)
model_name (str)
- fitted: ndarray¶
- params: dict¶
- peak_time: float¶
- r2: float¶
- residuals: ndarray¶
- residuals_std: ndarray¶
- sse: float¶
- model_name: str¶
- class circust.fitting.rhythm_model.RhythmModel[source]¶
Bases:
ABCInterfaz comun para todos los modelos de ajuste de ritmos circadianos.
Las subclases deben implementar
fit().Los parametros pasados al constructor son hiperparametros que permanecen constantes entre llamadas a
fit()(p.ej. tamanos de rejilla para FMM).- abstractmethod fit(data, time_points)[source]¶
Ajusta el modelo a
dataobservados entime_points.El
FitResultdevuelto incluyepeak_timeya calculado.- Parameters:
data (
ndarray) – Valores de expresion normalizados (tipicamente en [-1, 1]).time_points (
ndarray) – Eje temporal circular en [0, 2*pi), producido por CPCA.
- Return type: