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.
Files changed (32) hide show
  1. SankeyExcelParser/__init__.py +0 -0
  2. SankeyExcelParser/io_excel.py +1867 -0
  3. SankeyExcelParser/io_excel_constants.py +811 -0
  4. SankeyExcelParser/sankey.py +3138 -0
  5. SankeyExcelParser/sankey_utils/__init__.py +0 -0
  6. SankeyExcelParser/sankey_utils/data.py +1118 -0
  7. SankeyExcelParser/sankey_utils/excel_source.py +31 -0
  8. SankeyExcelParser/sankey_utils/flux.py +344 -0
  9. SankeyExcelParser/sankey_utils/functions.py +278 -0
  10. SankeyExcelParser/sankey_utils/node.py +340 -0
  11. SankeyExcelParser/sankey_utils/protos/__init__.py +0 -0
  12. SankeyExcelParser/sankey_utils/protos/flux.py +84 -0
  13. SankeyExcelParser/sankey_utils/protos/node.py +386 -0
  14. SankeyExcelParser/sankey_utils/protos/sankey_object.py +135 -0
  15. SankeyExcelParser/sankey_utils/protos/tag_group.py +95 -0
  16. SankeyExcelParser/sankey_utils/sankey_object.py +165 -0
  17. SankeyExcelParser/sankey_utils/table_object.py +37 -0
  18. SankeyExcelParser/sankey_utils/tag.py +95 -0
  19. SankeyExcelParser/sankey_utils/tag_group.py +206 -0
  20. SankeyExcelParser/su_trace.py +239 -0
  21. SankeyExcelParser/tests/integration/__init__.py +0 -0
  22. SankeyExcelParser/tests/integration/test_base.py +356 -0
  23. SankeyExcelParser/tests/integration/test_run_check_input.py +100 -0
  24. SankeyExcelParser/tests/integration/test_run_conversions.py +96 -0
  25. SankeyExcelParser/tests/integration/test_run_load_input.py +94 -0
  26. SankeyExcelParser/tests/unit/__init__.py +0 -0
  27. SankeyExcelParser-1.0.0b0.data/scripts/run_parse_and_write_excel.py +155 -0
  28. SankeyExcelParser-1.0.0b0.data/scripts/run_parse_excel.py +115 -0
  29. SankeyExcelParser-1.0.0b0.dist-info/METADATA +113 -0
  30. SankeyExcelParser-1.0.0b0.dist-info/RECORD +32 -0
  31. SankeyExcelParser-1.0.0b0.dist-info/WHEEL +5 -0
  32. SankeyExcelParser-1.0.0b0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,386 @@
