Skip to content

Commit 183892e

Browse files
committed
Minor update.
1 parent 34cf20e commit 183892e

File tree

11 files changed

+381
-329
lines changed

11 files changed

+381
-329
lines changed

core/model.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ def with_preprocessing(self, strategy):
2929
class TimeseriesPreprocessing:
3030
"""Processes timeseries."""
3131
def __init__(self):
32-
pass
32+
self.ts = None
3333

3434
def process(self, ts):
35-
pass
35+
self.ts = ts
36+
return TimeseriesView([ts])
3637

3738

3839
class TimeseriesPreprocessingSegmentation(TimeseriesPreprocessing):
@@ -48,6 +49,7 @@ class TimeseriesPreprocessingSegmentation(TimeseriesPreprocessing):
4849
def __init__(self, segment_start, segment_end):
4950
self.seg_st = segment_start
5051
self.seg_end = segment_end
52+
self.ts = None
5153

5254
def process(self, ts):
5355
self.ts = ts[self.seg_st:self.seg_end]
@@ -90,7 +92,7 @@ def __init__(self):
9092
self.segments = None
9193
self.strategy = []
9294

93-
def add_strategy(self, strat):
95+
def add(self, strat):
9496
self.strategy.append(strat)
9597
return self
9698

@@ -238,7 +240,7 @@ def _hash(self):
238240
str_to_hash = str(self.graph.nodes()) + str(self.graph.edges())
239241
return hashlib.md5(str_to_hash.encode()).hexdigest()
240242

241-
def combine_identical_nodes_slid_win(self):
243+
def combine_identical_subgraphs(self):
242244
"""Combines nodes that have same value of attribute self.attribute if graph is classical graph and
243245
nodes that are identical graphs if graph is created using sliding window mechanism."""
244246
self.orig_graph = self.graph.copy()
@@ -254,11 +256,11 @@ def combine_identical_nodes_slid_win(self):
254256
continue
255257

256258
if(set(list(node_1.edges)) == set(list(node_2.edges))):
257-
self.graph = self._combine_nodes_win(self.graph, node_1, node_2, self.attribute)
259+
self.graph = self._combine_subgraphs(self.graph, node_1, node_2, self.attribute)
258260

259261
return self
260262

261-
def _combine_nodes_win(self, graph, node_1, node_2, att):
263+
def _combine_subgraphs(self, graph, node_1, node_2, att):
262264
"""Combines nodes node_1 and node_2, that are graphs."""
263265
for i in range(len(list(node_1.nodes(data=True)))):
264266
for j in range(len(list(node_2.nodes(data=True))[i][1][att])):
@@ -446,7 +448,7 @@ def to_sequence(self, graph):
446448
self.node_strategy.set_arguments(self.graph, self.nodes, dictionaries, self.att)
447449

448450

449-
i = 0
451+
ts_len = 0
450452
while len(self.sequences[0]) < self.timeseries_len:
451453
for j in range(len(self.sequences)):
452454

@@ -463,12 +465,12 @@ def to_sequence(self, graph):
463465
for j in range(self.skip_values + 1):
464466
for k in range(len(current_nodes)):
465467

466-
current_nodes[k] = self.node_strategy.next_node(i, k, current_nodes, self.switch_graphs, current_nodes[0])
468+
current_nodes[k] = self.node_strategy.next_node(ts_len, k, current_nodes, self.switch_graphs, current_nodes[0])
467469

468470
if(current_nodes[k] == None):
469471
return self
470472

471-
i += 1
473+
ts_len += 1
472474
return self.sequences
473475

474476
class ToSequenceVisitor(ToSequenceVisitorMaster):
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
## **Csv and xml files**:
22

3-
::: input_output.input
3+
::: tsg_io.input

docs/index.md

Lines changed: 105 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,28 @@
11
# ts2g<sup>2</sup>
22

3-
TS2G<sup>2</sup> stands for "timeseries to graphs and back". The library implements a variety of strategies to convert timeseries into graphs, and convert graphs into sequences.
3+
TS2G<sup>2</sup> stands for "timeseries to graphs and back". The library implements a variety of strategies to convert timeseries into graphs, and convert graphs into sequences. Below, we provide a code snippet to generate a graph from timeseries:
4+
5+
# load time series from a file
6+
timegraph = model.Timeseries(CsvStock(some_file_path, "ColumnOfInterest").from_csv())\
47

