SankeyExcelParser 1.0.0b0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- SankeyExcelParser/__init__.py +0 -0
- SankeyExcelParser/io_excel.py +1867 -0
- SankeyExcelParser/io_excel_constants.py +811 -0
- SankeyExcelParser/sankey.py +3138 -0
- SankeyExcelParser/sankey_utils/__init__.py +0 -0
- SankeyExcelParser/sankey_utils/data.py +1118 -0
- SankeyExcelParser/sankey_utils/excel_source.py +31 -0
- SankeyExcelParser/sankey_utils/flux.py +344 -0
- SankeyExcelParser/sankey_utils/functions.py +278 -0
- SankeyExcelParser/sankey_utils/node.py +340 -0
- SankeyExcelParser/sankey_utils/protos/__init__.py +0 -0
- SankeyExcelParser/sankey_utils/protos/flux.py +84 -0
- SankeyExcelParser/sankey_utils/protos/node.py +386 -0
- SankeyExcelParser/sankey_utils/protos/sankey_object.py +135 -0
- SankeyExcelParser/sankey_utils/protos/tag_group.py +95 -0
- SankeyExcelParser/sankey_utils/sankey_object.py +165 -0
- SankeyExcelParser/sankey_utils/table_object.py +37 -0
- SankeyExcelParser/sankey_utils/tag.py +95 -0
- SankeyExcelParser/sankey_utils/tag_group.py +206 -0
- SankeyExcelParser/su_trace.py +239 -0
- SankeyExcelParser/tests/integration/__init__.py +0 -0
- SankeyExcelParser/tests/integration/test_base.py +356 -0
- SankeyExcelParser/tests/integration/test_run_check_input.py +100 -0
- SankeyExcelParser/tests/integration/test_run_conversions.py +96 -0
- SankeyExcelParser/tests/integration/test_run_load_input.py +94 -0
- SankeyExcelParser/tests/unit/__init__.py +0 -0
- SankeyExcelParser-1.0.0b0.data/scripts/run_parse_and_write_excel.py +155 -0
- SankeyExcelParser-1.0.0b0.data/scripts/run_parse_excel.py +115 -0
- SankeyExcelParser-1.0.0b0.dist-info/METADATA +113 -0
- SankeyExcelParser-1.0.0b0.dist-info/RECORD +32 -0
- SankeyExcelParser-1.0.0b0.dist-info/WHEEL +5 -0
- SankeyExcelParser-1.0.0b0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,340 @@
|
|
1
|
+
"""
|
2
|
+
Author : Vincent LE DOZE
|
3
|
+
Date : 31/05/23
|
4
|
+
|
5
|
+
This file contains descriptions for Node class
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
# Local modules -----------------------------------------------------
|
10
|
+
from SankeyExcelParser.sankey_utils.protos.flux import _ProtoFlux
|
11
|
+
from SankeyExcelParser.sankey_utils.protos.node import _ProtoNode
|
12
|
+
|
13
|
+
|
14
|
+
# CLASS ----------------------------------------------------------------------------
|
15
|
+
class Node(_ProtoNode):
|
16
|
+
"""
|
17
|
+
Define a node object.
|
18
|
+
Inherits from `_ProtoNode`, but add methods to deal with other Nodes.
|
19
|
+
"""
|
20
|
+
|
21
|
+
def __init__(
|
22
|
+
self,
|
23
|
+
name: str,
|
24
|
+
level: int,
|
25
|
+
**kwargs
|
26
|
+
):
|
27
|
+
# Init super
|
28
|
+
_ProtoNode.__init__(self, name, level)
|
29
|
+
# Add constructor values
|
30
|
+
self.update(**kwargs)
|
31
|
+
|
32
|
+
def update(
|
33
|
+
self,
|
34
|
+
**kwargs
|
35
|
+
):
|
36
|
+
for key, value in kwargs.items():
|
37
|
+
setattr(self, key, value)
|
38
|
+
|
39
|
+
@property
|
40
|
+
def children_ids(self):
|
41
|
+
if not self.has_at_least_one_child():
|
42
|
+
return [[]]
|
43
|
+
return [[_.id for _ in grp] for grp in self._children_grps if len(grp) > 0]
|
44
|
+
|
45
|
+
@property
|
46
|
+
def parents_ids(self):
|
47
|
+
return [_.id for _ in self._parents]
|
48
|
+
|
49
|
+
def add_child(self, node: _ProtoNode, childrengrp_id: int = -1):
|
50
|
+
"""
|
51
|
+
Add child to a children list.
|
52
|
+
|
53
|
+
Parameters
|
54
|
+
----------
|
55
|
+
:param node: Child node to add.
|
56
|
+
:type node: _ProtoNode
|
57
|
+
|
58
|
+
:param childrengrp_id: Children group in which we should add child to.
|
59
|
+
:type childrengrp_id: int, optionnal (default=-1)
|
60
|
+
"""
|
61
|
+
# Verify that we don't already have that child
|
62
|
+
# Add new groupe
|
63
|
+
if self._create_new_children_grp:
|
64
|
+
self._children_grps.append([])
|
65
|
+
self._create_new_children_grp = False
|
66
|
+
# Secure childgroup index
|
67
|
+
if childrengrp_id > 0:
|
68
|
+
while childrengrp_id >= len(self._children_grps):
|
69
|
+
self._children_grps.append([])
|
70
|
+
# Protection
|
71
|
+
if node not in self._children_grps[childrengrp_id]:
|
72
|
+
# Add child
|
73
|
+
self._children_grps[childrengrp_id].append(node)
|
74
|
+
# Add self to child's parent
|
75
|
+
node._add_parent(self)
|
76
|
+
|
77
|
+
def create_new_children_group(self):
|
78
|
+
self._create_new_children_grp = True
|
79
|
+
|
80
|
+
def has_at_least_one_child(self):
|
81
|
+
for _ in self._children_grps:
|
82
|
+
if len(_) > 0:
|
83
|
+
return True
|
84
|
+
return False
|
85
|
+
|
86
|
+
def is_child_of_given_node(self, node: _ProtoNode):
|
87
|
+
return (self in node.parents)
|
88
|
+
|
89
|
+
def get_set_of_all_base_children(self):
|
90
|
+
if self.has_at_least_one_child():
|
91
|
+
children_set = set()
|
92
|
+
for children_grp in self._children_grps:
|
93
|
+
for child in children_grp:
|
94
|
+
children_set |= child.get_set_of_all_base_children()
|
95
|
+
return children_set
|
96
|
+
return set([self])
|
97
|
+
|
98
|
+
def autocompute_level_and_children_levels(self, min_level=1):
|
99
|
+
"""
|
100
|
+
Autocompute level based on parenthood leveling.
|
101
|
+
Returns max level that has been reached from children.
|
102
|
+
"""
|
103
|
+
# Update own level
|
104
|
+
self._level = max(self._level, min_level)
|
105
|
+
# Init max level value
|
106
|
+
max_level = self._level
|
107
|
+
# Update sub-levels
|
108
|
+
for children_grp in self._children_grps:
|
109
|
+
# Secure: Start from a common min level for given children grp
|
110
|
+
min_children_level = min_level + 1
|
111
|
+
for child in children_grp:
|
112
|
+
min_children_level = max(child.level, min_children_level)
|
113
|
+
# Propagate level computing
|
114
|
+
for child in children_grp:
|
115
|
+
max_children_level = \
|
116
|
+
child.autocompute_level_and_children_levels(min_level=min_children_level)
|
117
|
+
max_level = max(max_children_level, max_level)
|
118
|
+
# Return max level
|
119
|
+
return max_level
|
120
|
+
|
121
|
+
def _add_parent(self, node: _ProtoNode):
|
122
|
+
"""
|
123
|
+
Add parent.
|
124
|
+
|
125
|
+
Parameters
|
126
|
+
----------
|
127
|
+
:param node: Parent node to add.
|
128
|
+
:type node: _ProtoNode
|
129
|
+
"""
|
130
|
+
if node not in self._parents:
|
131
|
+
self._parents.append(node)
|
132
|
+
|
133
|
+
def has_parents(self):
|
134
|
+
return len(self._parents) > 0
|
135
|
+
|
136
|
+
def is_parent_of_given_node(self, node: _ProtoNode):
|
137
|
+
return node.is_child_of_given_node(self)
|
138
|
+
|
139
|
+
def add_input_flux(self, flux: _ProtoFlux):
|
140
|
+
self._input_flux.append(flux)
|
141
|
+
|
142
|
+
def add_output_flux(self, flux: _ProtoFlux):
|
143
|
+
self._output_flux.append(flux)
|
144
|
+
|
145
|
+
def get_flux_from_given_node(self, node: _ProtoNode):
|
146
|
+
"""
|
147
|
+
Return the flux node->self
|
148
|
+
|
149
|
+
Parameters
|
150
|
+
----------
|
151
|
+
:param node: Node where flux must arrive from
|
152
|
+
:type node: _ProtoNode
|
153
|
+
|
154
|
+
Returns
|
155
|
+
-------
|
156
|
+
:return: Flux that as been ask if found, otherwise None
|
157
|
+
:rtype: _ProtoFlux | None
|
158
|
+
"""
|
159
|
+
for flux in self._input_flux:
|
160
|
+
if flux.orig == node:
|
161
|
+
return flux
|
162
|
+
return None
|
163
|
+
|
164
|
+
def get_flux_to_given_node(self, node: _ProtoNode):
|
165
|
+
"""
|
166
|
+
Return the flux self->node
|
167
|
+
|
168
|
+
Parameters
|
169
|
+
----------
|
170
|
+
:param node: Node where flux must go to
|
171
|
+
:type node: _ProtoNode
|
172
|
+
|
173
|
+
Returns
|
174
|
+
-------
|
175
|
+
:return: Flux that as been ask if found, otherwise None
|
176
|
+
:rtype: _ProtoFlux | None
|
177
|
+
"""
|
178
|
+
for flux in self._output_flux:
|
179
|
+
if flux.dest == node:
|
180
|
+
return flux
|
181
|
+
return None
|
182
|
+
|
183
|
+
def update_table(
|
184
|
+
self,
|
185
|
+
level: int,
|
186
|
+
taggs_names: list,
|
187
|
+
extra_infos_names: list,
|
188
|
+
lineages_processed: list,
|
189
|
+
lineages_tables: list,
|
190
|
+
current_lineage_table: list,
|
191
|
+
lineages_entries,
|
192
|
+
current_lineage_entries,
|
193
|
+
lineages_entries__levels,
|
194
|
+
current_lineage_entries__levels
|
195
|
+
):
|
196
|
+
"""
|
197
|
+
Update a panda table with this node infos.
|
198
|
+
The columns are organized as :
|
199
|
+
|
200
|
+
1. Level
|
201
|
+
2. Name
|
202
|
+
3. Mat balance
|
203
|
+
4. Color
|
204
|
+
5. All node tags (multiple columns) : for each column we have the respective tags or None
|
205
|
+
6. Definition
|
206
|
+
14. All remaining extra infos (if present, multiple columns)
|
207
|
+
|
208
|
+
Parameters
|
209
|
+
----------
|
210
|
+
:param level: Level that will be indicated on table for the node.
|
211
|
+
Can be different form actual level because of multiplicity of parents
|
212
|
+
:type level: int
|
213
|
+
|
214
|
+
:param taggs_names: List of tag groups for node tags columns
|
215
|
+
:type taggs_names: list[str] | list[TagGroup]
|
216
|
+
|
217
|
+
:param extra_infos_names: List of extra infos to search for extra infos columns
|
218
|
+
:type extra_infos_names: list[str]
|
219
|
+
|
220
|
+
:param lineages_processed: List of children grp that have already been added to table
|
221
|
+
:type lineages_processed: list[list[Node]] (modified)
|
222
|
+
|
223
|
+
:param lineages_tables: List of all tables (2-D list) of all possible lineages of nodes
|
224
|
+
:type lineages_tables: list[list[list[str]]] (modified)
|
225
|
+
|
226
|
+
:param current_lineage_table: Table (2-D list) containing infos of all current lineage related nodes
|
227
|
+
:type current_lineage_table: list[list[str]] (modified)
|
228
|
+
|
229
|
+
:param lineages_entries:
|
230
|
+
List of all lists of nodes that have been added to lineages_tables.
|
231
|
+
Used to colorize table.
|
232
|
+
:type lineages_entries: list[list[Node]] (modified)
|
233
|
+
|
234
|
+
:param current_lineage_entries:
|
235
|
+
List of nodes that have been added to current_lineage_table.
|
236
|
+
Used to colorize table.
|
237
|
+
:type current_lineage_entries: list[Node] (modified)
|
238
|
+
|
239
|
+
:param lineages_entries__level:
|
240
|
+
List of all lists of nodes' levels that have been added to lineages_tables.
|
241
|
+
Used to colorize table.
|
242
|
+
:type lineages_entries: list[list[int]] (modified)
|
243
|
+
|
244
|
+
:param current_lineage_entries__level:
|
245
|
+
List of nodes' levels that have been added to current_lineage_table.
|
246
|
+
Used to colorize table.
|
247
|
+
:type current_lineage_entries: list[int] (modified)
|
248
|
+
"""
|
249
|
+
# Create table line with corresponding data for self
|
250
|
+
line_node = [
|
251
|
+
level,
|
252
|
+
self.name,
|
253
|
+
self.mat_balance,
|
254
|
+
self.color]
|
255
|
+
# Add tags
|
256
|
+
line_node += self.get_tags_from_taggroups(
|
257
|
+
taggs_names, return_names_instead_of_refs=True)
|
258
|
+
# Add definition
|
259
|
+
line_node.append(self.definition)
|
260
|
+
# Add extra info cols if needed
|
261
|
+
for extra_info_name in extra_infos_names:
|
262
|
+
if extra_info_name in self.extra_infos.keys():
|
263
|
+
line_node.append(self.extra_infos[extra_info_name])
|
264
|
+
else:
|
265
|
+
line_node.append(None)
|
266
|
+
# Add line to the table
|
267
|
+
current_lineage_table.append(line_node)
|
268
|
+
current_lineage_entries.append(self)
|
269
|
+
current_lineage_entries__levels.append(level)
|
270
|
+
# If we have children for this node, we add them directly under
|
271
|
+
if self.has_at_least_one_child():
|
272
|
+
main_lineages_processed = False
|
273
|
+
# I do not pass by decorator here, because I need the pointer to childgroup for lineages_processed
|
274
|
+
for childgroup in self._children_grps:
|
275
|
+
# Pass already processed lineage
|
276
|
+
if childgroup in lineages_processed:
|
277
|
+
continue
|
278
|
+
# Recursively process children for main lineage (first children grp)
|
279
|
+
if not main_lineages_processed:
|
280
|
+
for child in childgroup:
|
281
|
+
child.update_table(
|
282
|
+
level+1,
|
283
|
+
taggs_names,
|
284
|
+
extra_infos_names,
|
285
|
+
lineages_processed,
|
286
|
+
lineages_tables,
|
287
|
+
current_lineage_table,
|
288
|
+
lineages_entries,
|
289
|
+
current_lineage_entries,
|
290
|
+
lineages_entries__levels,
|
291
|
+
current_lineage_entries__levels)
|
292
|
+
main_lineages_processed = True
|
293
|
+
else:
|
294
|
+
if len(childgroup) > 0: # Protection
|
295
|
+
# Start a new lineage (from level = 1)
|
296
|
+
new_line_node = line_node.copy()
|
297
|
+
new_line_node[0] = 1
|
298
|
+
new_lineage_table = [new_line_node]
|
299
|
+
lineages_tables.append(new_lineage_table)
|
300
|
+
# Update list of level / nodes for table colorization
|
301
|
+
new_lineage_entries = [self]
|
302
|
+
new_lineage_entries__levels = [1]
|
303
|
+
lineages_entries.append(new_lineage_entries)
|
304
|
+
lineages_entries__levels.append(new_lineage_entries__levels)
|
305
|
+
# Recursively process children for new lineage
|
306
|
+
for child in childgroup:
|
307
|
+
child.update_table(
|
308
|
+
2,
|
309
|
+
taggs_names,
|
310
|
+
extra_infos_names,
|
311
|
+
lineages_processed,
|
312
|
+
lineages_tables,
|
313
|
+
new_lineage_table,
|
314
|
+
lineages_entries,
|
315
|
+
new_lineage_entries,
|
316
|
+
lineages_entries__levels,
|
317
|
+
new_lineage_entries__levels)
|
318
|
+
lineages_processed.append(childgroup)
|
319
|
+
|
320
|
+
def get_as_dict(self):
|
321
|
+
# Init output
|
322
|
+
output = {}
|
323
|
+
# Get values
|
324
|
+
output['name'] = self.name
|
325
|
+
output['tags'] = [
|
326
|
+
[_.group.name, _.name] for _ in self.tags]
|
327
|
+
output['parents'] = [_.name for _ in self.parents]
|
328
|
+
output['childrens'] = \
|
329
|
+
[[_.name for _ in grp]
|
330
|
+
for grp in self.children_grps]
|
331
|
+
output['mat_balance'] = self.mat_balance
|
332
|
+
output['color'] = self.color
|
333
|
+
output['definition'] = self.definition
|
334
|
+
return output
|
335
|
+
|
336
|
+
def __repr__(self):
|
337
|
+
s = '{}'.format(self._name)
|
338
|
+
for tag in self._tags:
|
339
|
+
s += ' | {}'.format(tag)
|
340
|
+
return s
|
File without changes
|
@@ -0,0 +1,84 @@
|
|
1
|
+
"""
|
2
|
+
Author : Vincent LE DOZE
|
3
|
+
Date : 31/05/23
|
4
|
+
|
5
|
+
This file contains descriptions for proto Flux class
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
# Local modules -----------------------------------------------------
|
10
|
+
from SankeyExcelParser.sankey_utils.sankey_object import SankeyObject
|
11
|
+
from SankeyExcelParser.sankey_utils.protos.node import _ProtoNode
|
12
|
+
|
13
|
+
|
14
|
+
# CLASS ----------------------------------------------------------------------------
|
15
|
+
class _ProtoFlux(SankeyObject):
|
16
|
+
"""
|
17
|
+
Define a prototype for flux object.
|
18
|
+
Does nothing except defining attributes.
|
19
|
+
Inherits from `SankeyObject`
|
20
|
+
|
21
|
+
Parameters
|
22
|
+
----------
|
23
|
+
:param id: Flux id (standardized))
|
24
|
+
:type id: str
|
25
|
+
|
26
|
+
:param orig: Flux starting node
|
27
|
+
:type orig: _ProtoNode
|
28
|
+
|
29
|
+
:param dest: Flux ending node
|
30
|
+
:type dest: _ProtoNode
|
31
|
+
|
32
|
+
:param datas: All datas for the flux
|
33
|
+
:type datas: list [Data, ...]
|
34
|
+
|
35
|
+
:param results: All datas (as results) for the flux
|
36
|
+
:type results: list [Data, ...]
|
37
|
+
"""
|
38
|
+
|
39
|
+
def __init__(
|
40
|
+
self,
|
41
|
+
orig: _ProtoNode,
|
42
|
+
dest: _ProtoNode,
|
43
|
+
**kwargs
|
44
|
+
):
|
45
|
+
# Init super constructor
|
46
|
+
SankeyObject.__init__(self)
|
47
|
+
# Create attributs
|
48
|
+
self._id = orig.id+'---'+dest.id
|
49
|
+
self._orig = orig
|
50
|
+
self._dest = dest
|
51
|
+
|
52
|
+
@property
|
53
|
+
def id(self):
|
54
|
+
return self._id
|
55
|
+
|
56
|
+
@property
|
57
|
+
def orig(self):
|
58
|
+
return self._orig
|
59
|
+
|
60
|
+
@property
|
61
|
+
def dest(self):
|
62
|
+
return self._dest
|
63
|
+
|
64
|
+
@property
|
65
|
+
def natural_unit(self):
|
66
|
+
return self._orig.get_natural_unit()
|
67
|
+
|
68
|
+
@natural_unit.setter
|
69
|
+
def natural_unit(self, _):
|
70
|
+
# Unit apply only to origin
|
71
|
+
self._orig._add_natural_unit(_)
|
72
|
+
|
73
|
+
@property
|
74
|
+
def factor(self):
|
75
|
+
return self._orig.get_factor()
|
76
|
+
|
77
|
+
@factor.setter
|
78
|
+
def factor(self, _):
|
79
|
+
# Unit apply only to origin
|
80
|
+
self._orig.add_factor(_)
|
81
|
+
|
82
|
+
@property
|
83
|
+
def tooltips(self):
|
84
|
+
return self._orig.tooltips
|