topologicpy 0.8.95__py3-none-any.whl → 0.8.97__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.
- topologicpy/Cell.py +3 -2
- topologicpy/Dictionary.py +952 -134
- topologicpy/Graph.py +954 -106
- topologicpy/Wire.py +29 -4
- topologicpy/version.py +1 -1
- {topologicpy-0.8.95.dist-info → topologicpy-0.8.97.dist-info}/METADATA +1 -1
- {topologicpy-0.8.95.dist-info → topologicpy-0.8.97.dist-info}/RECORD +10 -10
- {topologicpy-0.8.95.dist-info → topologicpy-0.8.97.dist-info}/WHEEL +1 -1
- {topologicpy-0.8.95.dist-info → topologicpy-0.8.97.dist-info}/licenses/LICENSE +0 -0
- {topologicpy-0.8.95.dist-info → topologicpy-0.8.97.dist-info}/top_level.txt +0 -0
topologicpy/Dictionary.py
CHANGED
|
@@ -46,6 +46,139 @@ class Dictionary():
|
|
|
46
46
|
dictionaries.append(Dictionary.ByKeysValues(keys, values))
|
|
47
47
|
return dictionaries
|
|
48
48
|
'''
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def _ConvertAttribute(attr):
|
|
52
|
+
"""
|
|
53
|
+
Convert the found attribute into the proper value
|
|
54
|
+
"""
|
|
55
|
+
from topologicpy.Topology import Topology
|
|
56
|
+
import json
|
|
57
|
+
|
|
58
|
+
def is_json_string(input_string):
|
|
59
|
+
"""
|
|
60
|
+
Check if the input string is a valid JSON string.
|
|
61
|
+
"""
|
|
62
|
+
try:
|
|
63
|
+
json.loads(input_string)
|
|
64
|
+
return True
|
|
65
|
+
except json.JSONDecodeError:
|
|
66
|
+
return False
|
|
67
|
+
|
|
68
|
+
def json_to_dict(json_string):
|
|
69
|
+
"""
|
|
70
|
+
Convert a JSON-formatted string to a Python dictionary.
|
|
71
|
+
"""
|
|
72
|
+
return json.loads(json_string)
|
|
73
|
+
|
|
74
|
+
if isinstance(attr, IntAttribute):
|
|
75
|
+
return (attr.IntValue())
|
|
76
|
+
elif isinstance(attr, DoubleAttribute):
|
|
77
|
+
return (attr.DoubleValue())
|
|
78
|
+
elif isinstance(attr, StringAttribute):
|
|
79
|
+
temp_value = attr.StringValue()
|
|
80
|
+
topologies = None
|
|
81
|
+
try:
|
|
82
|
+
if is_json_string(temp_value):
|
|
83
|
+
topologies = Topology.ByJSONString(temp_value)
|
|
84
|
+
else:
|
|
85
|
+
topologies = None
|
|
86
|
+
except:
|
|
87
|
+
topologies = None
|
|
88
|
+
if isinstance(topologies, list):
|
|
89
|
+
if len(topologies) == 0:
|
|
90
|
+
topologies = None
|
|
91
|
+
if temp_value == "__NONE__":
|
|
92
|
+
return None
|
|
93
|
+
elif Topology.IsInstance(topologies, "Topology"):
|
|
94
|
+
return topologies
|
|
95
|
+
elif isinstance(topologies, list):
|
|
96
|
+
if len(topologies) > 1:
|
|
97
|
+
return topologies
|
|
98
|
+
elif len(topologies) == 1:
|
|
99
|
+
return topologies[0]
|
|
100
|
+
elif is_json_string(temp_value):
|
|
101
|
+
ret_value = json_to_dict(temp_value)
|
|
102
|
+
return ret_value
|
|
103
|
+
else:
|
|
104
|
+
return (temp_value)
|
|
105
|
+
elif isinstance(attr, ListAttribute):
|
|
106
|
+
return (Dictionary.ListAttributeValues(attr))
|
|
107
|
+
elif isinstance(attr, float) or isinstance(attr, int):
|
|
108
|
+
return attr
|
|
109
|
+
elif isinstance(attr, str):
|
|
110
|
+
if attr == "__NONE__":
|
|
111
|
+
return None
|
|
112
|
+
topologies = None
|
|
113
|
+
try:
|
|
114
|
+
if is_json_string(attr):
|
|
115
|
+
topologies = Topology.ByJSONString(attr)
|
|
116
|
+
else:
|
|
117
|
+
topologies = None
|
|
118
|
+
except:
|
|
119
|
+
topologies = None
|
|
120
|
+
if isinstance(topologies, list):
|
|
121
|
+
if len(topologies) > 1:
|
|
122
|
+
return topologies
|
|
123
|
+
elif len(topologies) == 1:
|
|
124
|
+
return topologies[0]
|
|
125
|
+
elif is_json_string(attr):
|
|
126
|
+
return json_to_dict(attr)
|
|
127
|
+
else:
|
|
128
|
+
return (attr)
|
|
129
|
+
elif isinstance(attr, tuple):
|
|
130
|
+
return Dictionary.ListAttributeValues([Dictionary._ConvertAttribute(x) for x in list(attr)])
|
|
131
|
+
elif isinstance(attr, list):
|
|
132
|
+
return Dictionary.ListAttributeValues([Dictionary._ConvertAttribute(x) for x in attr])
|
|
133
|
+
elif isinstance(attr, dict):
|
|
134
|
+
return attr
|
|
135
|
+
else:
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
@staticmethod
|
|
139
|
+
def _ConvertValue(value):
|
|
140
|
+
"""
|
|
141
|
+
Converts the input value to the proper attribute
|
|
142
|
+
"""
|
|
143
|
+
from topologicpy.Topology import Topology
|
|
144
|
+
import json
|
|
145
|
+
|
|
146
|
+
def dict_to_json(py_dict):
|
|
147
|
+
"""
|
|
148
|
+
Convert a Python dictionary to a JSON-formatted string.
|
|
149
|
+
"""
|
|
150
|
+
return json.dumps(py_dict, indent=2)
|
|
151
|
+
|
|
152
|
+
attr = topologic.StringAttribute("__NONE__") # Hook to Core
|
|
153
|
+
if value == None:
|
|
154
|
+
attr = topologic.StringAttribute("__NONE__") # Hook to Core
|
|
155
|
+
elif isinstance(value, bool):
|
|
156
|
+
if value == False:
|
|
157
|
+
attr = topologic.IntAttribute(0) # Hook to Core
|
|
158
|
+
else:
|
|
159
|
+
attr = topologic.IntAttribute(1) # Hook to Core
|
|
160
|
+
elif isinstance(value, int):
|
|
161
|
+
attr = topologic.IntAttribute(value) # Hook to Core
|
|
162
|
+
elif isinstance(value, float):
|
|
163
|
+
attr = topologic.DoubleAttribute(value) # Hook to Core
|
|
164
|
+
elif Topology.IsInstance(value, "Topology"):
|
|
165
|
+
str_value = Topology.JSONString(value)
|
|
166
|
+
attr = topologic.StringAttribute(str_value) # Hook to Core
|
|
167
|
+
elif isinstance(value, dict):
|
|
168
|
+
str_value = dict_to_json(value)
|
|
169
|
+
attr = topologic.StringAttribute(str_value) # Hook to Core
|
|
170
|
+
elif isinstance(value, str):
|
|
171
|
+
attr = topologic.StringAttribute(value) # Hook to Core
|
|
172
|
+
elif isinstance(value, tuple):
|
|
173
|
+
l = [Dictionary._ConvertValue(v) for v in list(value)]
|
|
174
|
+
attr = topologic.ListAttribute(l) # Hook to Core
|
|
175
|
+
elif isinstance(value, list):
|
|
176
|
+
l = [Dictionary._ConvertValue(v) for v in value]
|
|
177
|
+
attr = topologic.ListAttribute(l) # Hook to Core
|
|
178
|
+
else:
|
|
179
|
+
attr = topologic.StringAttribute("__NONE__") # Hook to Core
|
|
180
|
+
return attr
|
|
181
|
+
|
|
49
182
|
@staticmethod
|
|
50
183
|
def AdjacencyDictionary(topology, subTopologyType: str = None, labelKey: str = None, weightKey: str = None, includeWeights: bool = False, mantissa: int = 6, silent: bool = False):
|
|
51
184
|
"""
|
|
@@ -165,7 +298,134 @@ class Dictionary():
|
|
|
165
298
|
d = Dictionary.RemoveKey(d, labelKey)
|
|
166
299
|
subtopology = Topology.SetDictionary(subtopology, d)
|
|
167
300
|
return adjDict
|
|
168
|
-
|
|
301
|
+
|
|
302
|
+
@staticmethod
|
|
303
|
+
def BooleanDictionariesByKey(dictionariesA,
|
|
304
|
+
dictionariesB,
|
|
305
|
+
key: str,
|
|
306
|
+
operation: str = "union",
|
|
307
|
+
exclusive: bool = True,
|
|
308
|
+
silent: bool = False):
|
|
309
|
+
"""
|
|
310
|
+
Booleans the keys/values of the dictionaries in the second list on the
|
|
311
|
+
dictionaries in the first list based on a shared dictionary key/value and the boolean operation.
|
|
312
|
+
|
|
313
|
+
If a dictionary in the first list and a dictionary in second list have the same value
|
|
314
|
+
for the given dictionary key, the dictionary from the second list is imprinted the dictionary
|
|
315
|
+
in the first list.
|
|
316
|
+
|
|
317
|
+
Parameters
|
|
318
|
+
----------
|
|
319
|
+
dictionariesA : list[topologic_core.Dictionary]
|
|
320
|
+
Target list of dictionaries to be updated.
|
|
321
|
+
dictionariesB : list[topologic_core.Dictionary]
|
|
322
|
+
Source list of dictionaries providing values.
|
|
323
|
+
key : str
|
|
324
|
+
Dictionary key used to match dictionaries.
|
|
325
|
+
operation : str , optional
|
|
326
|
+
the type of desired boolean operation. Options are:
|
|
327
|
+
- "union" / "merge"
|
|
328
|
+
- "difference"
|
|
329
|
+
- "intersection"
|
|
330
|
+
- "SymmetricDifference" / "SymDif" / "XOR"
|
|
331
|
+
- "Impose"
|
|
332
|
+
- "Imprint"
|
|
333
|
+
The options are case-insensitive. Default is "union"
|
|
334
|
+
exclusive: bool , optional
|
|
335
|
+
If set to True, only the first matching dictionary in the second list is applied.
|
|
336
|
+
silent : bool , optional
|
|
337
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
|
338
|
+
|
|
339
|
+
Returns
|
|
340
|
+
-------
|
|
341
|
+
list[topologic_core.Dictionary]
|
|
342
|
+
The updated first list of dictionaries
|
|
343
|
+
"""
|
|
344
|
+
|
|
345
|
+
from topologicpy.Topology import Topology
|
|
346
|
+
from topologicpy.Dictionary import Dictionary
|
|
347
|
+
|
|
348
|
+
dictionariesA = [d for d in dictionariesA if Topology.IsInstance(d, "Dictionary")]
|
|
349
|
+
if len(dictionariesA) < 1:
|
|
350
|
+
if not silent:
|
|
351
|
+
print("Dictionary.BooleanDictionariesByKey - Error: The dictionariesA input parameter does not contain any valid dictionaries. Returning None.")
|
|
352
|
+
return None
|
|
353
|
+
|
|
354
|
+
dictionariesB = [d for d in dictionariesB if Topology.IsInstance(d, "Dictionary")]
|
|
355
|
+
if len(dictionariesB) < 1:
|
|
356
|
+
if not silent:
|
|
357
|
+
print("Dictionary.BooleanDictionariesByKey - Error: The dictionariesB input parameter does not contain any valid dictionaries. Returning None.")
|
|
358
|
+
return None
|
|
359
|
+
|
|
360
|
+
dictionariesC = []
|
|
361
|
+
op = operation.lower()
|
|
362
|
+
if not op in ["union", "merge", "difference", "intersection", "symmetricdifference", "symdif", "xor", "impose", "imprint"]:
|
|
363
|
+
if not silent:
|
|
364
|
+
print("Dictionary.BooleanDictionariesByKey - Error: Unrecognized boolean operation. Returning None.")
|
|
365
|
+
return None
|
|
366
|
+
# Imprint dictionariesB unto dictionariesA
|
|
367
|
+
if exclusive:
|
|
368
|
+
lookup = {}
|
|
369
|
+
for d in dictionariesB:
|
|
370
|
+
if d:
|
|
371
|
+
v = Dictionary.ValueAtKey(d, key)
|
|
372
|
+
lookup[v] = d
|
|
373
|
+
for dA in dictionariesA:
|
|
374
|
+
if not dA:
|
|
375
|
+
continue
|
|
376
|
+
vA = Dictionary.ValueAtKey(dA, key, None)
|
|
377
|
+
dB = lookup.get(vA, None)
|
|
378
|
+
if dB:
|
|
379
|
+
if op in ["union", "merge"]:
|
|
380
|
+
dA = Dictionary.Union(dA, dB)
|
|
381
|
+
elif op == "difference":
|
|
382
|
+
dA = Dictionary.Difference(dA, dB)
|
|
383
|
+
elif op == "intersection":
|
|
384
|
+
dA = Dictionary.Intersection(dA, dB)
|
|
385
|
+
elif op in ["symmetricdifference", "symdif", "xor"]:
|
|
386
|
+
dA = Dictionary.SymmetricDifference(dA, dB)
|
|
387
|
+
elif op == "impose":
|
|
388
|
+
dA = Dictionary.Impose(dA, dB)
|
|
389
|
+
elif op == "imprint":
|
|
390
|
+
dA = Dictionary.Imprint(dA, dB)
|
|
391
|
+
else:
|
|
392
|
+
continue
|
|
393
|
+
dictionariesC.append(dA)
|
|
394
|
+
else:
|
|
395
|
+
if not silent:
|
|
396
|
+
print(f"Dictionary.BooleanDictionariesByKey - Warning: No match found for {vA}. Assigning an empty dictionary.")
|
|
397
|
+
dictionariesC.append(Dictionary.ByKeysValues([],[]))
|
|
398
|
+
else:
|
|
399
|
+
for dA in dictionariesA:
|
|
400
|
+
if not dA:
|
|
401
|
+
continue
|
|
402
|
+
vA = Dictionary.ValueAtKey(dA, key, None)
|
|
403
|
+
if vA:
|
|
404
|
+
for dB in dictionariesB:
|
|
405
|
+
if not dB:
|
|
406
|
+
continue
|
|
407
|
+
vB = Dictionary.ValueAtKey(dB, key, None)
|
|
408
|
+
if not vB:
|
|
409
|
+
continue
|
|
410
|
+
if vA == vB:
|
|
411
|
+
if op in ["union", "merge"]:
|
|
412
|
+
dA = Dictionary.Union(dA, dB)
|
|
413
|
+
elif op == "difference":
|
|
414
|
+
dA = Dictionary.Difference(dA, dB)
|
|
415
|
+
elif op == "intersection":
|
|
416
|
+
dA = Dictionary.Intersection(dA, dB)
|
|
417
|
+
elif op in ["symmetricdifference", "symdif", "xor"]:
|
|
418
|
+
dA = Dictionary.SymmetricDifference(dA, dB)
|
|
419
|
+
elif op == "impose":
|
|
420
|
+
dA = Dictionary.Impose(dA, dB)
|
|
421
|
+
elif op == "imprint":
|
|
422
|
+
dA = Dictionary.Imprint(dA, dB)
|
|
423
|
+
else:
|
|
424
|
+
continue
|
|
425
|
+
dictionariesC.append(dA)
|
|
426
|
+
|
|
427
|
+
return dictionariesC
|
|
428
|
+
|
|
169
429
|
@staticmethod
|
|
170
430
|
def ByKeyValue(key, value, silent: bool = False):
|
|
171
431
|
"""
|
|
@@ -192,51 +452,6 @@ class Dictionary():
|
|
|
192
452
|
return None
|
|
193
453
|
return Dictionary.ByKeysValues([key], [value], silent=silent)
|
|
194
454
|
|
|
195
|
-
|
|
196
|
-
@staticmethod
|
|
197
|
-
def _ConvertValue(value):
|
|
198
|
-
"""
|
|
199
|
-
Converts the input value to the proper attribute
|
|
200
|
-
"""
|
|
201
|
-
from topologicpy.Topology import Topology
|
|
202
|
-
import json
|
|
203
|
-
|
|
204
|
-
def dict_to_json(py_dict):
|
|
205
|
-
"""
|
|
206
|
-
Convert a Python dictionary to a JSON-formatted string.
|
|
207
|
-
"""
|
|
208
|
-
return json.dumps(py_dict, indent=2)
|
|
209
|
-
|
|
210
|
-
attr = topologic.StringAttribute("__NONE__") # Hook to Core
|
|
211
|
-
if value == None:
|
|
212
|
-
attr = topologic.StringAttribute("__NONE__") # Hook to Core
|
|
213
|
-
elif isinstance(value, bool):
|
|
214
|
-
if value == False:
|
|
215
|
-
attr = topologic.IntAttribute(0) # Hook to Core
|
|
216
|
-
else:
|
|
217
|
-
attr = topologic.IntAttribute(1) # Hook to Core
|
|
218
|
-
elif isinstance(value, int):
|
|
219
|
-
attr = topologic.IntAttribute(value) # Hook to Core
|
|
220
|
-
elif isinstance(value, float):
|
|
221
|
-
attr = topologic.DoubleAttribute(value) # Hook to Core
|
|
222
|
-
elif Topology.IsInstance(value, "Topology"):
|
|
223
|
-
str_value = Topology.JSONString(value)
|
|
224
|
-
attr = topologic.StringAttribute(str_value) # Hook to Core
|
|
225
|
-
elif isinstance(value, dict):
|
|
226
|
-
str_value = dict_to_json(value)
|
|
227
|
-
attr = topologic.StringAttribute(str_value) # Hook to Core
|
|
228
|
-
elif isinstance(value, str):
|
|
229
|
-
attr = topologic.StringAttribute(value) # Hook to Core
|
|
230
|
-
elif isinstance(value, tuple):
|
|
231
|
-
l = [Dictionary._ConvertValue(v) for v in list(value)]
|
|
232
|
-
attr = topologic.ListAttribute(l) # Hook to Core
|
|
233
|
-
elif isinstance(value, list):
|
|
234
|
-
l = [Dictionary._ConvertValue(v) for v in value]
|
|
235
|
-
attr = topologic.ListAttribute(l) # Hook to Core
|
|
236
|
-
else:
|
|
237
|
-
attr = topologic.StringAttribute("__NONE__") # Hook to Core
|
|
238
|
-
return attr
|
|
239
|
-
|
|
240
455
|
@staticmethod
|
|
241
456
|
def ByKeysValues(keys, values, silent: bool = False):
|
|
242
457
|
"""
|
|
@@ -500,7 +715,71 @@ class Dictionary():
|
|
|
500
715
|
keys = Dictionary.Keys(dictionary)
|
|
501
716
|
values = Dictionary.Values(dictionary)
|
|
502
717
|
return Dictionary.ByKeysValues(keys, values)
|
|
503
|
-
|
|
718
|
+
|
|
719
|
+
@staticmethod
|
|
720
|
+
def Difference(dictionaryA, dictionaryB, silent: bool = False):
|
|
721
|
+
"""
|
|
722
|
+
Returns the difference of dictionaryA and dictionaryB (A \\ B), based on keys.
|
|
723
|
+
|
|
724
|
+
Procedure
|
|
725
|
+
---------
|
|
726
|
+
1. Validate inputs.
|
|
727
|
+
2. If dictionaryA is None, return None.
|
|
728
|
+
3. If dictionaryB is None, return dictionaryA.
|
|
729
|
+
4. Return a new dictionary containing only keys found in dictionaryA but not
|
|
730
|
+
found in dictionaryB. Values are derived from dictionaryA.
|
|
731
|
+
|
|
732
|
+
Parameters
|
|
733
|
+
----------
|
|
734
|
+
dictionaryA : topologic_core.Dictionary
|
|
735
|
+
The first input dictionary (minuend).
|
|
736
|
+
dictionaryB : topologic_core.Dictionary
|
|
737
|
+
The second input dictionary (subtrahend).
|
|
738
|
+
silent : bool , optional
|
|
739
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
|
740
|
+
|
|
741
|
+
Returns
|
|
742
|
+
-------
|
|
743
|
+
topologic_core.Dictionary
|
|
744
|
+
The resulting difference dictionary.
|
|
745
|
+
|
|
746
|
+
"""
|
|
747
|
+
from topologicpy.Topology import Topology
|
|
748
|
+
|
|
749
|
+
if dictionaryA is None:
|
|
750
|
+
if not silent:
|
|
751
|
+
print("Dictionary.Difference - Warning: The dictionaryA input parameter is None. Returning None.")
|
|
752
|
+
return None
|
|
753
|
+
|
|
754
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
755
|
+
if not silent:
|
|
756
|
+
print("Dictionary.Difference - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
757
|
+
return None
|
|
758
|
+
|
|
759
|
+
if dictionaryB is None:
|
|
760
|
+
if not silent:
|
|
761
|
+
print("Dictionary.Difference - Warning: The dictionaryB input parameter is None. Returning dictionaryA.")
|
|
762
|
+
return dictionaryA
|
|
763
|
+
|
|
764
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
765
|
+
if not silent:
|
|
766
|
+
print("Dictionary.Difference - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
767
|
+
return None
|
|
768
|
+
|
|
769
|
+
keysA = Dictionary.Keys(dictionaryA) or []
|
|
770
|
+
keysB = Dictionary.Keys(dictionaryB) or []
|
|
771
|
+
|
|
772
|
+
out_keys = [k for k in keysA if k not in keysB]
|
|
773
|
+
|
|
774
|
+
if len(out_keys) == 0:
|
|
775
|
+
if not silent:
|
|
776
|
+
print("Dictionary.Difference - Warning: There are no keys in dictionaryA that are not in dictionaryB. Returning and empty dictionary.")
|
|
777
|
+
return Dictionary.ByKeysValues([], [])
|
|
778
|
+
|
|
779
|
+
out_vals = [Dictionary.ValueAtKey(dictionaryA, k) for k in out_keys]
|
|
780
|
+
|
|
781
|
+
return Dictionary.ByKeysValues(out_keys, out_vals)
|
|
782
|
+
|
|
504
783
|
@staticmethod
|
|
505
784
|
def Filter(elements, dictionaries, searchType="any", key=None, value=None):
|
|
506
785
|
"""
|
|
@@ -592,22 +871,288 @@ class Dictionary():
|
|
|
592
871
|
otherElements.append(elements[i])
|
|
593
872
|
return {"filteredDictionaries": filteredDictionaries, "otherDictionaries": otherDictionaries, "filteredIndices": filteredIndices, "otherIndices": otherIndices, "filteredElements": filteredElements, "otherElements": otherElements}
|
|
594
873
|
|
|
874
|
+
|
|
595
875
|
@staticmethod
|
|
596
|
-
def
|
|
876
|
+
def Intersection(dictionaryA, dictionaryB, silent: bool = False):
|
|
597
877
|
"""
|
|
598
|
-
Returns the
|
|
599
|
-
|
|
878
|
+
Returns the intersection of dA and dB, based on keys, using a two-step
|
|
879
|
+
construction and Dictionary.ByMergedDictionaries.
|
|
880
|
+
|
|
881
|
+
Procedure
|
|
882
|
+
---------
|
|
883
|
+
1. Compute the common keys between dA and dB.
|
|
884
|
+
2. Build two new dictionaries (dA_1 and dB_1) that contain exactly the
|
|
885
|
+
same common keys:
|
|
886
|
+
- dA_1 values are taken from dA
|
|
887
|
+
- dB_1 values are taken from dB
|
|
888
|
+
3. Return Dictionary.ByMergedDictionaries(dA_1, dB_1)
|
|
889
|
+
|
|
600
890
|
Parameters
|
|
601
891
|
----------
|
|
602
|
-
|
|
603
|
-
The input dictionary.
|
|
892
|
+
dictionaryA : topologic_core.Dictionary
|
|
893
|
+
The first input dictionary.
|
|
894
|
+
dictionaryB : topologic_core.Dictionary
|
|
895
|
+
The second input dictionary.
|
|
604
896
|
silent : bool , optional
|
|
605
897
|
If set to True, error and warning messages are suppressed. Default is False.
|
|
606
898
|
|
|
607
899
|
Returns
|
|
608
900
|
-------
|
|
609
|
-
|
|
610
|
-
The
|
|
901
|
+
topologic_core.Dictionary
|
|
902
|
+
The resulting intersection dictionary.
|
|
903
|
+
|
|
904
|
+
"""
|
|
905
|
+
from topologicpy.Topology import Topology
|
|
906
|
+
|
|
907
|
+
if dictionaryA is None or dictionaryB is None:
|
|
908
|
+
if not silent:
|
|
909
|
+
print("Dictionary.Intersection - Warning: One or both of the input dictionaries is None. Returning and empty dictionary.")
|
|
910
|
+
return Dictionary.ByKeysValues([], [])
|
|
911
|
+
|
|
912
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
913
|
+
if not silent:
|
|
914
|
+
print("Dictionary.Intersection - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
915
|
+
return None
|
|
916
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
917
|
+
if not silent:
|
|
918
|
+
print("Dictionary.Intersection - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
919
|
+
return None
|
|
920
|
+
|
|
921
|
+
keysA = Dictionary.Keys(dictionaryA) or []
|
|
922
|
+
keysB = Dictionary.Keys(dictionaryB) or []
|
|
923
|
+
|
|
924
|
+
common_keys = [k for k in keysA if k in keysB]
|
|
925
|
+
|
|
926
|
+
if len(common_keys) == 0:
|
|
927
|
+
if not silent:
|
|
928
|
+
print("Dictionary.Intersection - Warning: There are no common keys in the input dictionaries. Returning and empty dictionary.")
|
|
929
|
+
return Dictionary.ByKeysValues([], [])
|
|
930
|
+
|
|
931
|
+
a_vals = [Dictionary.ValueAtKey(dictionaryA, k) for k in common_keys]
|
|
932
|
+
b_vals = [Dictionary.ValueAtKey(dictionaryB, k) for k in common_keys]
|
|
933
|
+
|
|
934
|
+
dA_1 = Dictionary.ByKeysValues(common_keys, a_vals)
|
|
935
|
+
dB_1 = Dictionary.ByKeysValues(common_keys, b_vals)
|
|
936
|
+
|
|
937
|
+
return Dictionary.ByMergedDictionaries(dA_1, dB_1)
|
|
938
|
+
|
|
939
|
+
@staticmethod
|
|
940
|
+
def Impose(dictionaryA, dictionaryB, silent: bool = False):
|
|
941
|
+
"""
|
|
942
|
+
Imposes dictionaryB onto dictionaryA.
|
|
943
|
+
|
|
944
|
+
Procedure
|
|
945
|
+
---------
|
|
946
|
+
1. Validate inputs.
|
|
947
|
+
2. If dictionaryA is None, return None.
|
|
948
|
+
3. If dictionaryB is None, return dictionaryA.
|
|
949
|
+
4. Create a new dictionary that:
|
|
950
|
+
- overwrites values in dictionaryA with values from dictionaryB for overlapping keys
|
|
951
|
+
- adds keys/values from dictionaryB that do not exist in dictionaryA
|
|
952
|
+
|
|
953
|
+
Parameters
|
|
954
|
+
----------
|
|
955
|
+
dictionaryA : topologic_core.Dictionary
|
|
956
|
+
The first input dictionary (base).
|
|
957
|
+
dictionaryB : topologic_core.Dictionary
|
|
958
|
+
The second input dictionary (imposed).
|
|
959
|
+
silent : bool , optional
|
|
960
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
|
961
|
+
|
|
962
|
+
Returns
|
|
963
|
+
-------
|
|
964
|
+
topologic_core.Dictionary
|
|
965
|
+
The resulting imposed dictionary.
|
|
966
|
+
|
|
967
|
+
"""
|
|
968
|
+
from topologicpy.Topology import Topology
|
|
969
|
+
|
|
970
|
+
if dictionaryA is None:
|
|
971
|
+
if not silent:
|
|
972
|
+
print("Dictionary.Impose - Warning: The dictionaryA input parameter is None. Returning None.")
|
|
973
|
+
return None
|
|
974
|
+
|
|
975
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
976
|
+
if not silent:
|
|
977
|
+
print("Dictionary.Impose - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
978
|
+
return None
|
|
979
|
+
|
|
980
|
+
if dictionaryB is None:
|
|
981
|
+
if not silent:
|
|
982
|
+
print("Dictionary.Impose - Warning: The dictionaryB input parameter is None. Returning dictionaryA.")
|
|
983
|
+
return dictionaryA
|
|
984
|
+
|
|
985
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
986
|
+
if not silent:
|
|
987
|
+
print("Dictionary.Impose - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
988
|
+
return None
|
|
989
|
+
|
|
990
|
+
keysA = Dictionary.Keys(dictionaryA) or []
|
|
991
|
+
keysB = Dictionary.Keys(dictionaryB) or []
|
|
992
|
+
|
|
993
|
+
# Preserve A order first
|
|
994
|
+
out_keys = list(keysA)
|
|
995
|
+
out_vals = [Dictionary.ValueAtKey(dictionaryA, k) for k in keysA]
|
|
996
|
+
index_map = {k: i for i, k in enumerate(out_keys)}
|
|
997
|
+
|
|
998
|
+
for k in keysB:
|
|
999
|
+
vB = Dictionary.ValueAtKey(dictionaryB, k)
|
|
1000
|
+
if k in index_map:
|
|
1001
|
+
out_vals[index_map[k]] = vB
|
|
1002
|
+
else:
|
|
1003
|
+
index_map[k] = len(out_keys)
|
|
1004
|
+
out_keys.append(k)
|
|
1005
|
+
out_vals.append(vB)
|
|
1006
|
+
|
|
1007
|
+
return Dictionary.ByKeysValues(out_keys, out_vals)
|
|
1008
|
+
|
|
1009
|
+
@staticmethod
|
|
1010
|
+
def Imprint(dictionaryA, dictionaryB, silent: bool = False):
|
|
1011
|
+
"""
|
|
1012
|
+
Imprints dictionaryB onto dictionaryA.
|
|
1013
|
+
|
|
1014
|
+
Procedure
|
|
1015
|
+
---------
|
|
1016
|
+
1. Validate inputs.
|
|
1017
|
+
2. If dictionaryA is None, return None.
|
|
1018
|
+
3. If dictionaryB is None, return dictionaryA.
|
|
1019
|
+
4. Create a new dictionary that:
|
|
1020
|
+
- overwrites values in dictionaryA with values from dictionaryB for overlapping keys
|
|
1021
|
+
- ignores keys in dictionaryB that do not exist in dictionaryA
|
|
1022
|
+
|
|
1023
|
+
Parameters
|
|
1024
|
+
----------
|
|
1025
|
+
dictionaryA : topologic_core.Dictionary
|
|
1026
|
+
The first input dictionary (base).
|
|
1027
|
+
dictionaryB : topologic_core.Dictionary
|
|
1028
|
+
The second input dictionary (imprinted).
|
|
1029
|
+
silent : bool , optional
|
|
1030
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
|
1031
|
+
|
|
1032
|
+
Returns
|
|
1033
|
+
-------
|
|
1034
|
+
topologic_core.Dictionary
|
|
1035
|
+
The resulting imprinted dictionary.
|
|
1036
|
+
|
|
1037
|
+
"""
|
|
1038
|
+
from topologicpy.Topology import Topology
|
|
1039
|
+
|
|
1040
|
+
if dictionaryA is None:
|
|
1041
|
+
if not silent:
|
|
1042
|
+
print("Dictionary.Imprint - Warning: The dictionaryA input parameter is None. Returning None.")
|
|
1043
|
+
return None
|
|
1044
|
+
|
|
1045
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1046
|
+
if not silent:
|
|
1047
|
+
print("Dictionary.Imprint - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
1048
|
+
return None
|
|
1049
|
+
|
|
1050
|
+
if dictionaryB is None:
|
|
1051
|
+
if not silent:
|
|
1052
|
+
print("Dictionary.Imprint - Warning: The dictionaryB input parameter is None. Returning dictionaryA.")
|
|
1053
|
+
return dictionaryA
|
|
1054
|
+
|
|
1055
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1056
|
+
if not silent:
|
|
1057
|
+
print("Dictionary.Imprint - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
1058
|
+
return None
|
|
1059
|
+
|
|
1060
|
+
keysA = Dictionary.Keys(dictionaryA) or []
|
|
1061
|
+
keysB = Dictionary.Keys(dictionaryB) or []
|
|
1062
|
+
|
|
1063
|
+
keysB_set = set(keysB)
|
|
1064
|
+
|
|
1065
|
+
out_keys = list(keysA)
|
|
1066
|
+
out_vals = []
|
|
1067
|
+
for k in keysA:
|
|
1068
|
+
if k in keysB_set:
|
|
1069
|
+
out_vals.append(Dictionary.ValueAtKey(dictionaryB, k))
|
|
1070
|
+
else:
|
|
1071
|
+
out_vals.append(Dictionary.ValueAtKey(dictionaryA, k))
|
|
1072
|
+
|
|
1073
|
+
return Dictionary.ByKeysValues(out_keys, out_vals)
|
|
1074
|
+
|
|
1075
|
+
@staticmethod
|
|
1076
|
+
def Intersection(dictionaryA, dictionaryB, silent: bool = False):
|
|
1077
|
+
"""
|
|
1078
|
+
Returns the intersection of dA and dB, based on keys, using a two-step
|
|
1079
|
+
construction and Dictionary.ByMergedDictionaries.
|
|
1080
|
+
|
|
1081
|
+
Procedure
|
|
1082
|
+
---------
|
|
1083
|
+
1. Compute the common keys between dA and dB.
|
|
1084
|
+
2. Build two new dictionaries (dA_1 and dB_1) that contain exactly the
|
|
1085
|
+
same common keys:
|
|
1086
|
+
- dA_1 values are taken from dA
|
|
1087
|
+
- dB_1 values are taken from dB
|
|
1088
|
+
3. Return Dictionary.ByMergedDictionaries(dA_1, dB_1)
|
|
1089
|
+
|
|
1090
|
+
Parameters
|
|
1091
|
+
----------
|
|
1092
|
+
dictionaryA : topologic_core.Dictionary
|
|
1093
|
+
The first input dictionary.
|
|
1094
|
+
dictionaryB : topologic_core.Dictionary
|
|
1095
|
+
The second input dictionary.
|
|
1096
|
+
silent : bool , optional
|
|
1097
|
+
If set to True, warnings and errors are suppressed. Default is False.
|
|
1098
|
+
|
|
1099
|
+
Returns
|
|
1100
|
+
-------
|
|
1101
|
+
topologic_core.Dictionary
|
|
1102
|
+
The resulting intersection dictionary.
|
|
1103
|
+
|
|
1104
|
+
"""
|
|
1105
|
+
|
|
1106
|
+
from topologicpy.Topology import Topology
|
|
1107
|
+
|
|
1108
|
+
if dictionaryA is None or dictionaryB is None:
|
|
1109
|
+
if not silent:
|
|
1110
|
+
print("Dictionary.Intersection - Warning: One or both of the input dictionaries is None. Returning and empty dictionary.")
|
|
1111
|
+
return Dictionary.ByKeysValues([], [])
|
|
1112
|
+
|
|
1113
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1114
|
+
if not silent:
|
|
1115
|
+
print("Dictionary.Intersection - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
1116
|
+
return None
|
|
1117
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1118
|
+
if not silent:
|
|
1119
|
+
print("Dictionary.Intersection - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
1120
|
+
return None
|
|
1121
|
+
|
|
1122
|
+
keysA = Dictionary.Keys(dictionaryA) or []
|
|
1123
|
+
keysB = Dictionary.Keys(dictionaryB) or []
|
|
1124
|
+
|
|
1125
|
+
common_keys = [k for k in keysA if k in keysB]
|
|
1126
|
+
|
|
1127
|
+
if len(common_keys) == 0:
|
|
1128
|
+
if not silent:
|
|
1129
|
+
print("Dictionary.Intersection - Warning: There are no common keys in the input dictionaries. Returning and empty dictionary.")
|
|
1130
|
+
return Dictionary.ByKeysValues([], [])
|
|
1131
|
+
|
|
1132
|
+
a_vals = [Dictionary.ValueAtKey(dictionaryA, k) for k in common_keys]
|
|
1133
|
+
b_vals = [Dictionary.ValueAtKey(dictionaryB, k) for k in common_keys]
|
|
1134
|
+
|
|
1135
|
+
dA_1 = Dictionary.ByKeysValues(common_keys, a_vals)
|
|
1136
|
+
dB_1 = Dictionary.ByKeysValues(common_keys, b_vals)
|
|
1137
|
+
|
|
1138
|
+
return Dictionary.ByMergedDictionaries(dA_1, dB_1)
|
|
1139
|
+
|
|
1140
|
+
@staticmethod
|
|
1141
|
+
def Keys(dictionary, silent: bool = False):
|
|
1142
|
+
"""
|
|
1143
|
+
Returns the keys of the input dictionary.
|
|
1144
|
+
|
|
1145
|
+
Parameters
|
|
1146
|
+
----------
|
|
1147
|
+
dictionary : topologic_core.Dictionary or dict
|
|
1148
|
+
The input dictionary.
|
|
1149
|
+
silent : bool , optional
|
|
1150
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
|
1151
|
+
|
|
1152
|
+
Returns
|
|
1153
|
+
-------
|
|
1154
|
+
list
|
|
1155
|
+
The list of keys of the input dictionary.
|
|
611
1156
|
|
|
612
1157
|
"""
|
|
613
1158
|
from topologicpy.Topology import Topology
|
|
@@ -646,7 +1191,65 @@ class Dictionary():
|
|
|
646
1191
|
listAttributes = listAttribute.ListValue()
|
|
647
1192
|
returnList = [Dictionary._ConvertAttribute(attr) for attr in listAttributes]
|
|
648
1193
|
return returnList
|
|
649
|
-
|
|
1194
|
+
|
|
1195
|
+
@staticmethod
|
|
1196
|
+
def Merge(dictionaryA, dictionaryB, silent: bool = False):
|
|
1197
|
+
"""
|
|
1198
|
+
Returns the merge (union) of dictionaryA and dictionaryB.
|
|
1199
|
+
|
|
1200
|
+
Procedure
|
|
1201
|
+
---------
|
|
1202
|
+
1. Validate inputs.
|
|
1203
|
+
2. If either input is None, return the other (if valid).
|
|
1204
|
+
3. Return Dictionary.ByMergedDictionaries(dictionaryA, dictionaryB).
|
|
1205
|
+
|
|
1206
|
+
Parameters
|
|
1207
|
+
----------
|
|
1208
|
+
dictionaryA : topologic_core.Dictionary
|
|
1209
|
+
The first input dictionary.
|
|
1210
|
+
dictionaryB : topologic_core.Dictionary
|
|
1211
|
+
The second input dictionary.
|
|
1212
|
+
silent : bool , optional
|
|
1213
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
|
1214
|
+
|
|
1215
|
+
Returns
|
|
1216
|
+
-------
|
|
1217
|
+
topologic_core.Dictionary
|
|
1218
|
+
The resulting merged dictionary.
|
|
1219
|
+
|
|
1220
|
+
"""
|
|
1221
|
+
from topologicpy.Topology import Topology
|
|
1222
|
+
|
|
1223
|
+
if dictionaryA is None and dictionaryB is None:
|
|
1224
|
+
if not silent:
|
|
1225
|
+
print("Dictionary.Merge - Warning: Both of the input dictionaries are None. Returning None.")
|
|
1226
|
+
return None
|
|
1227
|
+
|
|
1228
|
+
if dictionaryA is None:
|
|
1229
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1230
|
+
if not silent:
|
|
1231
|
+
print("Dictionary.Merge - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
1232
|
+
return None
|
|
1233
|
+
return dictionaryB
|
|
1234
|
+
|
|
1235
|
+
if dictionaryB is None:
|
|
1236
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1237
|
+
if not silent:
|
|
1238
|
+
print("Dictionary.Merge - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
1239
|
+
return None
|
|
1240
|
+
return dictionaryA
|
|
1241
|
+
|
|
1242
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1243
|
+
if not silent:
|
|
1244
|
+
print("Dictionary.Merge - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
1245
|
+
return None
|
|
1246
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1247
|
+
if not silent:
|
|
1248
|
+
print("Dictionary.Merge - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
1249
|
+
return None
|
|
1250
|
+
|
|
1251
|
+
return Dictionary.ByMergedDictionaries(dictionaryA, dictionaryB)
|
|
1252
|
+
|
|
650
1253
|
@staticmethod
|
|
651
1254
|
def PythonDictionary(dictionary, silent: bool = False):
|
|
652
1255
|
"""
|
|
@@ -854,92 +1457,226 @@ class Dictionary():
|
|
|
854
1457
|
return dictionary
|
|
855
1458
|
|
|
856
1459
|
@staticmethod
|
|
857
|
-
def
|
|
1460
|
+
def SymDif(dictionaryA, dictionaryB, silent: bool = False):
|
|
858
1461
|
"""
|
|
859
|
-
|
|
1462
|
+
Returns the symmetric difference (XOR) of dictionaryA and dictionaryB, based on keys.
|
|
1463
|
+
|
|
1464
|
+
Procedure
|
|
1465
|
+
---------
|
|
1466
|
+
1. Validate inputs.
|
|
1467
|
+
2. Compute keys that exist in exactly one of the two dictionaries.
|
|
1468
|
+
3. Create a new dictionary containing:
|
|
1469
|
+
- unique keys from dictionaryA with values from dictionaryA
|
|
1470
|
+
- unique keys from dictionaryB with values from dictionaryB
|
|
1471
|
+
|
|
1472
|
+
Parameters
|
|
1473
|
+
----------
|
|
1474
|
+
dictionaryA : topologic_core.Dictionary
|
|
1475
|
+
The first input dictionary.
|
|
1476
|
+
dictionaryB : topologic_core.Dictionary
|
|
1477
|
+
The second input dictionary.
|
|
1478
|
+
silent : bool , optional
|
|
1479
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
|
1480
|
+
|
|
1481
|
+
Returns
|
|
1482
|
+
-------
|
|
1483
|
+
topologic_core.Dictionary
|
|
1484
|
+
The resulting symmetric difference dictionary.
|
|
1485
|
+
|
|
860
1486
|
"""
|
|
861
1487
|
from topologicpy.Topology import Topology
|
|
862
|
-
import json
|
|
863
1488
|
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
try:
|
|
869
|
-
json.loads(input_string)
|
|
870
|
-
return True
|
|
871
|
-
except json.JSONDecodeError:
|
|
872
|
-
return False
|
|
1489
|
+
if dictionaryA is None and dictionaryB is None:
|
|
1490
|
+
if not silent:
|
|
1491
|
+
print("Dictionary.SymDif - Warning: Both of the input dictionaries are None. Returning and empty dictionary.")
|
|
1492
|
+
return Dictionary.ByKeysValues([], [])
|
|
873
1493
|
|
|
874
|
-
|
|
875
|
-
""
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
1494
|
+
if dictionaryA is None:
|
|
1495
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1496
|
+
if not silent:
|
|
1497
|
+
print("Dictionary.SymDif - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
1498
|
+
return None
|
|
1499
|
+
return dictionaryB
|
|
1500
|
+
|
|
1501
|
+
if dictionaryB is None:
|
|
1502
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1503
|
+
if not silent:
|
|
1504
|
+
print("Dictionary.SymDif - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
1505
|
+
return None
|
|
1506
|
+
return dictionaryA
|
|
1507
|
+
|
|
1508
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1509
|
+
if not silent:
|
|
1510
|
+
print("Dictionary.SymDif - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
1511
|
+
return None
|
|
1512
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1513
|
+
if not silent:
|
|
1514
|
+
print("Dictionary.SymDif - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
1515
|
+
return None
|
|
1516
|
+
|
|
1517
|
+
keysA = Dictionary.Keys(dictionaryA) or []
|
|
1518
|
+
keysB = Dictionary.Keys(dictionaryB) or []
|
|
1519
|
+
|
|
1520
|
+
uniqueA = [k for k in keysA if k not in keysB]
|
|
1521
|
+
uniqueB = [k for k in keysB if k not in keysA]
|
|
1522
|
+
|
|
1523
|
+
if len(uniqueA) == 0 and len(uniqueB) == 0:
|
|
1524
|
+
if not silent:
|
|
1525
|
+
print("Dictionary.SymDif - Warning: The input dictionaries have identical keys. Returning and empty dictionary.")
|
|
1526
|
+
return Dictionary.ByKeysValues([], [])
|
|
1527
|
+
|
|
1528
|
+
out_keys = []
|
|
1529
|
+
out_vals = []
|
|
1530
|
+
|
|
1531
|
+
for k in uniqueA:
|
|
1532
|
+
out_keys.append(k)
|
|
1533
|
+
out_vals.append(Dictionary.ValueAtKey(dictionaryA, k))
|
|
1534
|
+
|
|
1535
|
+
for k in uniqueB:
|
|
1536
|
+
out_keys.append(k)
|
|
1537
|
+
out_vals.append(Dictionary.ValueAtKey(dictionaryB, k))
|
|
1538
|
+
|
|
1539
|
+
return Dictionary.ByKeysValues(out_keys, out_vals)
|
|
879
1540
|
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
1541
|
+
@staticmethod
|
|
1542
|
+
def SymmetricDifference(dictionaryA, dictionaryB, silent: bool = False):
|
|
1543
|
+
"""
|
|
1544
|
+
Returns the symmetric difference (XOR) of dictionaryA and dictionaryB, based on keys.
|
|
1545
|
+
|
|
1546
|
+
Procedure
|
|
1547
|
+
---------
|
|
1548
|
+
1. Validate inputs.
|
|
1549
|
+
2. Compute keys that exist in exactly one of the two dictionaries.
|
|
1550
|
+
3. Create a new dictionary containing:
|
|
1551
|
+
- unique keys from dictionaryA with values from dictionaryA
|
|
1552
|
+
- unique keys from dictionaryB with values from dictionaryB
|
|
1553
|
+
|
|
1554
|
+
Parameters
|
|
1555
|
+
----------
|
|
1556
|
+
dictionaryA : topologic_core.Dictionary
|
|
1557
|
+
The first input dictionary.
|
|
1558
|
+
dictionaryB : topologic_core.Dictionary
|
|
1559
|
+
The second input dictionary.
|
|
1560
|
+
silent : bool , optional
|
|
1561
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
|
1562
|
+
|
|
1563
|
+
Returns
|
|
1564
|
+
-------
|
|
1565
|
+
topologic_core.Dictionary
|
|
1566
|
+
The resulting symmetric difference dictionary.
|
|
1567
|
+
|
|
1568
|
+
"""
|
|
1569
|
+
from topologicpy.Topology import Topology
|
|
1570
|
+
|
|
1571
|
+
if dictionaryA is None and dictionaryB is None:
|
|
1572
|
+
if not silent:
|
|
1573
|
+
print("Dictionary.SymmetricDifference - Warning: Both of the input dictionaries are None. Returning and empty dictionary.")
|
|
1574
|
+
return Dictionary.ByKeysValues([], [])
|
|
1575
|
+
|
|
1576
|
+
if dictionaryA is None:
|
|
1577
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1578
|
+
if not silent:
|
|
1579
|
+
print("Dictionary.SymmetricDifference - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
898
1580
|
return None
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
return topologies[0]
|
|
906
|
-
elif is_json_string(temp_value):
|
|
907
|
-
ret_value = json_to_dict(temp_value)
|
|
908
|
-
return ret_value
|
|
909
|
-
else:
|
|
910
|
-
return (temp_value)
|
|
911
|
-
elif isinstance(attr, ListAttribute):
|
|
912
|
-
return (Dictionary.ListAttributeValues(attr))
|
|
913
|
-
elif isinstance(attr, float) or isinstance(attr, int):
|
|
914
|
-
return attr
|
|
915
|
-
elif isinstance(attr, str):
|
|
916
|
-
if attr == "__NONE__":
|
|
1581
|
+
return dictionaryB
|
|
1582
|
+
|
|
1583
|
+
if dictionaryB is None:
|
|
1584
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1585
|
+
if not silent:
|
|
1586
|
+
print("Dictionary.SymmetricDifference - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
917
1587
|
return None
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
return Dictionary.
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
1588
|
+
return dictionaryA
|
|
1589
|
+
|
|
1590
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1591
|
+
if not silent:
|
|
1592
|
+
print("Dictionary.SymmetricDifference - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
1593
|
+
return None
|
|
1594
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1595
|
+
if not silent:
|
|
1596
|
+
print("Dictionary.SymmetricDifference - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
1597
|
+
return None
|
|
1598
|
+
|
|
1599
|
+
keysA = Dictionary.Keys(dictionaryA) or []
|
|
1600
|
+
keysB = Dictionary.Keys(dictionaryB) or []
|
|
1601
|
+
|
|
1602
|
+
uniqueA = [k for k in keysA if k not in keysB]
|
|
1603
|
+
uniqueB = [k for k in keysB if k not in keysA]
|
|
1604
|
+
|
|
1605
|
+
if len(uniqueA) == 0 and len(uniqueB) == 0:
|
|
1606
|
+
if not silent:
|
|
1607
|
+
print("Dictionary.SymmetricDifference - Warning: The input dictionaries have identical keys. Returning and empty dictionary.")
|
|
1608
|
+
return Dictionary.ByKeysValues([], [])
|
|
1609
|
+
|
|
1610
|
+
out_keys = []
|
|
1611
|
+
out_vals = []
|
|
1612
|
+
|
|
1613
|
+
for k in uniqueA:
|
|
1614
|
+
out_keys.append(k)
|
|
1615
|
+
out_vals.append(Dictionary.ValueAtKey(dictionaryA, k))
|
|
1616
|
+
|
|
1617
|
+
for k in uniqueB:
|
|
1618
|
+
out_keys.append(k)
|
|
1619
|
+
out_vals.append(Dictionary.ValueAtKey(dictionaryB, k))
|
|
1620
|
+
|
|
1621
|
+
return Dictionary.ByKeysValues(out_keys, out_vals)
|
|
1622
|
+
|
|
1623
|
+
@staticmethod
|
|
1624
|
+
def Union(dictionaryA, dictionaryB, silent: bool = False):
|
|
1625
|
+
"""
|
|
1626
|
+
Returns the union (merge) of dictionaryA and dictionaryB.
|
|
1627
|
+
|
|
1628
|
+
Procedure
|
|
1629
|
+
---------
|
|
1630
|
+
1. Validate inputs.
|
|
1631
|
+
2. If either input is None, return the other (if valid).
|
|
1632
|
+
3. Return Dictionary.ByMergedDictionaries(dictionaryA, dictionaryB).
|
|
1633
|
+
|
|
1634
|
+
Parameters
|
|
1635
|
+
----------
|
|
1636
|
+
dictionaryA : topologic_core.Dictionary
|
|
1637
|
+
The first input dictionary.
|
|
1638
|
+
dictionaryB : topologic_core.Dictionary
|
|
1639
|
+
The second input dictionary.
|
|
1640
|
+
silent : bool , optional
|
|
1641
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
|
1642
|
+
|
|
1643
|
+
Returns
|
|
1644
|
+
-------
|
|
1645
|
+
topologic_core.Dictionary
|
|
1646
|
+
The resulting union dictionary.
|
|
1647
|
+
|
|
1648
|
+
"""
|
|
1649
|
+
from topologicpy.Topology import Topology
|
|
1650
|
+
|
|
1651
|
+
if dictionaryA is None and dictionaryB is None:
|
|
1652
|
+
if not silent:
|
|
1653
|
+
print("Dictionary.Union - Warning: Both of the input dictionaries are None. Returning None.")
|
|
1654
|
+
return None
|
|
1655
|
+
|
|
1656
|
+
if dictionaryA is None:
|
|
1657
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1658
|
+
if not silent:
|
|
1659
|
+
print("Dictionary.Union - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
1660
|
+
return None
|
|
1661
|
+
return dictionaryB
|
|
1662
|
+
|
|
1663
|
+
if dictionaryB is None:
|
|
1664
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1665
|
+
if not silent:
|
|
1666
|
+
print("Dictionary.Union - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
1667
|
+
return None
|
|
1668
|
+
return dictionaryA
|
|
1669
|
+
|
|
1670
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1671
|
+
if not silent:
|
|
1672
|
+
print("Dictionary.Union - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
1673
|
+
return None
|
|
1674
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1675
|
+
if not silent:
|
|
1676
|
+
print("Dictionary.Union - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
942
1677
|
return None
|
|
1678
|
+
|
|
1679
|
+
return Dictionary.ByMergedDictionaries(dictionaryA, dictionaryB)
|
|
943
1680
|
|
|
944
1681
|
@staticmethod
|
|
945
1682
|
def ValueAtKey(dictionary, key, defaultValue=None, silent=False):
|
|
@@ -1023,7 +1760,7 @@ class Dictionary():
|
|
|
1023
1760
|
return None
|
|
1024
1761
|
returnList.append(attr)
|
|
1025
1762
|
return returnList
|
|
1026
|
-
|
|
1763
|
+
|
|
1027
1764
|
@staticmethod
|
|
1028
1765
|
def ValuesAtKeys(dictionary, keys, defaultValue=None, silent: bool = False):
|
|
1029
1766
|
"""
|
|
@@ -1067,5 +1804,86 @@ class Dictionary():
|
|
|
1067
1804
|
print("Dictionary.ValuesAtKeys - Error: The input keys parameter contains invalid values. Returning None.")
|
|
1068
1805
|
return None
|
|
1069
1806
|
return [Dictionary.ValueAtKey(dictionary, key, defaultValue=defaultValue, silent=silent) for key in keys]
|
|
1070
|
-
|
|
1807
|
+
|
|
1808
|
+
@staticmethod
|
|
1809
|
+
def XOR(dictionaryA, dictionaryB, silent: bool = False):
|
|
1810
|
+
"""
|
|
1811
|
+
Returns the XOR (symmetric difference) of dictionaryA and dictionaryB, based on keys.
|
|
1812
|
+
|
|
1813
|
+
Procedure
|
|
1814
|
+
---------
|
|
1815
|
+
1. Validate inputs.
|
|
1816
|
+
2. Compute keys that exist in exactly one of the two dictionaries.
|
|
1817
|
+
3. Create a new dictionary containing:
|
|
1818
|
+
- unique keys from dictionaryA with values from dictionaryA
|
|
1819
|
+
- unique keys from dictionaryB with values from dictionaryB
|
|
1820
|
+
|
|
1821
|
+
Parameters
|
|
1822
|
+
----------
|
|
1823
|
+
dictionaryA : topologic_core.Dictionary
|
|
1824
|
+
The first input dictionary.
|
|
1825
|
+
dictionaryB : topologic_core.Dictionary
|
|
1826
|
+
The second input dictionary.
|
|
1827
|
+
silent : bool , optional
|
|
1828
|
+
If set to True, error and warning messages are suppressed. Default is False.
|
|
1829
|
+
|
|
1830
|
+
Returns
|
|
1831
|
+
-------
|
|
1832
|
+
topologic_core.Dictionary
|
|
1833
|
+
The resulting XOR (symmetric difference) dictionary.
|
|
1834
|
+
|
|
1835
|
+
"""
|
|
1836
|
+
from topologicpy.Topology import Topology
|
|
1837
|
+
|
|
1838
|
+
if dictionaryA is None and dictionaryB is None:
|
|
1839
|
+
if not silent:
|
|
1840
|
+
print("Dictionary.XOR - Warning: Both of the input dictionaries are None. Returning and empty dictionary.")
|
|
1841
|
+
return Dictionary.ByKeysValues([], [])
|
|
1842
|
+
|
|
1843
|
+
if dictionaryA is None:
|
|
1844
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1845
|
+
if not silent:
|
|
1846
|
+
print("Dictionary.XOR - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
1847
|
+
return None
|
|
1848
|
+
return dictionaryB
|
|
1849
|
+
|
|
1850
|
+
if dictionaryB is None:
|
|
1851
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1852
|
+
if not silent:
|
|
1853
|
+
print("Dictionary.XOR - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
1854
|
+
return None
|
|
1855
|
+
return dictionaryA
|
|
1856
|
+
|
|
1857
|
+
if not Topology.IsInstance(dictionaryA, "Dictionary"):
|
|
1858
|
+
if not silent:
|
|
1859
|
+
print("Dictionary.XOR - Error: the dictionaryA input parameter is not a valid dictionary. Returning None.")
|
|
1860
|
+
return None
|
|
1861
|
+
if not Topology.IsInstance(dictionaryB, "Dictionary"):
|
|
1862
|
+
if not silent:
|
|
1863
|
+
print("Dictionary.XOR - Error: the dictionaryB input parameter is not a valid dictionary. Returning None.")
|
|
1864
|
+
return None
|
|
1865
|
+
|
|
1866
|
+
keysA = Dictionary.Keys(dictionaryA) or []
|
|
1867
|
+
keysB = Dictionary.Keys(dictionaryB) or []
|
|
1868
|
+
|
|
1869
|
+
uniqueA = [k for k in keysA if k not in keysB]
|
|
1870
|
+
uniqueB = [k for k in keysB if k not in keysA]
|
|
1871
|
+
|
|
1872
|
+
if len(uniqueA) == 0 and len(uniqueB) == 0:
|
|
1873
|
+
if not silent:
|
|
1874
|
+
print("Dictionary.XOR - Warning: The input dictionaries have identical keys. Returning and empty dictionary.")
|
|
1875
|
+
return Dictionary.ByKeysValues([], [])
|
|
1876
|
+
|
|
1877
|
+
out_keys = []
|
|
1878
|
+
out_vals = []
|
|
1879
|
+
|
|
1880
|
+
for k in uniqueA:
|
|
1881
|
+
out_keys.append(k)
|
|
1882
|
+
out_vals.append(Dictionary.ValueAtKey(dictionaryA, k))
|
|
1883
|
+
|
|
1884
|
+
for k in uniqueB:
|
|
1885
|
+
out_keys.append(k)
|
|
1886
|
+
out_vals.append(Dictionary.ValueAtKey(dictionaryB, k))
|
|
1887
|
+
|
|
1888
|
+
return Dictionary.ByKeysValues(out_keys, out_vals)
|
|
1071
1889
|
|