Skip to content

Commit c1930cb

Browse files
EliEli
authored andcommitted
Added a 'blend' option for transition_ts.
Updated notebook for transition.ipynb and rebuild docs.
1 parent 755140c commit c1930cb

File tree

17 files changed

+355
-232
lines changed

17 files changed

+355
-232
lines changed
11.8 KB
Loading
1.51 KB
Loading

docs/html/_modules/scipy/interpolate/_cubic.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ <h1>Source code for scipy.interpolate._cubic</h1><div class="highlight"><pre>
264264

265265

266266
<div class="viewcode-block" id="PchipInterpolator">
267-
<a class="viewcode-back" href="../../../vtools.functions.html#vtools.data.timeseries.PchipInterpolator">[docs]</a>
267+
<a class="viewcode-back" href="../../../vtools.functions.html#vtools.functions.envelope.PchipInterpolator">[docs]</a>
268268
<span class="k">class</span> <span class="nc">PchipInterpolator</span><span class="p">(</span><span class="n">CubicHermiteSpline</span><span class="p">):</span>
269269
<span class="w"> </span><span class="sa">r</span><span class="sd">&quot;&quot;&quot;PCHIP 1-D monotonic cubic interpolation.</span>
270270

@@ -342,7 +342,7 @@ <h1>Source code for scipy.interpolate._cubic</h1><div class="highlight"><pre>
342342
<span class="sd"> &quot;&quot;&quot;</span>
343343

