Tema 1 · Señales (Parte II)
Departament d’Enginyeria Electrònica
Escola Tècnica Superior d’Enginyeria
Despatx 2.2.14
Grado en Ingeniería Electrónica de Telecomunicación (GIET)
Curso 2026/2027
Antes de empezar
De la Parte I conviene tener frescas:
La correlación cruzada entre dos señales \(x_1[n]\) y \(x_2[n]\) se define como:
\[R_{x_1x_2}[l] = \sum_{n=-\infty}^{\infty} x_1[n]\,x_2[n+l]\]
Se multiplica una señal por la otra desplazada \(l\) muestras y se suman los resultados.
El resultado es función del desplazamiento \(l\).
Permite detectar similitudes y patrones repetitivos.
La correlación cruzada es no es conmutativa:
\[R_{x_1x_2}[l] \neq R_{x_2x_1}[l]\]
La correlación cruzada permite detectar la presencia de un patrón en una señal ruidosa. Por ejemplo, un radar emite un pulso y recibe el eco reflejado por un objeto; la correlación entre ambos destapa el retardo y la amplitud del eco.
La misma tabla sirve para la correlación. Con las mismas señales de antes:
\[R_{x_1x_2}[l] = \sum_{n=-\infty}^{\infty} x_1[n]\,x_2[n+l] \qquad\quad x_1[n] = \{\underset{\uparrow}{1},\, 2,\, 3\} \qquad x_2[n] = \{\underset{\uparrow}{1},\, -1,\, 2\}\]
| \(l=-2\) | \(l=-1\) | \(l=0\) | \(l=1\) | \(l=2\) | |
|---|---|---|---|---|---|
| \(x_1[0]=1\) | \(1(1)\) | \(-1(-1)\) | \(2(2)\) | ||
| \(x_1[1]=2\) | \(2(1)\) | \(-2(-1)\) | \(4(2)\) | ||
| \(x_1[2]=3\) | \(3(1)\) | \(-3(-1)\) | \(6(2)\) | ||
| \(R_{x_1x_2}[l]\) | \(\mathbf{3}\) | \(\mathbf{-1}\) | \(\mathbf{5}\) | \(\mathbf{3}\) | \(\mathbf{2}\) |
cr = {
const x1s = [1, 2, 3], x2s = [1, -1, 2];
const x1 = k => (k >= 0 && k <= 2) ? x1s[k] : 0;
const x2 = k => (k >= 0 && k <= 2) ? x2s[k] : 0;
const K = d3.range(-5, 6);
const rv = l => d3.sum(K, k => x1(k) * x2(k + l));
const terminos = d3.range(0, 3).filter(k => x2(k + l_cr) !== 0).map(k => ({k, x1: x1(k), x2: x2(k + l_cr)}));
return {
x1: K.map(k => ({k, v: x1(k)})),
x2: K.map(k => ({k, v: x2(k + l_cr)})),
r: d3.range(-4, 5).map(l => ({l, v: rv(l), hecho: l <= l_cr})),
terminos,
rl: rv(l_cr)
};
}
Plot.plot({
width: 1216, height: 220, marginRight: 80,
x: {label: "k", domain: [-5.5, 5.5], ticks: d3.range(-5, 6)},
y: {label: null, domain: [-1.5, 3.5], grid: true},
marks: [
cr.terminos.length ? Plot.rect([{x1: cr.terminos[0].k - 0.5, x2: cr.terminos.at(-1).k + 0.5}],
{x1: "x1", x2: "x2", y1: -1.5, y2: 3.5, fill: "#41ab5d", fillOpacity: 0.2}) : null,
Plot.ruleY([0]),
Plot.ruleX(cr.x2, {x: d => d.k + 0.12, y1: 0, y2: "v", stroke: "#e74c3c", strokeWidth: 2.5}),
Plot.dot(cr.x2.filter(d => d.v !== 0), {x: d => d.k + 0.12, y: "v", stroke: "#e74c3c", fill: "white", r: 5, strokeWidth: 2}),
Plot.ruleX(cr.x1, {x: d => d.k - 0.12, y1: 0, y2: "v", stroke: "#2c7fb8", strokeWidth: 2.5}),
Plot.dot(cr.x1.filter(d => d.v !== 0), {x: d => d.k - 0.12, y: "v", fill: "#2c7fb8", r: 5}),
Plot.text([{x: 5.5, y: 2.9}], {x: "x", y: "y", text: () => "x₁[k]", fill: "#2c7fb8", textAnchor: "start", dx: 8}),
Plot.text([{x: 5.5, y: 1.9}], {x: "x", y: "y", text: () => "x₂[k+l]", fill: "#e74c3c", textAnchor: "start", dx: 8})
]
})// El margen superior holgado despega la etiqueta del eje y del gráfico de arriba; el alto total
// crece más que el margen, así que el área de dibujo también gana.
Plot.plot({
width: 1216, height: 235, marginTop: 48, marginRight: 80,
x: {label: "l", domain: [-5.5, 5.5], ticks: d3.range(-5, 6)},
y: {label: "Rx₁x₂[l]", domain: [-2, 6], grid: true},
marks: [
Plot.ruleY([0]),
Plot.dot(cr.r, {x: "l", y: "v", fill: "#ccc", r: 3}),
Plot.ruleX(cr.r.filter(d => d.hecho), {x: "l", y1: 0, y2: "v", stroke: "#41ab5d", strokeWidth: 2.5}),
Plot.dot(cr.r.filter(d => d.hecho), {x: "l", y: "v", fill: "#41ab5d", r: 5}),
Plot.dot([{l: l_cr, v: cr.rl}], {x: "l", y: "v", stroke: "#41ab5d", r: 9, strokeWidth: 2})
]
})📐 Ejemplo 1.1: Correlación de dos secuencias finitas
Calcula \(R_{x_1x_2}[l] = \displaystyle\sum_{n} x_1[n]\,x_2[n+l]\) por el método tabular:
\[x_1[n] = \{\underset{\uparrow}{1},\, 2,\, -1\} \qquad\qquad x_2[n] = \{2,\, \underset{\uparrow}{1},\, 0,\, 3\}\]
Cada fila es \(x_1[n]\,x_2[n+l]\): las muestras de \(x_2\) van en orden natural y cada fila se desplaza hacia la izquierda:
| \(l=-3\) | \(l=-2\) | \(l=-1\) | \(l=0\) | \(l=1\) | \(l=2\) | |
|---|---|---|---|---|---|---|
| \(x_1[0]=1\) | \(2(2)\) | \(1(1)\) | \(0(0)\) | \(3(3)\) | ||
| \(x_1[1]=2\) | \(4(2)\) | \(2(1)\) | \(0(0)\) | \(6(3)\) | ||
| \(x_1[2]=-1\) | \(-2(2)\) | \(-1(1)\) | \(0(0)\) | \(-3(3)\) | ||
| \(R_{x_1x_2}[l]\) | \(\mathbf{-2}\) | \(\mathbf{3}\) | \(\mathbf{4}\) | \(\mathbf{-2}\) | \(\mathbf{6}\) | \(\mathbf{3}\) |
La convolución de dos señales discretas \(x_1[n]\) y \(x_2[n]\) se define como:
\[y[n] = (x_1 * x_2)[n] = \sum_{k=-\infty}^{\infty} x_1[k]\,x_2[n-k]\]
Muy similar a la correlación, pero una de las señales está invertida en el tiempo.
Es fundamental, ya que permite calcular la salida de un sistema, por ejemplo, cualquier filtro digital.
| Propiedad | Expresión |
|---|---|
| Conmutativa | \(x_1 * x_2 = x_2 * x_1\) |
| Asociativa | \((x_1 * x_2) * x_3 = x_1 * (x_2 * x_3)\) |
| Distributiva | \(x_1 * (x_2 + x_3) = x_1 * x_2 + x_1 * x_3\) |
| Elemento neutro | \(x * \delta = x\) |
Aquí se ve como la convolución de una señal ruidosa con la respuesta impulsional de un filtro paso-bajo permite reducir el ruido:
El método tabular es muy útil para señales de duración finita, por ejemplo:
\[y[n] = x_1[n] * x_2[n] = \sum_{k=-\infty}^{\infty} x_1[k]\,x_2[n-k] \qquad\quad x_1[n] = \{\underset{\uparrow}{1},\, 2,\, 3\} \qquad x_2[n] = \{\underset{\uparrow}{1},\, -1,\, 2\}\]
Se construye una tabla donde:
| \(n=0\) | \(n=1\) | \(n=2\) | \(n=3\) | \(n=4\) | |
|---|---|---|---|---|---|
| \(x_1[0]=1\) | \(1(1)\) | \(-1(-1)\) | \(2(2)\) | ||
| \(x_1[1]=2\) | \(2(1)\) | \(-2(-1)\) | \(4(2)\) | ||
| \(x_1[2]=3\) | \(3(1)\) | \(-3(-1)\) | \(6(2)\) | ||
| \(y[n]\) | \(\mathbf{1}\) | \(\mathbf{1}\) | \(\mathbf{3}\) | \(\mathbf{1}\) | \(\mathbf{6}\) |
ct = {
const x1s = [1, 2, 3], x2s = [1, -1, 2];
const x1 = k => (k >= 0 && k <= 2) ? x1s[k] : 0;
const x2 = k => (k >= 0 && k <= 2) ? x2s[k] : 0;
const K = d3.range(-4, 7);
const yv = n => d3.sum(K, k => x1(k) * x2(n - k));
const terminos = d3.range(0, 3).filter(k => x2(n_ct - k) !== 0).map(k => ({k, x1: x1(k), x2: x2(n_ct - k)}));
return {
x1: K.map(k => ({k, v: x1(k)})),
x2: K.map(k => ({k, v: x2(n_ct - k)})),
y: d3.range(-2, 7).map(n => ({n, v: yv(n), hecho: n <= n_ct})),
terminos,
yn: yv(n_ct)
};
}
Plot.plot({
width: 1216, height: 220, marginRight: 70,
x: {label: "k", domain: [-4.5, 6.5], ticks: d3.range(-4, 7)},
y: {label: null, domain: [-1.5, 3.5], grid: true},
marks: [
ct.terminos.length ? Plot.rect([{x1: ct.terminos[0].k - 0.5, x2: ct.terminos.at(-1).k + 0.5}],
{x1: "x1", x2: "x2", y1: -1.5, y2: 3.5, fill: "#41ab5d", fillOpacity: 0.2}) : null,
Plot.ruleY([0]),
Plot.ruleX(ct.x2, {x: d => d.k + 0.12, y1: 0, y2: "v", stroke: "#e74c3c", strokeWidth: 2.5}),
Plot.dot(ct.x2.filter(d => d.v !== 0), {x: d => d.k + 0.12, y: "v", stroke: "#e74c3c", fill: "white", r: 5, strokeWidth: 2}),
Plot.ruleX(ct.x1, {x: d => d.k - 0.12, y1: 0, y2: "v", stroke: "#2c7fb8", strokeWidth: 2.5}),
Plot.dot(ct.x1.filter(d => d.v !== 0), {x: d => d.k - 0.12, y: "v", fill: "#2c7fb8", r: 5}),
Plot.text([{x: 6.5, y: 2.9}], {x: "x", y: "y", text: () => "x₁[k]", fill: "#2c7fb8", textAnchor: "start", dx: 8}),
Plot.text([{x: 6.5, y: 1.9}], {x: "x", y: "y", text: () => "x₂[n−k]", fill: "#e74c3c", textAnchor: "start", dx: 8})
]
})// Mismo criterio que en la correlación: margen superior holgado para despegar la etiqueta del
// gráfico de arriba, y alto total que crece más que el margen para ganar área de dibujo.
Plot.plot({
width: 1216, height: 235, marginTop: 48, marginRight: 70,
x: {label: "n", domain: [-4.5, 6.5], ticks: d3.range(-4, 7)},
y: {label: "y[n]", domain: [-0.5, 7], grid: true},
marks: [
Plot.ruleY([0]),
Plot.dot(ct.y, {x: "n", y: "v", fill: "#ccc", r: 3}),
Plot.ruleX(ct.y.filter(d => d.hecho), {x: "n", y1: 0, y2: "v", stroke: "#41ab5d", strokeWidth: 2.5}),
Plot.dot(ct.y.filter(d => d.hecho), {x: "n", y: "v", fill: "#41ab5d", r: 5}),
Plot.dot([{n: n_ct, v: ct.yn}], {x: "n", y: "v", stroke: "#41ab5d", r: 9, strokeWidth: 2})
]
})📐 Ejemplo 1.2: Convolución de dos secuencias finitas
Calcula \(y[n] = x_1[n] * x_2[n]\) por el método tabular:
\[x_1[n] = \{\underset{\uparrow}{1},\, 2,\, -1\} \qquad\qquad x_2[n] = \{2,\, \underset{\uparrow}{1},\, 0,\, 3\}\]
Cada fila es \(x_1[k]\,x_2[n-k]\), con las muestras de \(x_2\) en orden natural:
| \(n=-1\) | \(n=0\) | \(n=1\) | \(n=2\) | \(n=3\) | \(n=4\) | |
|---|---|---|---|---|---|---|
| \(x_1[0]=1\) | \(2(2)\) | \(1(1)\) | \(0(0)\) | \(3(3)\) | ||
| \(x_1[1]=2\) | \(4(2)\) | \(2(1)\) | \(0(0)\) | \(6(3)\) | ||
| \(x_1[2]=-1\) | \(-2(2)\) | \(-1(1)\) | \(0(0)\) | \(-3(3)\) | ||
| \(y[n]\) | \(\mathbf{2}\) | \(\mathbf{5}\) | \(\mathbf{0}\) | \(\mathbf{2}\) | \(\mathbf{6}\) | \(\mathbf{-3}\) |
El método analítico debe usarse para señales de duración infinita, por ejemplo, si queremos calcular la convolución de:
\[f[n] = \left(\tfrac{1}{3}\right)^n {\color{#2c7fb8}{u[n-1]}} \qquad\qquad g[n] = 2\,{\color{#e74c3c}{u[n-2]}}\]
\[y[n] = \sum_{k=-\infty}^{\infty} f[k]\,g[n-k] = \sum_{k=-\infty}^{\infty} \left(\tfrac{1}{3}\right)^{k} \underbrace{{\color{#2c7fb8}{u[k-1]}}}_{\neq\, 0 \;\text{si}\; {\color{#2c7fb8}{k \,\geq\, 1}}} \cdot\; 2\, \underbrace{{\color{#e74c3c}{u[n-k-2]}}}_{\neq\, 0 \;\text{si}\; {\color{#e74c3c}{k \,\leq\, n-2}}}\]
1) Cada escalón anula el sumatorio por un lado:
a) \({\color{#2c7fb8}{u[k-1]}} \neq 0 \iff {\color{#2c7fb8}{k \geq 1}}\)
b) \({\color{#e74c3c}{u[n-k-2]}} \neq 0 \iff {\color{#e74c3c}{k \leq n-2}}\)
2) Por tanto, el sumatorio puede truncarse:
\[ {\color{#9370db}{n \,\geq\, 3}} \Longleftarrow \underbrace{{\color{#2c7fb8}{1}} \,\leq\, k \,\leq\, {\color{#e74c3c}{n-2}}}_{\color{#41ab5d}{\text{ventana}}} \Longrightarrow y[n] = 2\sum_{k={\color{#2c7fb8}{1}}}^{{\color{#e74c3c}{n-2}}} \left(\tfrac{1}{3}\right)^{k}\]
3) Aplicando el sumatorio de una serie geométrica:
\[y[n] = 2\sum_{k={\color{#2c7fb8}{1}}}^{{\color{#e74c3c}{n-2}}} \left(\tfrac{1}{3}\right)^{k} = 2\;\frac{\left(\tfrac{1}{3}\right)^{{\color{#2c7fb8}{1}}} - \left(\tfrac{1}{3}\right)^{{\color{#e74c3c}{n-2}}+1}}{1 - \tfrac{1}{3}}\]
4) Resultado (solamente válido para \(n \geq 3\)):
\[y[n] = \left(1 - \left(\tfrac{1}{3}\right)^{n-2}\right) {\color{#9370db}{u[n-3]}}\]
\[y[n] = \sum_{k=-\infty}^{\infty} \left(\tfrac{1}{3}\right)^{k} \underbrace{{\color{#2c7fb8}{u[k-1]}}}_{\neq\, 0 \;\text{si}\; {\color{#2c7fb8}{k \,\geq\, 1}}} \cdot\; 2\, \underbrace{{\color{#e74c3c}{u[n-k-2]}}}_{\neq\, 0 \;\text{si}\; {\color{#e74c3c}{k \,\leq\, n-2}}}\]
html`<div class="ojs-texto"><p>${
n_ci < 3 ? `Ventana vacía ⇒ <i>y</i>[${n_ci}] = 0`
: n_ci === 3 ? `<b style="color:#41ab5d">¡Primer solape! Solo <i>k</i> = 1 ⇒ <i>y</i>[3] = 2/3</b>`
: `<span style="color:#41ab5d">Ventana 1 ≤ <i>k</i> ≤ ${n_ci - 2} ⇒ <i>y</i>[${n_ci}] = ${ci.yn.toFixed(6)}</span>`
}</p>${n_ci === 12 ? `<p><b>Así, hasta <i>n</i> → ∞</b></p>` : ""}</div>`ci = {
const K = d3.range(-4, 13);
const f = k => k >= 1 ? Math.pow(1 / 3, k) : 0;
const alto_g = 0.375;
const yv = m => m >= 3 ? 1 - Math.pow(1 / 3, m - 2) : 0;
return {
f: K.map(k => ({k, v: f(k)})),
g: K.map(k => ({k, v: n_ci - k >= 2 ? alto_g : 0})),
y: d3.range(-1, 13).map(m => ({n: m, v: yv(m), hecho: m <= n_ci})),
yn: yv(n_ci),
alto_g
};
}
Plot.plot({
width: 1216, height: 220, marginRight: 70,
x: {label: "k", domain: [-4.5, 12.5], ticks: d3.range(-4, 13)},
y: {label: "f[k]", domain: [-0.03, 0.43], grid: true},
marks: [
n_ci >= 3 ? Plot.rect([{x1: 0.5, x2: n_ci - 1.5}],
{x1: "x1", x2: "x2", y1: -0.03, y2: 0.43, fill: "#41ab5d", fillOpacity: 0.2}) : null,
Plot.ruleY([0]),
Plot.ruleX(ci.g, {x: "k", y1: 0, y2: "v", stroke: "#e74c3c", strokeWidth: 2}),
Plot.dot(ci.g.filter(d => d.v > 0), {x: "k", y: "v", stroke: "#e74c3c", fill: "white", r: 4.5, strokeWidth: 2}),
Plot.ruleX(ci.f, {x: "k", y1: 0, y2: "v", stroke: "#2c7fb8", strokeWidth: 2.5}),
Plot.dot(ci.f, {x: "k", y: "v", fill: "#2c7fb8", r: 5}),
Plot.ruleX([n_ci - 2], {stroke: "#e74c3c", strokeDasharray: "4 4"}),
Plot.text([{x: 12.5, y: ci.alto_g}], {x: "x", y: "y", text: () => "g = 2", fill: "#e74c3c", textAnchor: "start", dx: 8})
]
})Plot.plot({
width: 1216, height: 160, marginRight: 70,
x: {label: "n", domain: [-1.5, 12.5], ticks: d3.range(-1, 13)},
y: {label: "y[n]", domain: [-0.1, 1.15], grid: true},
marks: [
Plot.ruleY([0]),
Plot.ruleY([1], {stroke: "#888", strokeDasharray: "4 4"}),
Plot.dot(ci.y, {x: "n", y: "v", fill: "#ccc", r: 3}),
Plot.ruleX(ci.y.filter(d => d.hecho), {x: "n", y1: 0, y2: "v", stroke: "#41ab5d", strokeWidth: 2.5}),
Plot.dot(ci.y.filter(d => d.hecho), {x: "n", y: "v", fill: "#41ab5d", r: 5}),
Plot.dot([{n: n_ci, v: ci.yn}], {x: "n", y: "v", stroke: "#41ab5d", r: 9, strokeWidth: 2})
]
})📐 Ejemplo 1.3: Convolución analítica de dos señales infinitas
Calcula \(y[n] = f[n] * g[n]\) para
\[f[n] = \left(\tfrac{1}{2}\right)^n {\color{#2c7fb8}{u[n-1]}} \qquad\qquad g[n] = {\color{#e74c3c}{u[n-3]}}\]
Aplicando la definición de convolución:
\[y[n] = \sum_{k=-\infty}^{\infty} \left(\tfrac{1}{2}\right)^{k} \underbrace{{\color{#2c7fb8}{u[k-1]}}}_{\neq\, 0 \;\text{si}\; {\color{#2c7fb8}{k \,\geq\, 1}}} \cdot\; \underbrace{{\color{#e74c3c}{u[n-k-3]}}}_{\neq\, 0 \;\text{si}\; {\color{#e74c3c}{k \,\leq\, n-3}}}\]
Aquí una cota es inferior y la otra superior, así que la ventana se cierra por los dos lados, y solo existe si la de abajo no adelanta a la de arriba:
\[ {\color{#9370db}{n \,\geq\, 4}} \Longleftarrow \underbrace{{\color{#2c7fb8}{1}} \,\leq\, k \,\leq\, {\color{#e74c3c}{n-3}}}_{\color{#41ab5d}{\text{ventana}}}\]
Con la suma de la serie geométrica finita:
\[\begin{aligned} y[n] &= \sum_{k={\color{#2c7fb8}{1}}}^{{\color{#e74c3c}{n-3}}} \left(\tfrac{1}{2}\right)^{k} = \frac{\left(\tfrac{1}{2}\right)^{{\color{#2c7fb8}{1}}} - \left(\tfrac{1}{2}\right)^{{\color{#e74c3c}{n-3}}+1}}{1 - \tfrac{1}{2}} \\[0.4em] &= 1 - \left(\tfrac{1}{2}\right)^{\,n-3} \end{aligned}\]
Resultado (solamente válido para \(n \geq 4\)):
\[y[n] = \left(1 - \left(\tfrac{1}{2}\right)^{\,n-3}\right) {\color{#9370db}{u[n-4]}}\]
El método analítico sirve igual para la correlación. Por ejemplo, vamos a calcular la correlación usando las mismas señales que en el ejemplo de convolución:
\[f[n] = \left(\tfrac{1}{3}\right)^n {\color{#2c7fb8}{u[n-1]}} \qquad\qquad g[n] = 2\,{\color{#e74c3c}{u[n-2]}}\]
\[R_{fg}[l] = \sum_{n=-\infty}^{\infty} f[n]\,g[n+l] = \sum_{n=-\infty}^{\infty} \left(\tfrac{1}{3}\right)^{n} \underbrace{{\color{#2c7fb8}{u[n-1]}}}_{\neq\, 0 \;\text{si}\; {\color{#2c7fb8}{n \,\geq\, 1}}} \cdot\; 2\, \underbrace{{\color{#e74c3c}{u[n+l-2]}}}_{\neq\, 0 \;\text{si}\; {\color{#e74c3c}{n \,\geq\, 2-l}}}\]
Tenemos que: \[R_{fg}[l] = \sum_{n=-\infty}^{\infty} \left(\tfrac{1}{3}\right)^{n} \underbrace{{\color{#2c7fb8}{u[n-1]}}}_{\neq\, 0 \;\text{si}\; {\color{#2c7fb8}{n \,\geq\, 1}}} \cdot\; 2\, \underbrace{{\color{#e74c3c}{u[n+l-2]}}}_{\neq\, 0 \;\text{si}\; {\color{#e74c3c}{n \,\geq\, 2-l}}}\]
1) Los escalones anulan el sumatorio por abajo:
2) Por tanto, el sumatorio puede truncarse por abajo:
\[\underbrace{ n \geq \max({\color{#2c7fb8}{1}},\, {\color{#e74c3c}{2-l}})}_{\color{#41ab5d}{\text{ventana}}} \]
a) Si \({\color{#9370db}{l \,\geq\, 1}}\), manda \({\color{#2c7fb8}{1}}\) y entonces:
\[R_{fg}[l] = 2\sum_{n={\color{#2c7fb8}{1}}}^{\infty} \left(\tfrac{1}{3}\right)^{n} = 2 \frac{\left(\tfrac{1}{3}\right)^{{\color{#2c7fb8}{1}}}}{1 - \tfrac{1}{3}} = 1 \]
b) Si \({\color{#9370db}{l \,\leq\, 1}}\), manda \({\color{#e74c3c}{2-l}}\) y entonces:
\[R_{fg}[l] = 2\sum_{n={\color{#e74c3c}{2-l}}}^{\infty} \left(\tfrac{1}{3}\right)^{n} = 2 \frac{\left(\tfrac{1}{3}\right)^{{\color{#e74c3c}{2-l}}}}{1 - \tfrac{1}{3}} = 3\left(\tfrac{1}{3}\right)^{{\color{#e74c3c}{2-l}}} = 3^{(l-1)}\]
3) Podemos resumirlo como una función a trozos:
\[R_{fg}[l] = \begin{cases} 1 & {\color{#9370db}{l \,\geq\, 1}} \\[0.2em] 3^{\,l-1} & {\color{#9370db}{l \,\leq\, 1}} \end{cases} \]
NOTA: Puede ser útil dibujar para saber qué condición es la más restrictiva en cada caso:
qm = {
const rojo = 2 - l_qm;
return {rojo, ini: Math.max(1, rojo)};
}
Plot.plot({
width: 726, height: 174, marginTop: 46, marginLeft: 138, marginRight: 60, marginBottom: 35,
style: {fontSize: "14px"},
x: {label: "n", domain: [-5.5, 10.5], ticks: d3.range(-5, 11), grid: true},
y: {axis: null, domain: [-0.6, 2.9]},
marks: [
Plot.ruleX([{x: 1}], {x: "x", stroke: "#2c7fb8", strokeDasharray: "4 4"}),
Plot.ruleX([{x: qm.rojo}], {x: "x", stroke: "#e74c3c", strokeDasharray: "4 4"}),
// La etiqueta azul está fija y la roja se mueve con l: van en filas distintas, y además en
// sentidos opuestos, para que no choquen al cruzarse en l = 1.
Plot.text([{x: 1, y: 2.9, t: "n = 1", c: "#2c7fb8"}],
{x: "x", y: "y", text: "t", fill: "c", textAnchor: "start", dx: 6, dy: -21, fontSize: 16.5}),
Plot.text([{x: qm.rojo, y: 2.9, t: "n = 2 − l", c: "#e74c3c"}],
{x: "x", y: "y", text: "t", fill: "c", textAnchor: "end", dx: -6, dy: -2, fontSize: 16.5}),
Plot.ruleY([{y: 2, x1: 1, x2: 10.5}],
{y: "y", x1: "x1", x2: "x2", stroke: "#2c7fb8", strokeWidth: 8.8, strokeOpacity: 0.45}),
Plot.dot([{y: 2, x: 1}], {x: "x", y: "y", fill: "#2c7fb8", r: 5.5}),
Plot.ruleY([{y: 1, x1: qm.rojo, x2: 10.5}],
{y: "y", x1: "x1", x2: "x2", stroke: "#e74c3c", strokeWidth: 8.8, strokeOpacity: 0.45}),
Plot.dot([{y: 1, x: qm.rojo}], {x: "x", y: "y", fill: "#e74c3c", r: 5.5}),
Plot.ruleY([{y: 0, x1: qm.ini, x2: 10.5}],
{y: "y", x1: "x1", x2: "x2", stroke: "#41ab5d", strokeWidth: 8.8, strokeOpacity: 0.75}),
Plot.dot([{y: 0, x: qm.ini}], {x: "x", y: "y", fill: "#41ab5d", r: 5.5}),
Plot.text([
{y: 2, t: "n ≥ 1", c: "#2c7fb8"},
{y: 1, t: `n ≥ 2 − l = ${qm.rojo}`, c: "#e74c3c"},
{y: 0, t: `ventana: n ≥ ${qm.ini}`, c: "#41ab5d"}
], {x: () => -5.5, y: "y", text: "t", fill: "c", textAnchor: "end", dx: -9, fontSize: 18.7}),
Plot.text([{y: 2}, {y: 1}, {y: 0}],
{x: () => 10.5, y: "y", text: () => "→ ∞", textAnchor: "start", dx: 7, fill: "#888"})
]
})re = {
const rojo = 2 - l_re;
return {rojo, ini: Math.max(1, rojo), azul: l_re >= 1};
}
// Enseña la variante del l actual. Va como celda con nombre, y no como bloque suelto, por dos
// razones: no devuelve el contenedor (OJS se lo llevaría a su celda) y, al tener nombre, OJS no
// imprime su valor, que si no sale como un "undefined" debajo de la fórmula.
sumatorio_visible = {
const caso = re.azul ? "azul" : "rojo";
for (const s of document.querySelectorAll("#sumatorio-swap .sumatorio-l")) {
s.style.visibility = (s.dataset.caso === caso) ? "visible" : "hidden";
}
return caso;
}mapa = d3.range(-6.5, 6.51, 0.25).map(l => ({l, n: Math.max(1, 2 - l)}))
Plot.plot({
width: 1216, height: 430, marginRight: 80, marginBottom: 45,
style: {fontSize: "15px"},
x: {label: "l", domain: [-6.5, 6.5], ticks: d3.range(-6, 7), grid: true},
y: {label: "n", domain: [-0.5, 8.5], ticks: d3.range(0, 9), grid: true},
marks: [
Plot.areaY(mapa, {x: "l", y1: "n", y2: 8.5, fill: "#41ab5d", fillOpacity: 0.2}),
Plot.ruleY([0]),
Plot.line([{l: -6.5, n: 1}, {l: 6.5, n: 1}],
{x: "l", y: "n", stroke: "#2c7fb8", strokeWidth: 2, strokeDasharray: "4 4"}),
Plot.line([{l: -6.5, n: 8.5}, {l: 6.5, n: -4.5}],
{x: "l", y: "n", stroke: "#e74c3c", strokeWidth: 2, strokeDasharray: "4 4"}),
// El borde de la ventana se pinta con el color de la cota que manda en cada tramo: rojo
// mientras gana 2-l y azul a partir del codo, donde toma el relevo el 1.
Plot.line(mapa.filter(d => d.l <= 1), {x: "l", y: "n", stroke: "#e74c3c", strokeWidth: 3.5}),
Plot.line(mapa.filter(d => d.l >= 1), {x: "l", y: "n", stroke: "#2c7fb8", strokeWidth: 3.5}),
Plot.ruleX([{x: l_re}], {x: "x", stroke: "#9370db", strokeWidth: 2, strokeDasharray: "2 4"}),
Plot.dot([{l: l_re, n: re.ini}],
{x: "l", y: "n", fill: re.azul ? "#2c7fb8" : "#e74c3c", stroke: "#9370db", r: 8, strokeWidth: 2.5}),
// El codo parte el eje l en dos regímenes; las flechas salen de esa vertical hacia cada lado.
Plot.ruleX([{x: 1}], {x: "x", stroke: "#41ab5d", strokeWidth: 1.5, strokeDasharray: "5 5", strokeOpacity: 0.6}),
Plot.arrow([{x1: 0.9, x2: -2.2, y: 7.9}],
{x1: "x1", x2: "x2", y1: "y", y2: "y", stroke: "#e74c3c", strokeWidth: 2.5, headLength: 10}),
Plot.arrow([{x1: 1.1, x2: 3.1, y: 7.9}],
{x1: "x1", x2: "x2", y1: "y", y2: "y", stroke: "#2c7fb8", strokeWidth: 2.5, headLength: 10}),
Plot.text([{l: -3.2, n: 7.9, t: "manda 2 − l", c: "#e74c3c"},
{l: 3.8, n: 7.9, t: "manda 1", c: "#2c7fb8"}],
{x: "l", y: "n", text: "t", fill: "c", fontSize: 19, fontWeight: "bold"}),
Plot.text([{l: 6.5, n: 1, t: "n = 1", c: "#2c7fb8"}],
{x: "l", y: "n", text: "t", fill: "c", textAnchor: "start", dx: 10, fontSize: 16}),
Plot.text([{l: -6.5, n: 7.5, t: "n = 2 − l", c: "#e74c3c"}],
{x: "l", y: "n", text: "t", fill: "c", textAnchor: "start", dx: 8, dy: 14, fontSize: 16}),
]
})// El mensaje de la derecha es bastante más largo que el otro y se partía en dos líneas: se
// encoge solo en ese caso, para no tocar el tamaño del que ya cabía.
html`<div class="ojs-texto"><p style="font-size: ${l_ca < 1 ? "1em" : "0.82em"}">${
l_ca < 1 ? `<span style="color:#41ab5d">Ventana <i>n</i> ≥ ${2 - l_ca} ⇒ <i>R</i><sub>fg</sub>[${l_ca}] = ${ca.rl.toFixed(6)}</span>`
: `<b style="color:#41ab5d">El escalón cubre ya todo <i>f</i>: ventana <i>n</i> ≥ 1 ⇒ <i>R</i><sub>fg</sub>[${l_ca}] = 1</b>`
}</p>${l_ca === 6 ? `<p><b>Saturado, así hasta <i>l</i> → ∞</b></p>` : ""}</div>`ca = {
const N = d3.range(-4, 13);
const f = n => n >= 1 ? Math.pow(1 / 3, n) : 0;
const alto_g = 0.375;
const rv = m => Math.min(1, Math.pow(3, m - 1));
return {
f: N.map(n => ({n, v: f(n)})),
g: N.map(n => ({n, v: n + l_ca - 2 >= 0 ? alto_g : 0})),
r: d3.range(-6, 7).map(m => ({l: m, v: rv(m), hecho: m <= l_ca})),
rl: rv(l_ca),
inicio: Math.max(1, 2 - l_ca),
alto_g
};
}
Plot.plot({
width: 1216, height: 220, marginRight: 70,
x: {label: "n", domain: [-4.5, 12.5], ticks: d3.range(-4, 13)},
y: {label: "f[n]", domain: [-0.03, 0.43], grid: true},
marks: [
Plot.rect([{x1: ca.inicio - 0.5, x2: 12.5}],
{x1: "x1", x2: "x2", y1: -0.03, y2: 0.43, fill: "#41ab5d", fillOpacity: 0.2}),
Plot.ruleY([0]),
Plot.ruleX(ca.g, {x: "n", y1: 0, y2: "v", stroke: "#e74c3c", strokeWidth: 2}),
Plot.dot(ca.g.filter(d => d.v > 0), {x: "n", y: "v", stroke: "#e74c3c", fill: "white", r: 4.5, strokeWidth: 2}),
Plot.ruleX(ca.f, {x: "n", y1: 0, y2: "v", stroke: "#2c7fb8", strokeWidth: 2.5}),
Plot.dot(ca.f, {x: "n", y: "v", fill: "#2c7fb8", r: 5}),
Plot.ruleX([ca.inicio], {stroke: "#41ab5d", strokeDasharray: "4 4"}),
Plot.text([{x: 12.5, y: ca.alto_g}], {x: "x", y: "y", text: () => "g[n+l] = 2", fill: "#e74c3c", textAnchor: "start", dx: 8})
]
})Plot.plot({
width: 1216, height: 160, marginRight: 70,
x: {label: "l", domain: [-6.5, 6.5], ticks: d3.range(-6, 7)},
y: {label: "Rfg[l]", domain: [-0.1, 1.15], grid: true},
marks: [
Plot.ruleY([0]),
Plot.ruleY([1], {stroke: "#888", strokeDasharray: "4 4"}),
Plot.dot(ca.r, {x: "l", y: "v", fill: "#ccc", r: 3}),
Plot.ruleX(ca.r.filter(d => d.hecho), {x: "l", y1: 0, y2: "v", stroke: "#41ab5d", strokeWidth: 2.5}),
Plot.dot(ca.r.filter(d => d.hecho), {x: "l", y: "v", fill: "#41ab5d", r: 5}),
Plot.dot([{l: l_ca, v: ca.rl}], {x: "l", y: "v", stroke: "#41ab5d", r: 9, strokeWidth: 2})
]
})📐 Ejemplo 1.4: Correlación analítica de dos señales infinitas
Calcula \(R_{fg}[l]\) para
\[f[n] = \left(\tfrac{1}{2}\right)^n {\color{#2c7fb8}{u[n-1]}} \qquad\qquad g[n] = {\color{#e74c3c}{u[n-3]}}\]
Aplicando la definición de correlación cruzada:
\[R_{fg}[l] = \sum_{n=-\infty}^{\infty} \left(\tfrac{1}{2}\right)^{n} \underbrace{{\color{#2c7fb8}{u[n-1]}}}_{\neq\, 0 \;\text{si}\; {\color{#2c7fb8}{n \,\geq\, 1}}} \cdot\; \underbrace{{\color{#e74c3c}{u[n+l-3]}}}_{\neq\, 0 \;\text{si}\; {\color{#e74c3c}{n \,\geq\, 3-l}}}\]
Las dos condiciones son cotas inferiores, así que:
\[n \geq \max({\color{#2c7fb8}{1}},\, {\color{#e74c3c}{3-l}})\]
Si \({\color{#9370db}{l \,\geq\, 2}}\) manda \({\color{#2c7fb8}{1}}\), y la serie geométrica da
\[R_{fg}[l] = \sum_{n={\color{#2c7fb8}{1}}}^{\infty} \left(\tfrac{1}{2}\right)^{n} = \frac{\left(\tfrac{1}{2}\right)^{{\color{#2c7fb8}{1}}}}{1 - \tfrac{1}{2}} = 1\]
Si \({\color{#9370db}{l \,\leq\, 2}}\) manda \({\color{#e74c3c}{3-l}}\), y la misma serie da
\[\begin{aligned} R_{fg}[l] &= \sum_{n={\color{#e74c3c}{3-l}}}^{\infty} \left(\tfrac{1}{2}\right)^{n} = \frac{\left(\tfrac{1}{2}\right)^{{\color{#e74c3c}{3-l}}}}{1 - \tfrac{1}{2}} \\[0.4em] &= \left(\tfrac{1}{2}\right)^{2-l} = 2^{\,l-2} \end{aligned}\]
Podemos resumirlo en una función a trozos:
\[ R_{fg}[l] = \begin{cases} 2^{\,l-2}, & l \leq 2 \\[0.4em] 1, & l \geq 2 \end{cases}\]
La autocorrelación es un caso particular de la correlación cruzada, donde se correlaciona una señal consigo misma (exactamente misma fórmula pero tomando \(x_1 = x_2\)):
\[R_{xx}[l] = \sum_{n=-\infty}^{\infty} x[n]\,x[n+l] \]
Compara la señal consigo misma, desplazada \(l\) muestras
Por tanto, para retardo cero, autocorrelación es máxima y además coincide con la energía de la señal
\[ R_{xx}[0] = \sum_{n=-\infty}^{\infty} x[n]\,x[n] =\sum_{n=-\infty}^{\infty} |x[n]|^2 = E_x\]
En la práctica, se suele normalizar dividiendo entre \(R_{xx}[0]\) para que el máximo valga 1
Permite detectar periodicidad en señales
📐 Ejemplo 1.5: Autocorrelación de una señal con eco
Un sonar emite un pulso \(\delta[n]\) y recibe ese mismo pulso más un eco retrasado \(5\) muestras y atenuado por un factor \(0{,}5\). Dicha señal se modela como \(x[n] = \delta[n] + 0{,}5\,\delta[n-5]\). Calcula su autocorrelación de forma analítica usando las propiedades de la delta de Kronecker.
\[R_{xx}[l] = \sum_{n=-\infty}^{\infty} \bigl(\delta[n] + 0{,}5\,\delta[n-5]\bigr) \bigl(\delta[n+l] + 0{,}5\,\delta[n+l-5]\bigr)\]
Salen cuatro productos, y cada uno solo sobrevive para un desplazamiento específico, porque dos deltas solo coinciden si sus argumentos son iguales:
| producto | coinciden en | aporta |
|---|---|---|
| \(\delta[n]\,\delta[n+l]\) | \(l=0\) | \(1\) |
| \(0{,}5\,\delta[n]\,\delta[n+l-5]\) | \(l=5\) | \(0{,}5\) |
| \(0{,}5\,\delta[n-5]\,\delta[n+l]\) | \(l=-5\) | \(0{,}5\) |
| \(0{,}25\,\delta[n-5]\,\delta[n+l-5]\) | \(l=0\) | \(0{,}25\) |
Un ECG real (MIT-BIH 208, \(f_s = 360\) Hz): latido irregular y ruidoso; \(R_{xx}[l]\) lo destapa.
Las definiciones de correlación y convolución son para el caso continuo son análogas a las discretas, y se resumen en la siguiente tabla:
| Discreto | Continuo | |
|---|---|---|
| Correlación | \(R_{x_1x_2}[l] = \displaystyle\sum_{n=-\infty}^{\infty} x_1[n]\,x_2[n+l]\) | \(R_{x_1x_2}(\tau) = \displaystyle\int_{-\infty}^{\infty} x_1(t)\,x_2(t+\tau)\,dt\) |
| Autocorrelación | \(R_{xx}[l] = \displaystyle\sum_{n=-\infty}^{\infty} x[n]\,x[n+l]\) | \(R_{xx}(\tau) = \displaystyle\int_{-\infty}^{\infty} x(t)\,x(t+\tau)\,dt\) |
| Convolución | \((x_1 * x_2) [n] = \displaystyle\sum_{k=-\infty}^{\infty} x_1[k]\,x_2[n-k]\) | \((x_1 * x_2) (t) = \displaystyle\int_{-\infty}^{\infty} x_1(\theta)\,x_2(t-\theta)\,d\theta\) |
La metodología es la misma que en el caso discreto pero usando integrales en lugar de sumatorios, por ejemplo, para calcular la convolución de:
\[f(t) = e^{-t}\,{\color{#2c7fb8}{u(t-1)}} \qquad\qquad g(t) = 2\,{\color{#e74c3c}{u(t-2)}}\]
\[y(t) = \int_{-\infty}^{\infty} f(\theta)\,g(t-\theta)\,d\theta = \int_{-\infty}^{\infty} e^{-\theta} \underbrace{{\color{#2c7fb8}{u(\theta-1)}}}_{\neq\, 0 \;\text{si}\; {\color{#2c7fb8}{\theta \,\geq\, 1}}} \cdot\; 2\, \underbrace{{\color{#e74c3c}{u(t-\theta-2)}}}_{\neq\, 0 \;\text{si}\; {\color{#e74c3c}{\theta \,\leq\, t-2}}}\,d\theta\]
Cada escalón anula la integral por un lado:
Por tanto, la integral puede truncarse:
\[ {\color{#9370db}{t \,\geq\, 3}} \Longleftarrow \underbrace{{\color{#2c7fb8}{1}} \,\leq\, \theta \,\leq\, {\color{#e74c3c}{t-2}}}_{\color{#41ab5d}{\text{ventana}}} \Longrightarrow y(t) = 2\int_{{\color{#2c7fb8}{1}}}^{{\color{#e74c3c}{t-2}}} e^{-\theta}\,d\theta\]
Integrando la exponencial:
\[y(t) = 2\int_{{\color{#2c7fb8}{1}}}^{{\color{#e74c3c}{t-2}}} e^{-\theta}\,d\theta = 2\left(e^{-{\color{#2c7fb8}{1}}} - e^{-({\color{#e74c3c}{t-2}})}\right)\]
Resultado (solamente válido para \(t \geq 3\)):
\[y(t) = 2\left(e^{-1} - e^{-(t-2)}\right) {\color{#9370db}{u(t-3)}}\]
\[y(t) = \int_{-\infty}^{\infty} e^{-\theta} \underbrace{{\color{#2c7fb8}{u(\theta-1)}}}_{\neq\, 0 \;\text{si}\; {\color{#2c7fb8}{\theta \,\geq\, 1}}} \cdot\; 2\, \underbrace{{\color{#e74c3c}{u(t-\theta-2)}}}_{\neq\, 0 \;\text{si}\; {\color{#e74c3c}{\theta \,\leq\, t-2}}}\,d\theta\]
📐 Ejemplo 1.6: Autocorrelación de una exponencial causal
Calcula \(R_{xx}(\tau)\) para
\[x(t) = e^{-t}\,{\color{#2c7fb8}{u(t)}}\]
\[R_{xx}(\tau) = \int_{-\infty}^{\infty} e^{-t} \underbrace{{\color{#2c7fb8}{u(t)}}}_{\neq\, 0 \;\text{si}\; {\color{#2c7fb8}{t \,\geq\, 0}}} \;e^{-(t+\tau)} \underbrace{{\color{#e74c3c}{u(t+\tau)}}}_{\neq\, 0 \;\text{si}\; {\color{#e74c3c}{t \,\geq\, -\tau}}} dt = e^{-\tau}\!\!\int_{\max({\color{#2c7fb8}{0}},\,{\color{#e74c3c}{-\tau}})}^{\infty}\!\! e^{-2t}\,dt\]
De nuevo dos cotas inferiores: la ventana nunca se vacía y manda la mayor.
Si \({\color{#9370db}{\tau \,\geq\, 0}}\) manda \({\color{#2c7fb8}{0}}\):
\[R_{xx}(\tau) = e^{-\tau}\int_{{\color{#2c7fb8}{0}}}^{\infty} e^{-2t}\,dt = \frac{e^{-\tau}}{2}\]
Si \({\color{#9370db}{\tau \,\leq\, 0}}\) manda \({\color{#e74c3c}{-\tau}}\):
\[R_{xx}(\tau) = e^{-\tau}\int_{{\color{#e74c3c}{-\tau}}}^{\infty} e^{-2t}\,dt = e^{-\tau}\,\frac{e^{2\tau}}{2} = \frac{e^{\tau}}{2}\]
Las dos ramas son la misma con un valor absoluto: \(\;R_{xx}(\tau) = \tfrac{1}{2}\,e^{-|\tau|}\)
📐 Ejemplo 1.7: Autocorrelación de un pulso rectangular
Calcula \(R_{xx}(\tau)\) para el pulso unidad (no desarrolles el producto dentro de la integral):
\[x(t) = u(t) - u(t-1)\]
\[R_{xx}(\tau) \triangleq \int_{-\infty}^{\infty} x(t)x(t+\tau)\,dt = \int_{-\infty}^{\infty} \underbrace{x(t)}_{\neq\, 0 \;\text{si}\; {\color{#2c7fb8}{0 \,\leq\, t \,\leq\, 1}}} \underbrace{x(t+\tau)}_{\neq\, 0 \;\text{si}\; {\color{#e74c3c}{-\tau \,\leq\, t \,\leq\, 1-\tau}}} dt\]
Ahora cada señal aporta una cota inferior y una superior, así que la ventana empieza en la mayor de las inferiores y acaba en la menor de las superiores:
\[R_{xx}(\tau) = \int_{\max({\color{#2c7fb8}{0}},\,{\color{#e74c3c}{-\tau}})}^{\min({\color{#2c7fb8}{1}},\,{\color{#e74c3c}{1-\tau}})} dt = \min({\color{#2c7fb8}{1}},\,{\color{#e74c3c}{1-\tau}}) - \max({\color{#2c7fb8}{0}},\,{\color{#e74c3c}{-\tau}})\]
Diferenciamos dos casos según el signo de \(\tau\) (ver siguiente diapositiva):
NOTA: Recuerda que la autocorrelación es siempre par.
pa = {
const lo = Math.max(0, -tau_pa);
const hi = Math.min(1, 1 - tau_pa);
return {lo, hi, pos: tau_pa >= 0};
}
integral_visible = {
const caso = pa.pos ? "pos" : "neg";
for (const s of document.querySelectorAll("#integral-swap .integral-tau")) {
s.style.visibility = (s.dataset.caso === caso) ? "visible" : "hidden";
}
return caso;
}para = d3.range(-1, 1.0001, 0.02).map(tau => ({tau, lo: Math.max(0, -tau), hi: Math.min(1, 1 - tau)}))
Plot.plot({
width: 1216, height: 400, marginRight: 90, marginBottom: 45,
style: {fontSize: "15px"},
x: {label: "τ", domain: [-1.8, 1.8], ticks: d3.range(-1.5, 1.6, 0.5), grid: true},
y: {label: "t", domain: [-1.2, 2.2], ticks: d3.range(-1, 2.1, 0.5), grid: true},
marks: [
Plot.areaY(para, {x: "tau", y1: "lo", y2: "hi", fill: "#41ab5d", fillOpacity: 0.2}),
Plot.ruleY([0], {stroke: "#888"}),
// Las cuatro restricciones, prolongadas en discontinuo más allá del paralelogramo.
Plot.line([{x: -1.8, y: 0}, {x: 1.8, y: 0}],
{x: "x", y: "y", stroke: "#2c7fb8", strokeWidth: 1.5, strokeDasharray: "4 4"}),
Plot.line([{x: -1.8, y: 1}, {x: 1.8, y: 1}],
{x: "x", y: "y", stroke: "#2c7fb8", strokeWidth: 1.5, strokeDasharray: "4 4"}),
Plot.line([{x: -1.8, y: 1.8}, {x: 1.8, y: -1.8}],
{x: "x", y: "y", stroke: "#e74c3c", strokeWidth: 1.5, strokeDasharray: "4 4"}),
Plot.line([{x: -1.8, y: 2.8}, {x: 1.8, y: -0.8}],
{x: "x", y: "y", stroke: "#e74c3c", strokeWidth: 1.5, strokeDasharray: "4 4"}),
// Bordes del paralelogramo: abajo manda -τ (rojo) hasta τ = 0 y luego el 0 (azul); arriba,
// al revés.
Plot.line([{x: -1, y: 1}, {x: 0, y: 0}],
{x: "x", y: "y", stroke: "#e74c3c", strokeWidth: 3.5}),
Plot.line([{x: 0, y: 0}, {x: 1, y: 0}],
{x: "x", y: "y", stroke: "#2c7fb8", strokeWidth: 3.5}),
Plot.line([{x: -1, y: 1}, {x: 0, y: 1}],
{x: "x", y: "y", stroke: "#2c7fb8", strokeWidth: 3.5}),
Plot.line([{x: 0, y: 1}, {x: 1, y: 0}],
{x: "x", y: "y", stroke: "#e74c3c", strokeWidth: 3.5}),
// El corte vertical en el τ actual: eso es exactamente lo que integra la fórmula.
Plot.ruleX([{x: tau_pa}], {x: "x", stroke: "#9370db", strokeWidth: 2, strokeDasharray: "2 4"}),
Plot.ruleX([{x: tau_pa, y1: pa.lo, y2: pa.hi}],
{x: "x", y1: "y1", y2: "y2", stroke: "#41ab5d", strokeWidth: 7, strokeOpacity: 0.85}),
Plot.dot([{x: tau_pa, y: pa.lo}],
{x: "x", y: "y", fill: pa.pos ? "#2c7fb8" : "#e74c3c", stroke: "#9370db", r: 7, strokeWidth: 2.5}),
Plot.dot([{x: tau_pa, y: pa.hi}],
{x: "x", y: "y", fill: pa.pos ? "#e74c3c" : "#2c7fb8", stroke: "#9370db", r: 7, strokeWidth: 2.5}),
// Rótulos de las cuatro rectas.
Plot.text([{x: 1.8, y: 0, t: "t = 0", c: "#2c7fb8"},
{x: 1.8, y: 1, t: "t = 1", c: "#2c7fb8"}],
{x: "x", y: "y", text: "t", fill: "c", textAnchor: "start", dx: 10, fontSize: 16}),
Plot.text([{x: -1.4, y: 1.4, t: "t = −τ", c: "#e74c3c"},
{x: -0.75, y: 1.75, t: "t = 1 − τ", c: "#e74c3c"}],
{x: "x", y: "y", text: "t", fill: "c", textAnchor: "start", dx: 8, dy: -8, fontSize: 16}),
Plot.text([{x: 0, y: 0.5, t: "solape"}],
{x: "x", y: "y", text: "t", fill: "#41ab5d", fontSize: 19, fontWeight: "bold"})
]
})Señales y Sistemas Lineales - GIET - 2026/2027