5-
stream = TimeseriesArrayStream([2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3])
6-
timeseries = Timeseries(stream)
7-
g = timeseries.to_graph(NaturalVisibilityGraphStrategy())
8-
sequence = g.to_sequence(RandomWalkSequenceGenerationStrategy(), sequence_length=500)
8+
# and preprocess the timeseries with multiple preprocessing strategies
9+
.with_preprocessing(model.TimeseriesPreprocessingComposite()\
10+
.add_strategy(model.TimeseriesPreprocessingSegmentation(60, 120))\
11+
.add_strategy(model.TimeseriesPreprocessingSlidingWindow(5)))\
912

10-
For a more detailed example, look at the [Amazon stocks demo](https://github.com/graph-massivizer/ts2g2/blob/main/tutorials/demo-amazon-stocks.ipynb).
13+
# then create a graph from the timeseries, following a particular strategy
14+
.to_graph(tgs.BuildTimeseriesToGraphNaturalVisibilityStrategy().get_strategy())\
15+
16+
# link graphs that result from the same timeseries, but at different sliding window frames
17+
.link(mgl.LinkGraphs().sliding_window())\
18+
19+
# and combine identical graphs that result from the abovementioned time windows into single nodes
20+
.combine_identical_nodes_slid_win()\
21+
22+
# finally, draw the graph
23+
.draw("red")
24+
25+
For a more detailed example, look at the [Amazon stocks demo](https://github.com/graph-massivizer/ts2g2/blob/main/tutorials/demo-ts2g2.ipynb).
1126

1227
Many of the methods implemented in this library are described in _Silva, Vanessa Freitas, et al. "Time series analysis via network science: Concepts and algorithms." Wiley Interdisciplinary Reviews: Data Mining and Knowledge Discovery 11.3 (2021): e1404._ Nevertheless, the library also includes additional techniques found in other works from the scientific literature.
1328

@@ -41,72 +56,52 @@ The package is a joint effort between the [Jožef Stefan Institute](https://www.
4156
<tr>
4257
<td class="tg-7btt">1</td>
4358
<td class="tg-0pky">Natural Visibility Graph</td>
44-
<td class="tg-0pky">
45-
X
46-
</td>
47-
<td class="tg-0pky">
48-
<!-- directed -->
49-
X
50-
</td>
51-
<td class="tg-0pky">
52-
<!-- weighted -->
53-
X
54-
</td>
55-
<td class="tg-0pky">
56-
<!-- constraints:references: penetration -->
57-
X
58-
</td>
59-
<td class="tg-0pky">
60-
<!-- constraints:references: angle -->
61-
X
62-
</td>
59+
<td class="tg-0pky">X</td>
60+
<td class="tg-0pky">X</td>
61+
<td class="tg-0pky">X</td>
62+
<td class="tg-0pky">X</td>
63+
<td class="tg-0pky">X</td>
6364
</tr>
6465
<tr>
6566
<td class="tg-7btt">2</td>
6667
<td class="tg-0pky">Horizontal Visibility Graph</td>
67-
<td class="tg-0pky">
68-
X
69-
</td>
70-
<td class="tg-0pky">
71-
<!-- directed -->
72-
X
73-
</td>
74-
<td class="tg-0pky">
75-
<!-- weighted -->
76-
X
77-
</td>
78-
<td class="tg-0pky">
79-
<!-- constraints:references: penetration -->
80-
X
81-
</td>
82-
<td class="tg-0pky">
83-
<!-- constraints:references: angle -->
84-
X
85-
</td>
68+
<td class="tg-0pky">X</td>
69+
<td class="tg-0pky">X</td>
70+
<td class="tg-0pky">X</td>
71+
<td class="tg-0pky">X</td>
72+
<td class="tg-0pky">X</td>
8673
</tr>
8774
<tr>
8875
<td class="tg-7btt">3</td>
8976
<td class="tg-0pky">Difference Visibility Graph</td>
90-
<td class="tg-0pky">
91-
<!-- undirected -->
92-
</td>
93-
<td class="tg-0pky">
94-
<!-- directed -->
95-
</td>
96-
<td class="tg-0pky">
97-
<!-- weighted -->
98-
</td>
99-
<td class="tg-0pky">
100-
<!-- constraints:references: penetration -->
101-
</td>
102-
<td class="tg-0pky">
103-
<!-- constraints:references: angle -->
104-
</td>
77+
<td class="tg-0pky"></td>
78+
<td class="tg-0pky"></td>
79+
<td class="tg-0pky"></td>
80+
<td class="tg-0pky"></td>
81+
<td class="tg-0pky"></td>
82+
</tr>
83+
<tr>
84+
<td class="tg-7btt">4</td>
85+
<td class="tg-0pky">Quantile Graph</td>
86+
<td class="tg-0pky"></td>
87+
<td class="tg-0pky">X</td>
88+
<td class="tg-0pky">X</td>
89+
<td class="tg-0pky"></td>
90+
<td class="tg-0pky"></td>
91+
</tr>
92+
93+
<tr>
94+
<td class="tg-7btt">5</td>
95+
<td class="tg-0pky">Ordinal Partition Graph</td>
96+
<td class="tg-0pky"></td>
97+
<td class="tg-0pky">X</td>
98+
<td class="tg-0pky">X</td>
99+
<td class="tg-0pky"></td>
100+
<td class="tg-0pky"></td>
105101
</tr>
106102
</tbody>
107103
</table>
108104

109-
110105
#### References table
111106

112107
<table class="tg">
@@ -193,22 +188,65 @@ The package is a joint effort between the [Jožef Stefan Institute](https://www.
193188
<!-- constraints:references: angle -->
194189
</td>
195190
</tr>
191+
<tr>
192+
<td class="tg-7btt">4</td>
193+
<td class="tg-0pky">Quantile Graph</td>
194+
<td class="tg-0pky">
195+
</a>
196+
</td>
197+
<td class="tg-0pky">
198+
<!-- directed -->
199+
<a href="https://www.researchgate.net/figure/Illustrative-example-of-the-quantile-graph-algorithm-for-Q-4-On-the-left-panel-we_fig8_349721222">ref</a>
200+
</td>
201+
<td class="tg-0pky">
202+
<!-- weighted -->
203+
</td>
204+
<td class="tg-0pky">
205+
<!-- constraints:references: penetration -->
206+
</a>
207+
</td>
208+
<td class="tg-0pky">
209+
<!-- constraints:references: angle -->
210+
</a>
211+
</td>
212+
</tr><tr>
213+
<td class="tg-7btt">5</td>
214+
<td class="tg-0pky">Ordinal Partition Graph</td>
215+
<td class="tg-0pky">
216+
</a>
217+
</td>
218+
<td class="tg-0pky">
219+
<!-- directed -->
220+
</a>
221+
</td>
222+
<td class="tg-0pky">
223+
<!-- weighted -->
224+
</td>
225+
<td class="tg-0pky">
226+
<!-- constraints:references: penetration -->
227+
</a>
228+
</td>
229+
<td class="tg-0pky">
230+
<!-- constraints:references: angle -->
231+
</a>
232+
</td>
233+
</tr>
196234
</tbody>
197235
</table>
198236

199237

200238

201239
### Graphs to timeseries conversion
202240

203-
Graphs are converted back to timeseries by sampling node values from the graph following different strategies. The following strategies have been implemented so far:
241+
Graphs are converted back to timeseries by sampling node values from the graph following different strategies. Below, we provide a short snippet of code, to illustrate how this can be done.
204242

205-
- random node
206-
- random node neighbour
207-
- random node degree
208-
- random walk
209-
- random walk with restart
210-
- random walk with jump
243+
timegraph.to_sequence(model.ToSequenceVisitorSlidingWindow()\
244+
.next_node_strategy(tts.StrategySelectNextNodeRandomlyFromFirstGraph())\
245+
.next_value_strategy(tts.StrategyNextValueInNodeRandomForSlidingWindow().skip_every_x_steps(1))\
246+
.ts_length(50))\
247+
.draw_sequence()
211248

249+
When choosing the next node, the following strategies have been implemented so far: random node, random node neighbour, random node degree, random walk, random walk with restart, random walk with jump.
212250

213251
## Publications
214252

docs/tutorial.ipynb

Lines changed: 68 additions & 88 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)