1
+ """
2
+ Author : Vincent LE DOZE
3
+ Date : 31/05/23
4
+
5
+ This file contains descriptions for proto Node class
6
+
7
+ """
8
+
9
+ # External libs ---------------------------------------------------------------
10
+ import re
11
+
12
+ # Local modules -----------------------------------------------------
13
+ from SankeyExcelParser.sankey_utils.sankey_object import SankeyObject
14
+ from SankeyExcelParser.sankey_utils.functions import _stdStr, _convertColorToHex
15
+
16
+
17
+ # CLASS ----------------------------------------------------------------------------
18
+ LOCALISATION_OPTIONS = {
19
+ 'Local': ['locale?', 'domestique'],
20
+ 'Echange': ['echanges?']}
21
+
22
+
23
+ class _ProtoNodeUnit(object):
24
+ """
25
+ Define unit for a data object
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ **kwargs
31
+ ):
32
+ self._natural_unit = None
33
+ self._equivalent_unit = None
34
+ self._equivalent_to_natural = None
35
+ self._natural_to_equivalent = None
36
+ self._other_conversions = {}
37
+ self.update(**kwargs)
38
+
39
+ def update(
40
+ self,
41
+ **kwargs
42
+ ):
43
+ for key, value in kwargs.items():
44
+ setattr(self, key, value)
45
+
46
+ @property
47
+ def natural_unit(self):
48
+ return self._natural_unit
49
+
50
+ @natural_unit.setter
51
+ def natural_unit(self, _):
52
+ # None case
53
+ if _ is None:
54
+ self._natural_unit = None
55
+ return
56
+ # Real affectation
57
+ try:
58
+ self._natural_unit = str(_)
59
+ except Exception:
60
+ pass
61
+
62
+ @property
63
+ def equivalent_unit(self):
64
+ return self._equivalent_unit
65
+
66
+ @property
67
+ def equivalent_to_natural(self):
68
+ return self._equivalent_to_natural
69
+
70
+ @property
71
+ def natural_to_equivalent(self):
72
+ return self._natural_to_equivalent
73
+
74
+ @natural_to_equivalent.setter
75
+ def natural_to_equivalent(self, _):
76
+ # None case
77
+ if _ is None:
78
+ self._natural_to_equivalent = None
79
+ return
80
+ # Real affectation
81
+ try:
82
+ self._natural_to_equivalent = float(_)
83
+ # TODO: div 0 protection ? Or enough with try ?
84
+ self._equivalent_to_natural = (1.0/self._natural_to_equivalent)
85
+ except Exception:
86
+ pass
87
+
88
+ @property
89
+ def other_conversions(self):
90
+ return self._other_conversions
91
+
92
+ def add_other_conversion(self, name, value):
93
+ try:
94
+ f_value = float(value)
95
+ s_name = str(name)
96
+ # NAN protection
97
+ if (f_value != f_value):
98
+ return
99
+ self._other_conversions[s_name] = f_value
100
+ except Exception:
101
+ pass
102
+
103
+
104
+ class _ProtoNode(SankeyObject):
105
+ """
106
+ Define a prototype for node object.
107
+ Does nothing except defining attributes.
108
+ Inherits from `SankeyObject`
109
+
110
+ Parameters
111
+ ----------
112
+
113
+ :param id: Node id (standardized)
114
+ :type id: str
115
+
116
+ :param name: Node name (not standardized, as set by the user)
117
+ :type name: str
118
+
119
+ :param level: Parenthood level of the node.
120
+ 1=Node without parents,
121
+ 2+: Node with parents, ...
122
+ :type level: int
123
+
124
+ :param type: parenthood relationships
125
+ 'SR': Single root,
126
+ 'PR': parent root,
127
+ 'BC': base child,
128
+ 'PC': parent child
129
+ :type level: str
130
+
131
+ :param parents: Lists the parent nodes of the 'self' node.
132
+ :type parents: list [Node, ...]
133
+
134
+ :param children_grps: Lists the groups of child nodes of the 'self' node.
135
+ :type children_grps: list [list[Node, ...], ...]
136
+
137
+ :param input_flux: List of all flux that arrive to this node.
138
+ :type input_flux: list [Flux, ...]
139
+
140
+ :param output_flux: List of all flux that depart from this node.
141
+ :type output_flux: list [Flux, ...]
142
+
143
+ :param mat_balance: Do we respect or not of the matter balance.
144
+ 1: matter balance is respected,
145
+ 0: not respected.
146
+ :type mat_balance: int
147
+
148
+ :param color: Color applied to the node on application
149
+ :type color: str
150
+
151
+ :param definition: Node definition
152
+ :type definition: str
153
+ """
154
+
155
+ def __init__(
156
+ self,
157
+ name: str,
158
+ level: int,
159
+ **kwargs
160
+ ):
161
+ # Init super
162
+ SankeyObject.__init__(self)
163
+ # Id : keep only lower alphanumeric + spaces replaced with "_"
164
+ self._id = re.sub(r'[^a-z0-9 ]', '', _stdStr(name))\
165
+ .title().replace(' ', '')
166
+ # Init default value
167
+ self._name = name
168
+ self._level = level
169
+ # Parents & children
170
+ self._type = None
171
+ self._parents = []
172
+ self._children_grps = [[]]
173
+ self._create_new_children_grp = False
174
+ # Flux
175
+ self._input_flux = []
176
+ self._output_flux = []
177
+ # MFA
178
+ self._unit = {}
179
+ self._mat_balance = None
180
+ # Display on OpenSankey
181
+ self._color = None
182
+ self._definition = None
183
+
184
+ @property
185
+ def id(self):
186
+ return self._id
187
+
188
+ @property
189
+ def name(self):
190
+ return self._name
191
+
192
+ @property
193
+ def level(self):
194
+ return self._level
195
+
196
+ @level.setter
197
+ def level(self, _):
198
+ try:
199
+ self._level = max(1, int(_))
200
+ except Exception:
201
+ pass
202
+
203
+ @property
204
+ def type(self):
205
+ return self._type
206
+
207
+ @type.setter
208
+ def type(self, _):
209
+ if isinstance(_, str):
210
+ upper_ = _.upper()
211
+ if upper_ in ['SR', 'PR', 'BC', 'PC']:
212
+ self._type = upper_
213
+
214
+ @property
215
+ def mat_balance(self):
216
+ return self._mat_balance
217
+
218
+ @mat_balance.setter
219
+ def mat_balance(self, _):
220
+ try:
221
+ self._mat_balance = int(_)
222
+ except Exception:
223
+ pass
224
+
225
+ @property
226
+ def color(self):
227
+ return self._color
228
+
229
+ @property
230
+ def color_in_hex(self):
231
+ return _convertColorToHex(self._color, default_color='#808080') # Grey by default
232
+
233
+ @color.setter
234
+ def color(self, _):
235
+ if type(_) is str:
236
+ if len(_) > 0:
237
+ self._color = _
238
+
239
+ @property
240
+ def definition(self):
241
+ return self._definition
242
+
243
+ @definition.setter
244
+ def definition(self, _):
245
+ if type(_) is str:
246
+ self._definition = None
247
+ if len(_) > 0:
248
+ self._definition = _
249
+ return
250
+ if _ is None:
251
+ self._definition = None
252
+
253
+ @property
254
+ def parents(self):
255
+ return self._parents.copy()
256
+
257
+ def get_all_parents(self, limit=-1):
258
+ # if limit < 0, output = all existing parent, grand-parents, grand-grand-parents, etc...
259
+ if limit < 0:
260
+ if len(self._parents) == 0:
261
+ return []
262
+ else:
263
+ all_parents = self._parents.copy() # Beware modifying references
264
+ for parent in self._parents:
265
+ all_parents += parent.get_all_parents()
266
+ return all_parents
267
+ # if limit = 0, output = current node parents
268
+ # if limit = 1, output = current node parents + grand-parents
269
+ # if limit = 2, outpur = current node parents + grand-parents + grand-grand-parents
270
+ # etc...
271
+ elif limit == 0:
272
+ return self._parents
273
+ else:
274
+ all_parents = self._parents.copy()
275
+ for parent in self._parents:
276
+ all_parents += parent.get_all_parents(limit=limit-1)
277
+ return all_parents
278
+
279
+ @property
280
+ def children_grps(self):
281
+ return [_.copy() for _ in self._children_grps]
282
+
283
+ def get_brothers_grps(self):
284
+ """
285
+ Return dict of list of brothers nodes, ie nodes that share the same parent as self.
286
+ Brothers are referenced by their shared parents
287
+
288
+ Returns
289
+ -------
290
+ :return: Groups of existing brothers per parents
291
+ :rtype: list[ list[bro1, bro2, ...], ... ]
292
+ """
293
+ brothers = []
294
+ # No parents -> No brothers
295
+ if len(self.parents) == 0:
296
+ return brothers
297
+ # There are parents
298
+ for parent in self.parents:
299
+ for grp in parent.children_grps:
300
+ # Parent can have children grp where self does not belong
301
+ if self in grp:
302
+ # Remove self from brothers
303
+ grp.remove(self) # Safe : With children_grps setter, grp is a copy
304
+ brothers.append(grp)
305
+ return brothers
306
+
307
+ @property
308
+ def input_flux(self):
309
+ return self._input_flux.copy()
310
+
311
+ @property
312
+ def output_flux(self):
313
+ return self._output_flux.copy()
314
+
315
+ @property
316
+ def unit(self):
317
+ return self._unit
318
+
319
+ @property
320
+ def has_unit(self):
321
+ return len(self._unit) > 0
322
+
323
+ @property
324
+ def unit_localisation(self):
325
+ return list(self._unit.keys())
326
+
327
+ def get_natural_unit(self, localisation=None):
328
+ try:
329
+ if localisation is None:
330
+ return self._unit[self.unit_localisation[0]].natural_unit
331
+ else:
332
+ return self._unit[localisation].natural_unit
333
+ except Exception:
334
+ pass
335
+ return None
336
+
337
+ def add_natural_unit(self, _, localisation='Local'):
338
+ if localisation is not None:
339
+ if localisation in self._unit.keys():
340
+ self._unit[localisation].natural_unit = _
341
+ else:
342
+ self._unit[localisation] = _ProtoNodeUnit(natural_unit=_)
343
+
344
+ def get_factor(self, localisation=None):
345
+ try:
346
+ if localisation is None:
347
+ return self._unit[self.unit_localisation[0]].natural_to_equivalent
348
+ else:
349
+ return self._unit[localisation].natural_to_equivalent
350
+ except Exception:
351
+ pass
352
+ return None
353
+
354
+ def add_factor(self, _, localisation='Local'):
355
+ if localisation is not None:
356
+ if localisation in self._unit.keys():
357
+ self._unit[localisation].natural_to_equivalent = _
358
+ else:
359
+ self._unit[localisation] = _ProtoNodeUnit(natural_to_equivalent=_)
360
+
361
+ def get_other_factors(self, localisation=None):
362
+ try:
363
+ if localisation is None:
364
+ return self._unit[self.unit_localisation[0]].other_conversions
365
+ else:
366
+ return self._unit[localisation].other_conversions
367
+ except Exception:
368
+ pass
369
+ return None
370
+
371
+ def add_other_factor(self, name, factor, localisation='Local'):
372
+ if localisation is not None:
373
+ if localisation not in self._unit.keys():
374
+ self._unit[localisation] = _ProtoNodeUnit()
375
+ self._unit[localisation].add_other_conversion(name, factor)
376
+
377
+ def match_localisation(self, _):
378
+ try:
379
+ localisation = str(_)
380
+ for localisation_option, localisation_res in LOCALISATION_OPTIONS.items():
381
+ for localisation_re in localisation_res:
382
+ if re.fullmatch(localisation_re, _stdStr(localisation)):
383
+ return localisation_option
384
+ except Exception:
385
+ pass
386
+ return None
@@ -0,0 +1,135 @@
1
+ """
2
+ Author : Vincent LE DOZE
3
+ Date : 31/05/23
4
+
5
+ This file contains descriptions for sankey proto class
6
+
7
+ """
8
+
9
+
10
+ # Local modules -----------------------------------------------------
11
+ from SankeyExcelParser.sankey_utils.table_object import TableObject
12
+
13
+
14
+ # CLASS ----------------------------------------------------------------------------
15
+ class _ProtoToolTip(object):
16
+ """
17
+ Proto class for Tooltip
18
+
19
+ Parameters
20
+ ----------
21
+ :param name: Tooltip name
22
+ :type name: str
23
+
24
+ :param description: Tooltip description
25
+ :type description: str
26
+
27
+ :param content: Tooltip content
28
+ :type content: str
29
+ """
30
+ def __init__(
31
+ self,
32
+ **kwargs
33
+ ):
34
+ self._name = None
35
+ self._description = None
36
+ self._content = None
37
+ self.update(**kwargs)
38
+
39
+ def update(
40
+ self,
41
+ **kwargs
42
+ ):
43
+ for key, value in kwargs.items():
44
+ setattr(self, key, value)
45
+
46
+ @property
47
+ def name(self):
48
+ return self._name
49
+
50
+ @name.setter
51
+ def name(self, _):
52
+ # None case
53
+ if _ is None:
54
+ self._name = None
55
+ return
56
+ # Real affectation
57
+ try:
58
+ self._name = str(_)
59
+ except Exception:
60
+ pass
61
+
62
+ @property
63
+ def description(self):
64
+ return self._description
65
+
66
+ @description.setter
67
+ def description(self, _):
68
+ # None case
69
+ if _ is None:
70
+ self._description = None
71
+ return
72
+ # Real affectation
73
+ try:
74
+ self._description = str(_)
75
+ except Exception:
76
+ pass
77
+
78
+ @property
79
+ def content(self):
80
+ return self._content
81
+
82
+ @content.setter
83
+ def content(self, _):
84
+ # None case
85
+ if _ is None:
86
+ self._content = None
87
+ return
88
+ # Real affectation
89
+ try:
90
+ self._content = str(_)
91
+ except Exception:
92
+ pass
93
+
94
+
95
+ class _ProtoSankeyObject(TableObject):
96
+ """
97
+ Proto class for SankeyObject.
98
+ Define a generic sankey object.
99
+ herits from TableObject.
100
+
101
+ Parameters
102
+ ----------
103
+ :param tags: List of tags of this object.
104
+ :type tags: list [_ProtoTag, ...]
105
+ """
106
+
107
+ def __init__(self):
108
+ # Init parent class
109
+ TableObject.__init__(self)
110
+ # Init attributes
111
+ self._tags = []
112
+ self._taggs = []
113
+ # List of tooltips
114
+ self._tooltips = {}
115
+
116
+ @property
117
+ def tags(self):
118
+ return self._tags
119
+
120
+ @property
121
+ def taggs(self):
122
+ return self._taggs
123
+
124
+ @property
125
+ def tooltips(self):
126
+ return self._tooltips
127
+
128
+ def add_tooltip(self, name, description, content):
129
+ self._tooltips[name] = _ProtoToolTip(
130
+ name=name,
131
+ description=description,
132
+ content=content)
133
+
134
+ def update_tooltip(self, name, **kwargs):
135
+ self._tooltips[name].update(**kwargs)
@@ -0,0 +1,95 @@
1
+ """
2
+ Author : Vincent LE DOZE
3
+ Date : 31/05/23
4
+
5
+ This file contains descriptions for proto TagGroup class
6
+
7
+ """
8
+
9
+ # Local modules -----------------------------------------------------
10
+ from SankeyExcelParser.sankey_utils.table_object import TableObject
11
+ from SankeyExcelParser.sankey_utils.functions import _stdStr
12
+
13
+
14
+ # CLASS ----------------------------------------------------------------------------
15
+ class _ProtoTagGroup(TableObject):
16
+ """
17
+ Proto class for TagGroup
18
+ Define a Tag Group object.
19
+
20
+ Parameters
21
+ ----------
22
+ :param name: Name of the groupe (standardized)
23
+ :type name: str
24
+
25
+ :param name_unformatted: Name of the groupe (not standardized, as written by the user)
26
+ :type name_unformatted: str
27
+
28
+ :param tags: All tags contained by the group as dictionnary, with standardized tags name as entries.
29
+ :type tags: dict = {str: Tag, ...}
30
+
31
+ :param is_palette: Is the tag group a palette.
32
+ :type is_palette: int
33
+
34
+ :param colormap: Color map for tags colors.
35
+ :type colormap: str
36
+
37
+ :param color: Colors for each tags.
38
+ :type color: str
39
+ """
40
+
41
+ def __init__(
42
+ self,
43
+ name: str,
44
+ taggtype: str
45
+ ):
46
+ # Init parent class
47
+ TableObject.__init__(self)
48
+ # Init attributes
49
+ self._name = _stdStr(name)
50
+ self._name_unformatted = name
51
+ self._type = taggtype
52
+ self._tags = {}
53
+ self._anti_tags = None
54
+ self._antagonists_taggs = []
55
+ self._is_palette = None
56
+ self._colormap = None
57
+
58
+ @property
59
+ def name(self):
60
+ return self._name
61
+
62
+ @property
63
+ def name_unformatted(self):
64
+ return self._name_unformatted
65
+
66
+ @property
67
+ def type(self):
68
+ return self._type
69
+
70
+ @property
71
+ def is_palette(self):
72
+ return self._is_palette
73
+
74
+ @is_palette.setter
75
+ def is_palette(self, _):
76
+ try:
77
+ self._is_palette = int(_)
78
+ except Exception:
79
+ pass
80
+
81
+ @property
82
+ def has_palette(self):
83
+ try:
84
+ return (self._is_palette > 0)
85
+ except Exception:
86
+ return False
87
+
88
+ @property
89
+ def colormap(self):
90
+ return self._colormap
91
+
92
+ @colormap.setter
93
+ def colormap(self, _):
94
+ if type(_) is str:
95
+ self._colormap = _