# foundryts.functions.time\_series\_search
## foundryts.functions.time\_series\_search(predicate, labels=None, start=None, end=None, interval\_values=None, before='nearest', internal='default', after='nearest', min\_duration=None, max\_duration=None)
Returns a function that will search intervals on a time series using the provided predicate.
The function will return time intervals where the predicate is true.
Each returned interval is evaluated to the associated [`statistics()`](../functions-statistics/index.md#foundryts.functions.statistics). The [`dsl()`](../functions-dsl/index.md#foundryts.functions.dsl) formula in
`interval_values` will be used for evaluating the final [`statistics()`](../functions-statistics/index.md#foundryts.functions.statistics).
The specified interpolation strategies are used for filling in missing timestamps. See [`interpolate()`](../functions-interpolate/index.md#foundryts.functions.interpolate)
for more details on interpolation and strategies.
The intervals produced by this function are equivalent to events in Quiver. This is particularly
useful when a time series demonstrates intervaled behavior and analysis on the time series requires
access to the intervals. Each time series can then be split into ranges using [`time_range()`](../functions-time-range/index.md#foundryts.functions.time_range) such that
each interval is a new [`time_range()`](../functions-time-range/index.md#foundryts.functions.time_range) and operations can be applied independently on each time-range.
* **Parameters:**
* **predicate** ([*str*](https://docs.python.org/3/library/stdtypes.html#str)) – The predicate to search for intervals using a [`dsl()`](../functions-dsl/index.md#foundryts.functions.dsl) conditional program.
* **labels** (*Union* *\[*[*str*](https://docs.python.org/3/library/stdtypes.html#str) *,* *List* *\[*[*str*](https://docs.python.org/3/library/stdtypes.html#str) *]* *]* *,* *optional*) – Aliases for each input time series to refer to them in `predicate` and `interval_values`
(default is \[‘a’, ‘b’, …, ‘aa’, ‘ab’, …]).
* **start** ([*int*](https://docs.python.org/3/library/functions.html#int) *|* *datetime* *|* [*str*](https://docs.python.org/3/library/stdtypes.html#str) *,* *optional*) – Timestamp (inclusive) to start evaluating intervals in the time series. For an interval overlapping with the
`start` timestamp, the full interval will be included in the output (default is pandas.Timestamp.min).
* **end** ([*int*](https://docs.python.org/3/library/functions.html#int) *|* *datetime* *|* [*str*](https://docs.python.org/3/library/stdtypes.html#str) *,* *optional*) – Timestamp (exclusive) to end evaluating intervals in the time series. For an interval overlapping with the
`end` timestamp, the full interval will be included in the output (default is pandas.Timestamp.max\`).
* **interval\_values** ([*str*](https://docs.python.org/3/library/stdtypes.html#str) *,* *optional*) – [`dsl()`](../functions-dsl/index.md#foundryts.functions.dsl) program to transform the values that the interval statistics are computed over. This is required
for a non-numeric input time series since statistics cannot be computed over non-numeric data.
(default is the first input time series).
* **before** (*Union* *\[*[*str*](https://docs.python.org/3/library/stdtypes.html#str) *,* *List* *\[*[*str*](https://docs.python.org/3/library/stdtypes.html#str) *]* *]* *,* *optional*) – Strategy for interpolating points before the first point in the series, which can be a list per series,
use a valid strategy from [`interpolate()`](../functions-interpolate/index.md#foundryts.functions.interpolate) (default is `NEAREST`).
* **internal** (*Union* *\[*[*str*](https://docs.python.org/3/library/stdtypes.html#str) *,* *List* *\[*[*str*](https://docs.python.org/3/library/stdtypes.html#str) *]* *]* *,* *optional*) – Strategy for interpolating points between existing points, which can be a list per series, use a
valid value from [`interpolate()`](../functions-interpolate/index.md#foundryts.functions.interpolate) (default is `LINEAR` for numeric
and `PREVIOUS` for enum time series).
* **after** (*Union* *\[*[*str*](https://docs.python.org/3/library/stdtypes.html#str) *,* *List* *\[*[*str*](https://docs.python.org/3/library/stdtypes.html#str) *]* *]* *,* *optional*) – Strategy for interpolating points after the last point in the series, which can be a list per series,
use a valid strategy from [`interpolate()`](../functions-interpolate/index.md#foundryts.functions.interpolate) (default is `NEAREST`).
* **min\_duration** ([*int*](https://docs.python.org/3/library/functions.html#int) *|* [*str*](https://docs.python.org/3/library/stdtypes.html#str) *|* [*datetime.timedelta*](https://docs.python.org/3/library/datetime.html#datetime.timedelta) *,* *optional*) – Minimum duration for which predicate must be true for the time-range to qualify as an interval.
* **max\_duration** ([*int*](https://docs.python.org/3/library/functions.html#int) *|* [*str*](https://docs.python.org/3/library/stdtypes.html#str) *|* [*datetime.timedelta*](https://docs.python.org/3/library/datetime.html#datetime.timedelta) *,* *optional*) – Maximum duration for which predicate must be true for the time-range to qualify as an interval.
* **Returns:**
A function that returns the statistics over intervals satisfying the predicate for input time series.
* **Return type:**
(Union\[[FunctionNode](../nodes-function-node/index.md#foundryts.nodes.FunctionNode), NodeCollections]) -> SummaryNode
## Dataframe schema
| Column name | Type | Description |
|--------------------------|----------|--------------------------------------------------------------------------|
| count | int | Number of data points in the interval. |
| earliest\_point.timestamp | datetime | Timestamp of the first data point in the interval. |
| earliest\_point.value | float | Value of the first data point in the interval. |
| end\_timestamp | datetime | Timestamp (exclusive) of the end of the interval. |
| largest\_point.timestamp | datetime | Timestamp of the data point with the largest value
in the interval. |
| largest\_point.value | float | Largest value in the interval. |
| latest\_point.timestamp | datetime | Timestamp of the most recent data point in the
interval. |
| latest\_point.value | float | Value of the most recent data point in the interval. |
| mean | float | Average value of all data points in the interval. |
| smallest\_point.timestamp | datetime | Timestamp of the data point with the smallest value
in the interval. |
| smallest\_point.value | float | Smallest value in the interval. |
| start\_timestamp | datetime | Timestamp of the first data point in the interval. |
| standard\_deviation | float | Standard deviation of the data points in the
interval. |
| duration.seconds | int | Duration of the interval in seconds. |
| duration.subsecond\_nanos | int | Duration of the interval in nanoseconds. |
:::callout{theme="success" title="See Also"}
[`interpolate()`](../functions-interpolate/index.md#foundryts.functions.interpolate), [`statistics()`](../functions-statistics/index.md#foundryts.functions.statistics)
:::
## Examples
```pycon
>>> discrete_series = F.points(
... (0, 1.0),
... (1, 2.0),
... (2, 2.0),
... (3, 3.0),
... (4, 5.0),
... (5, 6.0),
... (6, 4.0),
... (7, 2.0),
... (8, 6.0),
... (9, 7.0),
... (10, 8.0),
... (11, 10.0),
... (12, 11.0),
... name="discrete",
... )
>>> discrete_series.to_pandas()
timestamp value
0 1970-01-01 00:00:00.000000000 1.0
1 1970-01-01 00:00:00.000000001 2.0
2 1970-01-01 00:00:00.000000002 2.0
3 1970-01-01 00:00:00.000000003 3.0
4 1970-01-01 00:00:00.000000004 5.0
5 1970-01-01 00:00:00.000000005 6.0
6 1970-01-01 00:00:00.000000006 4.0
7 1970-01-01 00:00:00.000000007 2.0
8 1970-01-01 00:00:00.000000008 6.0
9 1970-01-01 00:00:00.000000009 7.0
10 1970-01-01 00:00:00.000000010 8.0
11 1970-01-01 00:00:00.000000011 10.0
12 1970-01-01 00:00:00.000000012 11.0
```
```pycon
>>> even_search = F.time_series_search(
... predicate="discrete % 2 == 0",
... interval_values="discrete",
... labels="discrete",
... )(discrete_series)
# 3 Intervals with points:
# Interval 1: [(1, 2.0), (2, 2.0)]
# Interval 2: [(5, 6.0), (6, 4.0), (7, 2.0), (8, 6.0)]
# Interval 3: [(10, 8.0), (11, 10.0)]
>>> even_search.to_pandas()
count duration.seconds duration.subsecond_nanos earliest_point.timestamp earliest_point.value end_time largest_point.timestamp largest_point.value latest_point.timestamp latest_point.value mean smallest_point.timestamp smallest_point.value standard_deviation start_time
0 2 0 2 1970-01-01 00:00:00.000000001 2.0 1970-01-01 00:00:00.000000003 1970-01-01 00:00:00.000000002 2.0 1970-01-01 00:00:00.000000002 2.0 2.0 1970-01-01 00:00:00.000000002 2.0 0.000000 1970-01-01 00:00:00.000000001
1 4 0 4 1970-01-01 00:00:00.000000005 6.0 1970-01-01 00:00:00.000000009 1970-01-01 00:00:00.000000008 6.0 1970-01-01 00:00:00.000000008 6.0 4.5 1970-01-01 00:00:00.000000007 2.0 1.658312 1970-01-01 00:00:00.000000005
2 2 0 2 1970-01-01 00:00:00.000000010 8.0 1970-01-01 00:00:00.000000012 1970-01-01 00:00:00.000000011 10.0 1970-01-01 00:00:00.000000011 10.0 9.0 1970-01-01 00:00:00.000000010 8.0 1.000000 1970-01-01 00:00:00.000000010
```
```pycon
>>> search_formula = F.time_series_search(
... predicate="discrete % 2 == 0",
... interval_values="discrete * 2",
... labels="discrete",
... )(discrete_series)
# 3 Intervals with points (with doubled values):
# Interval 1: [(1, 4.0), (2, 4.0)]
# Interval 2: [(5, 12.0), (6, 8.0), (7, 4.0), (8, 12.0)]
# Interval 3: [(10, 16.0), (11, 20.0)]
>>> search_formula.to_pandas()
count duration.seconds duration.subsecond_nanos earliest_point.timestamp earliest_point.value end_time largest_point.timestamp largest_point.value latest_point.timestamp latest_point.value mean smallest_point.timestamp smallest_point.value standard_deviation start_time
0 2 0 2 1970-01-01 00:00:00.000000001 4.0 1970-01-01 00:00:00.000000003 1970-01-01 00:00:00.000000002 4.0 1970-01-01 00:00:00.000000002 4.0 4.0 1970-01-01 00:00:00.000000002 4.0 0.000000 1970-01-01 00:00:00.000000001
1 4 0 4 1970-01-01 00:00:00.000000005 12.0 1970-01-01 00:00:00.000000009 1970-01-01 00:00:00.000000008 12.0 1970-01-01 00:00:00.000000008 12.0 9.0 1970-01-01 00:00:00.000000007 4.0 3.316625 1970-01-01 00:00:00.000000005
2 2 0 2 1970-01-01 00:00:00.000000010 16.0 1970-01-01 00:00:00.000000012 1970-01-01 00:00:00.000000011 20.0 1970-01-01 00:00:00.000000011 20.0 18.0 1970-01-01 00:00:00.000000010 16.0 2.000000 1970-01-01 00:00:00.000000010
```
```pycon
>>> min_duration_search = F.time_series_search(
... predicate="discrete % 2 == 0",
... interval_values="discrete",
... labels="discrete",
... min_duration="3ns",
... )(discrete_series)
# The first and last intervals are filtered due to duration < 3
# 1 Interval with points:
# [(5, 6.0), (6, 4.0), (7, 2.0), (8, 6.0)]
>>> min_duration_search.to_pandas()
count duration.seconds duration.subsecond_nanos earliest_point.timestamp earliest_point.value end_time largest_point.timestamp largest_point.value latest_point.timestamp latest_point.value mean smallest_point.timestamp smallest_point.value standard_deviation start_time
0 4 0 4 1970-01-01 00:00:00.000000005 6.0 1970-01-01 00:00:00.000000009 1970-01-01 00:00:00.000000008 6.0 1970-01-01 00:00:00.000000008 6.0 4.5 1970-01-01 00:00:00.000000007 2.0 1.658312 1970-01-01 00:00:00.000000005
```
```pycon
>>> max_duration_search = F.time_series_search(
... predicate="discrete % 2 == 0",
... interval_values="discrete",
... labels="discrete",
... max_duration="3ns",
... )(discrete_series)
# Second interval is filtered due to duration > 3
# 2 Intervals with points:
# Interval 1: [(1, 2.0), (2, 2.0)]
# Interval 2: [(10, 8.0), (11, 10.0)]
>>> max_duration_search.to_pandas()
count duration.seconds duration.subsecond_nanos earliest_point.timestamp earliest_point.value end_time largest_point.timestamp largest_point.value latest_point.timestamp latest_point.value mean smallest_point.timestamp smallest_point.value standard_deviation start_time
0 2 0 2 1970-01-01 00:00:00.000000001 2.0 1970-01-01 00:00:00.000000003 1970-01-01 00:00:00.000000002 2.0 1970-01-01 00:00:00.000000002 2.0 2.0 1970-01-01 00:00:00.000000002 2.0 0.0 1970-01-01 00:00:00.000000001
1 2 0 2 1970-01-01 00:00:00.000000010 8.0 1970-01-01 00:00:00.000000012 1970-01-01 00:00:00.000000011 10.0 1970-01-01 00:00:00.000000011 10.0 9.0 1970-01-01 00:00:00.000000010 8.0 1.0 1970-01-01 00:00:00.000000010
```
```pycon
>>> toggle_series = F.points(
... (0, "OFF"),
... (1, "ON"),
... (2, "OFF"),
... (3, "OFF"),
... (4, "ON"),
... (5, "ON"),
... (6, "ON"),
... (7, "OFF"),
... (8, "ON"),
... (9, "ON"),
... (10, "OFF"),
... (11, "OFF"),
... (12, "ON"),
... name="toggle",
... )
>>> toggle_series.to_pandas()
timestamp value
0 1970-01-01 00:00:00.000000000 OFF
1 1970-01-01 00:00:00.000000001 ON
2 1970-01-01 00:00:00.000000002 OFF
3 1970-01-01 00:00:00.000000003 OFF
4 1970-01-01 00:00:00.000000004 ON
5 1970-01-01 00:00:00.000000005 ON
6 1970-01-01 00:00:00.000000006 ON
7 1970-01-01 00:00:00.000000007 OFF
8 1970-01-01 00:00:00.000000008 ON
9 1970-01-01 00:00:00.000000009 ON
10 1970-01-01 00:00:00.000000010 OFF
11 1970-01-01 00:00:00.000000011 OFF
12 1970-01-01 00:00:00.000000012 ON
>>> cross_series_search = F.time_series_search(
... predicate='toggle == "ON"',
... interval_values="discrete",
... labels=["toggle", "discrete"],
... )([toggle_series, discrete_series])
# 4 Intervals in discrete_series created from intervals in toggle_series where predicate is true:
# Interval 1: [(1, 2.0)]
# Interval 2: [(4, 5.0), (5, 6.0), (6, 4.0)]
# Interval 3: [(8, 6.0), (9, 7.0)]
# Interval 4: [(12, 11.0)]
>>> cross_series_search.to_pandas()
count duration.seconds duration.subsecond_nanos earliest_point.timestamp earliest_point.value end_time largest_point.timestamp largest_point.value latest_point.timestamp latest_point.value mean smallest_point.timestamp smallest_point.value standard_deviation start_time
0 1 0 1 1970-01-01 00:00:00.000000001 2.0 1970-01-01 00:00:00.000000002 1970-01-01 00:00:00.000000001 2.0 1970-01-01 00:00:00.000000001 2.0 2.0 1970-01-01 00:00:00.000000001 2.0 0.000000 1970-01-01 00:00:00.000000001
1 3 0 3 1970-01-01 00:00:00.000000004 5.0 1970-01-01 00:00:00.000000007 1970-01-01 00:00:00.000000005 6.0 1970-01-01 00:00:00.000000006 4.0 5.0 1970-01-01 00:00:00.000000006 4.0 0.816497 1970-01-01 00:00:00.000000004
2 2 0 2 1970-01-01 00:00:00.000000008 6.0 1970-01-01 00:00:00.000000010 1970-01-01 00:00:00.000000009 7.0 1970-01-01 00:00:00.000000009 7.0 6.5 1970-01-01 00:00:00.000000008 6.0 0.500000 1970-01-01 00:00:00.000000008
3 1 0 1 1970-01-01 00:00:00.000000012 11.0 1970-01-01 00:00:00.000000013 1970-01-01 00:00:00.000000012 11.0 1970-01-01 00:00:00.000000012 11.0 11.0 1970-01-01 00:00:00.000000012 11.0 0.000000 1970-01-01 00:00:00.000000012
```