Package: similarity-ts
SimilarityTS: Toolkit for the Evaluation of Similarity for multivariate time seriesTable of ContentsPackage DescriptionInstallationUsageConfiguring the toolkitExtending the toolkitLicenseAcknowledgementsPackage DescriptionSimilarityTS is an open-source package designed to facilitate the evaluation and comparison of
multivariate time series data. It provides a comprehensive toolkit for analyzing, visualizing, and reporting multiple
metrics and figures derived from time series datasets. The toolkit simplifies the process of evaluating the similarity of
time series by offering data preprocessing, metrics computation, visualization, statistical analysis, and report generation
functionalities. With its customizable features, SimilarityTS empowers researchers and data
scientists to gain insights, identify patterns, and make informed decisions based on their time series data.A command line interface tool is also available at:https://github.com/alejandrofdez-us/similarity-ts-cli.Available metricsThis toolkit can compute the following metrics:kl: Kullback-Leibler divergencejs: Jensen-Shannon divergenceks: Kolmogorov-Smirnov testmmd: Maximum Mean DiscrepancydtwDynamic Time Warpingcc: Difference of co-variancescp: Difference of correlationshi: Difference of histogramsAvailable figuresThis toolkit can generate the following figures:2d: the ordinary graphical representation of the time series in a 2D figure with the time represented on the x axis
and the data values on the y-axis forthe complete multivariate time series; anda plot per column.Each generated figure plots both thets1and thets2data to easily obtain key insights into
the similarities or differences between them.delta: the differences between the values of each column grouped by periods of time. For instance, the differences
between the percentage of cpu used every 10, 25 or 50 minutes. These delta can be used as a means of comparison between
time series short-/mid-/long-term patterns.pca: the linear dimensionality reduction technique that aims to find the principal components of a data set by
computing the linear combinations of the original characteristics that explain the most variance in the data.tsne: a tool for visualising high-dimensional data sets in a 2D or 3D graphical representation allowing the creation
of a single map that reveals the structure of the data at many different scales.dtwpath: In addition to the numerical similarity measure, the graphical representation of the DTW path of each
column can be useful to better analyse the similarities or differences between the time series columns. Notice that
there is no multivariate representation of DTW paths, only single column representations.InstallationInstall the package using pip in your local environment:pipinstallsimilarity-tsUsageUsers must create a newSimilarityTsobject by calling its constructor and passing the following parameters.ts1This time series may represent the baseline or ground truth time
series as anumpyarray with shape[length, num_features].ts2sA single or a set of time series as anumpyarray with shape[num_time_series, length, num_features].Constraints:ts1time-series andts2stime-series file(s) must:have the same dimensionality (number of columns)not include a timestamp columninclude only numeric valuesallts2stime-series must have the same length (number of rows).Ifts1time-series is longer (more rows) thants2stime-series, thets1time series will be
divided in windows of the same length as thets2stime-series.For eachts2stime-series, the most similar window (*) fromts1time series is selected.Finally, metrics and figures that assess the similarity between each pair ofts2stime-series and its
associated most similarts1window are computed.(*) The metric used for the selection of the most
similarts1time-series window per eachts2stime-series file is selectable.dtwis the default selected metric, however, any of
themetricsare also available for this purpose. See thetoolkit configuration section.Minimal usage examples:Usage examples can be found at:https://github.com/alejandrofdez-us/similarity-ts/tree/main/usage_examples.Compute metrics between random time series (ts1: one time series of lenght 200 and 2 dimensions andts2: five time series of length 100 and 2 dimensions):importnumpyasnpfromsimilarity_ts.similarity_tsimportSimilarityTsts1=np.random.rand(200,2)ts2s=np.random.rand(5,100,2)similarity_ts=SimilarityTs(ts1,ts2s)forts2_name,metric_name,computed_metricinsimilarity_ts.get_metric_computer():print(f'{ts2_name}.{metric_name}:{computed_metric}')Compute metrics and figures between random time series and save figures:importosimportnumpyasnpfromsimilarity_ts.plots.plot_factoryimportPlotFactoryfromsimilarity_ts.similarity_tsimportSimilarityTsdefmain():ts1=np.random.rand(200,2)ts2s=np.random.rand(5,100,2)similarity_ts=SimilarityTs(ts1,ts2s)forts2_name,metric_name,computed_metricinsimilarity_ts.get_metric_computer():print(f'{ts2_name}.{metric_name}:{computed_metric}')forts2_name,plot_name,generated_plotsinsimilarity_ts.get_plot_computer():__save_figures(ts2_name,plot_name,generated_plots)def__save_figures(filename,plot_name,generated_plots):forplotingenerated_plots:dir_path=__create_directory(filename,f'figures',plot_name)plot[0].savefig(f'{dir_path}{plot[0].axes[0].get_title()}.pdf',format='pdf',bbox_inches='tight')def__create_directory(filename,path,plot_name):ifplot_nameinPlotFactory.get_instance().figures_requires_all_samples:dir_path=f'{path}/{plot_name}/'else:original_filename=os.path.splitext(filename)[0]dir_path=f'{path}/{original_filename}/{plot_name}/'os.makedirs(dir_path,exist_ok=True)returndir_pathif__name__=='__main__':main()Configuring the ToolkitUsers can provide metrics or figures to be computed/generated and some other parameterisation. The following code snippet
creates a configuration object that should be passed to theSimilarityTsconstructor:def__create_similarity_ts_config():# The list of metrics names that will be computedmetric_config=MetricConfig(['js','mmd'])# The list of figure names that will be generated and the time step in seconds of the time series.plot_config=PlotConfig(['delta','pca'],timestamp_frequency_seconds=300)# Name of each time series of the ts2s set of time seriests2_names=['ts2_1_name','ts2_2_name','ts2_3_name','ts2_4_name','ts2_5_name']# Name of the featuresheader_names=['feature1_name','feature2_name']# Creation of the configuration# stride for cutting the ts1 when needed# metric used for selecting the most similar windowsimilarity_ts_config=SimilarityTsConfig(metric_config,plot_config,stride=10,window_selection_metric='kl',ts2_names=ts2_names,header_names=header_names)returnsimilarity_ts_configIf no metrics nor figures are provided, the tool will compute all the available metrics and figures.The following arguments are also available for fine-tuning:timestamp_frequency_seconds: the frequency in seconds in which samples were taken. This is needed to generate the delta figures with correct time magnitudes. By default is1second.stride: whents1time-series is longer thants2stime-series the windows are computed by using a
stride of1by default. Sometimes using a larger value for the stride parameter improves the performance by skipping
the computation of similarity between so many windows.window_selection_metric: the metric used for the selection of the most similarts1time-series window per eachts2stime-series file is selectable.dtwis the default selected metric, however, any of themetricsare also available for this purpose. See thetoolkit configuration section.ts2_names: name of each time series of thets2sset of time series.header_names: name of the features.Extending the toolkitAdditionally, users may implement their own metric or figure classes and include them by using theMetricFactoryorPlotFactoryregister methods. To ensure compatibility with our toolkit, they have to inherit from the base classesMetricandPlot.The following code snippet is an example of how to introduce the Euclidean distance metric:#eu.pyimportnumpyasnpfromsimilarity_ts.metrics.metricimportMetricclassEuclideanDistance(Metric):def__init__(self):super().__init__()self.name='ed'defcompute(self,ts1,ts2,similarity_ts):metric_result={'Multivariate':self.__ed(ts1,ts2)}returnmetric_resultdefcompute_distance(self,ts1,ts2):returnself.__ed(ts1,ts2)def__ed(self,ts1,ts2):returnnp.linalg.norm(ts1-ts2)Afterward, this metric can be registered by using theregister_metric(metric_class)method fromMetricFactoryas shown in the following code snippet:importnumpyasnpfromsimilarity_ts.similarity_tsimportSimilarityTsfromsimilarity_ts.metrics.metric_factoryimportMetricFactoryfromedimportEuclideanDistanceMetricFactory.get_instance().register_metric(EuclideanDistance)ts1=np.random.rand(200,2)ts2s=np.random.rand(5,100,2)similarity_ts=SimilarityTs(ts1,ts2s)forts2_name,metric_name,computed_metricinsimilarity_ts.get_metric_computer():print(f'{ts2_name}.{metric_name}:{computed_metric}')Similarly, new plots can be introduced. For instance aSimilarityPlotByCorrelationcould be defined as:#cc_plot.pyimportnumpyasnpimportmatplotlib.pyplotaspltfromsimilarity_ts.plots.plotimportPlotclassSimilarityPlotByCorrelation(Plot):def__init__(self,fig_size=(8,6)):super().__init__(fig_size)self.name='cc-plot'defcompute(self,similarity_ts,ts2_filename):super().compute(similarity_ts,ts2_filename)n_features=self.ts1.shape[1]similarity=np.corrcoef(self.ts1.T,self.ts2.T)fig,ax=plt.subplots()im=ax.imshow(similarity,cmap='RdYlBu',vmin=-1,vmax=1)ax.set_xticks(np.arange(n_features*2))ax.set_yticks(np.arange(n_features*2))xticklabels=[f'ts1_{nfeatures_index}'fornfeatures_indexinrange(1,n_features+1)]xticklabels=xticklabels+[f'ts2_{nfeatures_index}'fornfeatures_indexinrange(1,n_features+1)]ax.set_xticklabels(xticklabels)ax.set_yticklabels(xticklabels)ax.set_xlabel('Feature')ax.set_ylabel('Feature')foriinrange(n_features*2):forjinrange(n_features*2):ax.text(j,i,f'{similarity[i,j]:.2f}',ha='center',va='center',color='black')cbar=ax.figure.colorbar(im,ax=ax)cbar.ax.set_ylabel('Similarity',rotation=-90,va='bottom')plt.title('similarity-correlation')plt.tight_layout()return[(fig,ax)]Afterward, this plot can be registered by using theregister_plot(plot_class)method fromPlotFactoryas shown in the following code snippet that register the new metric and the new plot:importosimportnumpyasnpfromsimilarity_ts.plots.plot_factoryimportPlotFactoryfromsimilarity_ts.similarity_tsimportSimilarityTsfromsimilarity_ts.metrics.metric_factoryimportMetricFactoryfromedimportEuclideanDistancefromcc_plotimportSimilarityPlotByCorrelationdefmain():MetricFactory.get_instance().register_metric(EuclideanDistance)PlotFactory.get_instance().register_plot(SimilarityPlotByCorrelation)ts1=np.random.rand(200,2)ts2s=np.random.rand(5,100,2)similarity_ts=SimilarityTs(ts1,ts2s)forts2_name,metric_name,computed_metricinsimilarity_ts.get_metric_computer():print(f'{ts2_name}.{metric_name}:{computed_metric}')forts2_name,plot_name,generated_plotsinsimilarity_ts.get_plot_computer():__save_figures(ts2_name,plot_name,generated_plots)def__save_figures(filename,plot_name,generated_plots):forplotingenerated_plots:dir_path=__create_directory(filename,f'figures',plot_name)plot[0].savefig(f'{dir_path}{plot[0].axes[0].get_title()}.pdf',format='pdf',bbox_inches='tight')def__create_directory(filename,path,plot_name):ifplot_nameinPlotFactory.get_instance().figures_requires_all_samples:dir_path=f'{path}/{plot_name}/'else:original_filename=os.path.splitext(filename)[0]dir_path=f'{path}/{original_filename}/{plot_name}/'os.makedirs(dir_path,exist_ok=True)returndir_pathif__name__=='__main__':main()LicenseSimilarityTS toolkit is free and open-source software licensed under theMIT license.AcknowledgementsProject PID2021-122208OB-I00, PROYEXCEL_00286 and  TED2021-132695B-I00 project, funded by MCIN / AEI / 10.13039 / 501100011033, by Andalusian Regional Government, and by the European Union - NextGenerationEU.