Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ but cannot always guarantee backwards compatibility. Changes that may **break co

**Dependencies**

- Moved `xarray` from core dependencies to optional dependencies. [#2974](https://github.com/unit8co/darts/pull/2974) by [Jakub Chłapek](https://github.com/jakubchlapek).

### For developers of the library:

## [0.39.0](https://github.com/unit8co/darts/tree/0.39.0) (2025-11-23)
Expand Down
27 changes: 15 additions & 12 deletions darts/ad/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,28 +657,31 @@ def _plot_series(series, ax_id, linewidth, label_name, **kwargs):
label_name
Name that will appear in the legend.
"""
data_array = series.data_array(copy=False)
for i, c in enumerate(data_array.component[:10]):
comp = data_array.sel(component=c)

if comp.sample.size > 1:
central_series = comp.mean(dim="sample")
low_series = comp.quantile(q=0.05, dim="sample")
high_series = comp.quantile(q=0.95, dim="sample")
for i, c in enumerate(series.components[:10]):
comp_series = series[c]

if series.is_stochastic:
central_series = comp_series.mean(axis=2)
low_series = comp_series.quantile(q=0.05)
high_series = comp_series.quantile(q=0.95)
else:
central_series = comp
central_series = comp_series

label_to_use = (
(label_name + ("_" + str(i) if len(series.components) > 1 else ""))
if label_name != ""
else "" + str(str(c.values))
else "" + str(c)
)

central_series.plot(ax=ax_id, linewidth=linewidth, label=label_to_use, **kwargs)

if comp.sample.size > 1:
if series.is_stochastic:
ax_id.fill_between(
series.time_index, low_series, high_series, alpha=0.25, **kwargs
series.time_index,
low_series.values().flatten(),
high_series.values().flatten(),
alpha=0.25,
**kwargs,
)


Expand Down
18 changes: 5 additions & 13 deletions darts/dataprocessing/dtw/_plot.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import Union

import numpy as np
import xarray as xr
from matplotlib import pyplot as plt


Expand Down Expand Up @@ -142,23 +141,17 @@ def plot_alignment(
series1 += series1_y_offset
series2 += series2_y_offset

xa1 = series1.data_array(copy=False)
xa2 = series2.data_array(copy=False)

path = self.path()
n = len(path)

time_dim1 = series1.time_dim
time_dim2 = series2.time_dim

x_coords1 = np.array(xa1[time_dim1], dtype=xa1[time_dim1].dtype)[path[:, 0]]
x_coords2 = np.array(xa2[time_dim2], dtype=xa2[time_dim2].dtype)[path[:, 1]]
x_coords1 = series1.time_index[path[:, 0]]
x_coords2 = series2.time_index[path[:, 1]]

y_coords1 = series1.univariate_values()[path[:, 0]]
y_coords2 = series2.univariate_values()[path[:, 1]]

if series1.has_datetime_index:
x_dtype = xa1[time_dim1].dtype
x_dtype = series1.time_index.dtype
x_nan = np.datetime64("NaT")
else:
x_dtype = np.float64
Expand All @@ -175,8 +168,7 @@ def plot_alignment(
y_coords[1::3] = y_coords2
y_coords[2::3] = np.nan

arr = xr.DataArray(y_coords, dims=["value"], coords={"value": x_coords})
xr.plot.line(arr, x="value", **args_line)

series1.plot(**args_series1)
series2.plot(**args_series2)

plt.plot(x_coords, y_coords, **args_line)
8 changes: 2 additions & 6 deletions darts/tests/dataprocessing/dtw/test_dtw.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,9 @@ def test_itakura_window(self):
assert 1 > dist

def test_warp(self):
# Support different time dimension names
xa1 = self.series1.data_array().rename({"time": "time1"})
xa2 = self.series2.data_array().rename({"time": "time2"})

static_covs = pd.DataFrame([[0.0, 1.0]], columns=["st1", "st2"])
series1 = TimeSeries.from_xarray(xa1).with_static_covariates(static_covs)
series2 = TimeSeries.from_xarray(xa2).with_static_covariates(static_covs)
series1 = self.series1.with_static_covariates(static_covs)
series2 = self.series2.with_static_covariates(static_covs)
series1_copy = series1.copy()
series2_copy = series2.copy()

Expand Down
23 changes: 16 additions & 7 deletions darts/tests/test_timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import numpy as np
import pandas as pd
import pytest
import xarray as xr
from scipy.stats import kurtosis, skew

from darts import TimeSeries, concatenate, slice_intersect
Expand All @@ -17,7 +16,7 @@
quantile_names,
)
from darts.utils.timeseries_generation import constant_timeseries, linear_timeseries
from darts.utils.utils import expand_arr, freqs, generate_index
from darts.utils.utils import XARRAY_AVAILABLE, expand_arr, freqs, generate_index

TEST_BACKENDS = ["pandas"]

Expand Down Expand Up @@ -65,14 +64,17 @@ def test_creation(self):
)
assert ts.components.tolist() == ["a", "b", "a_1", "a_2", "b_1"]

# creation using from_xarray()
@pytest.mark.skipif(not XARRAY_AVAILABLE, reason="xarray required")
def test_xarray_creation(self):
import xarray as xr

ar = xr.DataArray(
np.random.randn(10, 2, 1),
dims=("time", "component", "sample"),
coords={"time": self.times, "component": ["a", "b"]},
name="time series",
)
_ = TimeSeries.from_xarray(ar)
ts = TimeSeries.from_xarray(ar)
assert ts.components.tolist() == ["a", "b"]

def test_from_times_and_values(self):
# Test creation from times and values
Expand Down Expand Up @@ -401,7 +403,10 @@ def test_univariate_component(self):
# only the right static covariate column should be retained
assert univ_series.static_covariates.sum().sum() == 1.1

@pytest.mark.skipif(not XARRAY_AVAILABLE, reason="requires xarray")
def test_column_names(self):
import xarray as xr

# test the column names resolution
columns_before = [
["0", "1", "2"],
Expand Down Expand Up @@ -810,14 +815,17 @@ def test_ops(self):
# Cannot divide by 0.
self.series1 / 0

def test_ops_array(self):
@pytest.mark.skipif(not XARRAY_AVAILABLE, reason="xarray required")
def test_ops_xarray(self):
# can work with xarray directly
series2_x = self.series2.data_array(copy=False)
assert self.series1 + self.series2 == self.series1 + series2_x
assert self.series1 - self.series2 == self.series1 - series2_x
assert self.series1 * self.series2 == self.series1 * series2_x
assert self.series1 / self.series2 == self.series1 / series2_x
assert self.series1**self.series2 == self.series1**series2_x

def test_ops_ndarray(self):
# can work with ndarray directly
series2_nd = self.series2.all_values(copy=False)
assert self.series1 + self.series2 == self.series1 + series2_nd
Expand Down Expand Up @@ -1277,6 +1285,7 @@ def test_fillna_value(self):
assert not np.isnan(series_no_nan.all_values(copy=False)).any()
assert series_1 == series_no_nan

@pytest.mark.skipif(not XARRAY_AVAILABLE, reason="xarray required")
def test_resample_timeseries(self):
# 01/01/2013 -> 10/01/2013, one value per day: 0 1 2 3 ... 9
times = pd.date_range("20130101", "20130110")
Expand Down Expand Up @@ -2404,7 +2413,7 @@ def helper_test_prepend(test_series: TimeSeries):
def helper_test_prepend_values(test_series: TimeSeries):
# reconstruct series
seriesA, seriesB = test_series.split_after(pd.Timestamp("20130106"))
arrayA = seriesA.data_array().values
arrayA = seriesA._values
prepended = seriesB.prepend_values(arrayA)
assert prepended == test_series
assert test_series.time_index.equals(prepended.time_index)
Expand Down
8 changes: 5 additions & 3 deletions darts/tests/test_timeseries_static_covariates.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
STATIC_COV_TAG,
)
from darts.utils.timeseries_generation import linear_timeseries
from darts.utils.utils import generate_index
from darts.utils.utils import XARRAY_AVAILABLE, generate_index

TEST_BACKENDS = ["pandas"]

Expand Down Expand Up @@ -92,7 +92,8 @@ def test_ts_from_x(self, tag, tmpdir_module):
ts, x = setup_tag(tag, ts)
kwargs = {tag: x}

self.helper_test_transfer(tag, ts, TimeSeries.from_xarray(ts.data_array()))
if XARRAY_AVAILABLE:
self.helper_test_transfer(tag, ts, TimeSeries.from_xarray(ts.data_array()))
self.helper_test_transfer(
tag, ts, TimeSeries.from_dataframe(ts.to_dataframe(), **kwargs)
)
Expand Down Expand Up @@ -922,7 +923,8 @@ def test_ts_methods(self, tag):
self.helper_test_transfer(tag, ts, ts.diff())
self.helper_test_transfer(tag, ts, ts.univariate_component(0))
self.helper_test_transfer(tag, ts, ts.map(lambda x: x + 1))
self.helper_test_transfer(tag, ts, ts.resample(ts.freq))
if XARRAY_AVAILABLE:
self.helper_test_transfer(tag, ts, ts.resample(ts.freq))
self.helper_test_transfer(tag, ts, ts[:5].append(ts[5:]))
self.helper_test_transfer(tag, ts, ts.append_values(ts.all_values()))

Expand Down
Loading
Loading