SankeyExcelParser 1.0.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|