344344
<div class="viewcode-block" id="PchipInterpolator.__init__">
345-
<a class="viewcode-back" href="../../../vtools.functions.html#vtools.data.timeseries.PchipInterpolator.__init__">[docs]</a>
345+
<a class="viewcode-back" href="../../../vtools.functions.html#vtools.functions.envelope.PchipInterpolator.__init__">[docs]</a>
346346
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">extrapolate</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
347347
<span class="n">x</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">axis</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">prepare_input</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">axis</span><span class="p">)</span>
348348
<span class="n">xp</span> <span class="o">=</span> <span class="n">x</span><span class="o">.</span><span class="n">reshape</span><span class="p">((</span><span class="n">x</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">0</span><span class="p">],)</span> <span class="o">+</span> <span class="p">(</span><span class="mi">1</span><span class="p">,)</span><span class="o">*</span><span class="p">(</span><span class="n">y</span><span class="o">.</span><span class="n">ndim</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
@@ -352,7 +352,7 @@ <h1>Source code for scipy.interpolate._cubic</h1><div class="highlight"><pre>
352352

353353

354354
<div class="viewcode-block" id="PchipInterpolator._edge_case">
355-
<a class="viewcode-back" href="../../../vtools.functions.html#vtools.data.timeseries.PchipInterpolator._edge_case">[docs]</a>
355+
<a class="viewcode-back" href="../../../vtools.functions.html#vtools.functions.envelope.PchipInterpolator._edge_case">[docs]</a>
356356
<span class="nd">@staticmethod</span>
357357
<span class="k">def</span> <span class="nf">_edge_case</span><span class="p">(</span><span class="n">h0</span><span class="p">,</span> <span class="n">h1</span><span class="p">,</span> <span class="n">m0</span><span class="p">,</span> <span class="n">m1</span><span class="p">):</span>
358358
<span class="c1"># one-sided three-point estimate for the derivative</span>
@@ -370,7 +370,7 @@ <h1>Source code for scipy.interpolate._cubic</h1><div class="highlight"><pre>
370370

371371

372372
<div class="viewcode-block" id="PchipInterpolator._find_derivatives">
373-
<a class="viewcode-back" href="../../../vtools.functions.html#vtools.data.timeseries.PchipInterpolator._find_derivatives">[docs]</a>
373+
<a class="viewcode-back" href="../../../vtools.functions.html#vtools.functions.envelope.PchipInterpolator._find_derivatives">[docs]</a>
374374
<span class="nd">@staticmethod</span>
375375
<span class="k">def</span> <span class="nf">_find_derivatives</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
376376
<span class="c1"># Determine the derivatives at the points y_k, d_k, by using</span>

docs/html/_modules/vtools/data/timeseries.html

Lines changed: 5 additions & 115 deletions
Large diffs are not rendered by default.

docs/html/_modules/vtools/functions/transition.html

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,20 @@ <h1>Source code for vtools.functions.transition</h1><div class="highlight"><pre>
224224
<span class="sd"> ts1 : pandas.Series or pandas.DataFrame</span>
225225
<span class="sd"> The final time series segment. Must share the same frequency and type as `ts0`.</span>
226226

227-
<span class="sd"> method : {&quot;linear&quot;, &quot;pchip&quot;}, default=&quot;linear&quot;</span>
228-
<span class="sd"> The interpolation method to use for generating the transition.</span>
227+
<span class="sd"> method : {&quot;linear&quot;, &quot;pchip&quot;, &quot;blend&quot;}, default=&quot;linear&quot;</span>
228+
<span class="sd"> The interpolation strategy:</span>
229+
<span class="sd"> - &quot;linear&quot;: interpolate across a gap using endpoints from ts0/ts1.</span>
230+
<span class="sd"> - &quot;pchip&quot;: shape-preserving interpolation using nearby points (see `overlap`).</span>
231+
<span class="sd"> - &quot;blend&quot;: requires an explicit `window=(start, end)` where both ts0 and ts1</span>
232+
<span class="sd"> have values on every timestamp; returns a linear combination</span>
233+
<span class="sd"> (1 - w(t)) * ts0(t) + w(t) * ts1(t) with w(start)=0 → w(end)=1.</span>
229234

230235
<span class="sd"> window : [start, end] or None</span>
231-
<span class="sd"> If None and there&#39;s a natural gap (ts0.last &lt; ts1.first), that full gap is used.</span>
232-
<span class="sd"> If provided, start&lt;end, ts0 must have samples at/before start, ts1 at/after end.</span>
236+
<span class="sd"> - For &quot;linear&quot;/&quot;pchip&quot;: If None and there&#39;s a natural gap (ts0.last &lt; ts1.first),</span>
237+
<span class="sd"> that full gap is used. If provided, start&lt;end, ts0 must have a sample at/before</span>
238+
<span class="sd"> start and ts1 at/after end; optional widening to a natural gap via `max_snap`.</span>
239+
<span class="sd"> - For &quot;blend&quot;: **Required.** Both series must cover every timestamp in</span>
240+
<span class="sd"> [start, end] with non-missing values; no widening or gap logic is applied.</span>
233241

234242
<span class="sd"> names : None, str, or iterable of str, optional</span>
235243
<span class="sd"> - If `None` (default), inputs must share compatible column names.</span>
@@ -268,6 +276,49 @@ <h1>Source code for vtools.functions.transition</h1><div class="highlight"><pre>
268276

269277
<span class="n">freq</span> <span class="o">=</span> <span class="n">ts0</span><span class="o">.</span><span class="n">index</span><span class="o">.</span><span class="n">freq</span>
270278

279+
280+
<span class="c1"># --- BLEND mode: explicit overlap with non-missing values in both series ---</span>
281+
<span class="k">if</span> <span class="n">method</span> <span class="o">==</span> <span class="s2">&quot;blend&quot;</span><span class="p">:</span>
282+
<span class="k">if</span> <span class="n">window</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
283+
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;method=&#39;blend&#39; requires window=(start, end).&quot;</span><span class="p">)</span>
284+
<span class="n">start</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">window</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
285+
<span class="n">end</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">Timestamp</span><span class="p">(</span><span class="n">window</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
286+
<span class="k">if</span> <span class="n">start</span> <span class="o">&gt;=</span> <span class="n">end</span><span class="p">:</span>
287+
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;blend window start must be strictly before end.&quot;</span><span class="p">)</span>
288+
<span class="c1"># exact inclusive grid for the blend interval</span>
289+
<span class="n">trans_index</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">date_range</span><span class="p">(</span><span class="n">start</span><span class="o">=</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="n">end</span><span class="p">,</span> <span class="n">freq</span><span class="o">=</span><span class="n">freq</span><span class="p">)</span>
290+
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">trans_index</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">:</span>
291+
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;blend window must contain at least two timestamps.&quot;</span><span class="p">)</span>
292+
<span class="c1"># require full coverage with no NaNs</span>
293+
<span class="k">try</span><span class="p">:</span>
294+
<span class="n">seg0</span> <span class="o">=</span> <span class="n">ts0</span><span class="o">.</span><span class="n">loc</span><span class="p">[</span><span class="n">trans_index</span><span class="p">]</span>
295+
<span class="n">seg1</span> <span class="o">=</span> <span class="n">ts1</span><span class="o">.</span><span class="n">loc</span><span class="p">[</span><span class="n">trans_index</span><span class="p">]</span>
296+
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
297+
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Both series must cover every timestamp in the blend window.&quot;</span><span class="p">)</span>
298+
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">ts0</span><span class="p">,</span> <span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">):</span>
299+
<span class="k">if</span> <span class="n">seg0</span><span class="o">.</span><span class="n">isna</span><span class="p">()</span><span class="o">.</span><span class="n">any</span><span class="p">()</span><span class="o">.</span><span class="n">any</span><span class="p">()</span> <span class="ow">or</span> <span class="n">seg1</span><span class="o">.</span><span class="n">isna</span><span class="p">()</span><span class="o">.</span><span class="n">any</span><span class="p">()</span><span class="o">.</span><span class="n">any</span><span class="p">():</span>
300+
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;NaNs found within blend window in ts0/ts1.&quot;</span><span class="p">)</span>
301+
<span class="n">w</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mf">0.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">trans_index</span><span class="p">))[:,</span> <span class="kc">None</span><span class="p">]</span>
302+
<span class="n">blended_vals</span> <span class="o">=</span> <span class="p">(</span><span class="mf">1.0</span> <span class="o">-</span> <span class="n">w</span><span class="p">)</span> <span class="o">*</span> <span class="n">seg0</span><span class="o">.</span><span class="n">to_numpy</span><span class="p">(</span><span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span> <span class="o">+</span> <span class="n">w</span> <span class="o">*</span> <span class="n">seg1</span><span class="o">.</span><span class="n">to_numpy</span><span class="p">(</span><span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
303+
<span class="n">blended</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">blended_vals</span><span class="p">,</span> <span class="n">index</span><span class="o">=</span><span class="n">trans_index</span><span class="p">,</span> <span class="n">columns</span><span class="o">=</span><span class="n">ts0</span><span class="o">.</span><span class="n">columns</span><span class="p">)</span>
304+
<span class="k">else</span><span class="p">:</span>
305+
<span class="k">if</span> <span class="n">seg0</span><span class="o">.</span><span class="n">isna</span><span class="p">()</span><span class="o">.</span><span class="n">any</span><span class="p">()</span> <span class="ow">or</span> <span class="n">seg1</span><span class="o">.</span><span class="n">isna</span><span class="p">()</span><span class="o">.</span><span class="n">any</span><span class="p">():</span>
306+
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;NaNs found within blend window in ts0/ts1.&quot;</span><span class="p">)</span>
307+
<span class="n">w</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mf">0.0</span><span class="p">,</span> <span class="mf">1.0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">trans_index</span><span class="p">))</span>
308+
<span class="n">blended_vals</span> <span class="o">=</span> <span class="p">(</span><span class="mf">1.0</span> <span class="o">-</span> <span class="n">w</span><span class="p">)</span> <span class="o">*</span> <span class="n">seg0</span><span class="o">.</span><span class="n">to_numpy</span><span class="p">(</span><span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span> <span class="o">+</span> <span class="n">w</span> <span class="o">*</span> <span class="n">seg1</span><span class="o">.</span><span class="n">to_numpy</span><span class="p">(</span><span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
309+
<span class="n">blended</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">Series</span><span class="p">(</span><span class="n">blended_vals</span><span class="p">,</span> <span class="n">index</span><span class="o">=</span><span class="n">trans_index</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">ts0</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
310+
<span class="c1"># splice: ts0 before start, blend in [start,end], ts1 after end</span>
311+
<span class="k">if</span> <span class="n">return_type</span> <span class="o">==</span> <span class="s2">&quot;glue&quot;</span><span class="p">:</span>
312+
<span class="k">return</span> <span class="n">blended</span>
313+
<span class="k">elif</span> <span class="n">return_type</span> <span class="o">==</span> <span class="s2">&quot;series&quot;</span><span class="p">:</span>
314+
<span class="n">left</span> <span class="o">=</span> <span class="n">ts0</span><span class="o">.</span><span class="n">loc</span><span class="p">[</span><span class="n">ts0</span><span class="o">.</span><span class="n">index</span> <span class="o">&lt;</span> <span class="n">start</span><span class="p">]</span>
315+
<span class="n">right</span> <span class="o">=</span> <span class="n">ts1</span><span class="o">.</span><span class="n">loc</span><span class="p">[</span><span class="n">ts1</span><span class="o">.</span><span class="n">index</span> <span class="o">&gt;</span> <span class="n">end</span><span class="p">]</span>
316+
<span class="k">return</span> <span class="n">pd</span><span class="o">.</span><span class="n">concat</span><span class="p">([</span><span class="n">left</span><span class="p">,</span> <span class="n">blended</span><span class="p">,</span> <span class="n">right</span><span class="p">])</span>
317+
<span class="k">else</span><span class="p">:</span>
318+
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;return_type must be either &#39;glue&#39; or &#39;series&#39;.&quot;</span><span class="p">)</span>
319+
320+
321+
271322
<span class="c1"># `resolved` is either:</span>
272323
<span class="c1"># • (start_time, end_time): data-aligned gap anchors computed from `window`</span>
273324
<span class="c1"># (and, if applicable, widened inside the natural gap by `max_snap`), where</span>
@@ -349,7 +400,7 @@ <h1>Source code for vtools.functions.transition</h1><div class="highlight"><pre>
349400
<span class="p">)</span>
350401
<span class="n">interpolated</span><span class="p">[</span><span class="n">col</span><span class="p">]</span> <span class="o">=</span> <span class="n">interp</span><span class="p">(</span><span class="n">trans_index</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="n">np</span><span class="o">.</span><span class="n">int64</span><span class="p">))</span>
351402
<span class="k">else</span><span class="p">:</span>
352-
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Only &#39;linear&#39; and &#39;pchip&#39; methods are supported.&quot;</span><span class="p">)</span>
403+
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Only &#39;linear&#39; and &#39;pchip&#39; and &#39;blend&#39; methods are supported.&quot;</span><span class="p">)</span>
353404

354405
<span class="c1"># Final output</span>
355406
<span class="k">if</span> <span class="n">return_type</span> <span class="o">==</span> <span class="s2">&quot;glue&quot;</span><span class="p">:</span>

0 commit comments

Comments
 (0)