Reputation: 45
I have two sets of nodes. Node set A contains a list of node ID and the node XYZ coordinates, ex: (ID: int, [x: float, y: float, z: float]). Node set B contains a node temperature and the nodes XYZ coordinates. All of the nodes in set A should (but not necessarily) be found in set B but set B can also contain additional nodes. I need to match the nodes in set A to their corresponding nodes in set B based on their coordinates. The main issue being that their coordinates are not exact matches (float errors exist).
The solution should preferably avoid non standard libraries. I have coded what I believe would not be the best solution to the problem. I've attempted to create a dict containing set B. The keys consists of a tuple containing truncated coordinates with the temperatures being the values. I then use truncated set A coordinates to query the dict. I am wondering if there is a more elegant and accurate way of going about the problem?
Upvotes: 1
Views: 704
Reputation: 10912
You can probably make use of math.isclose
, it requires a bit of tuning depending on your inputs (carefully selecting rel_tol
and abs_tol
based on your use case).
Any many cases default values will do:
import itertools
import math
def matching_temperatures(A, B):
temperatures = dict()
for a, b in itertools.product(A, B):
a_id, a_xyz = a
b_temp, b_xyz = b
if all(math.isclose(i, j) for i, j in zip(a_xyz, b_xyz)):
temperatures[a_id] = b_temp
return temperatures
# Let's say our coordinates have the following error margin:
epsilon = 1e-9
A = (
('a', (3.3, 2.2, 1.1)),
('b', (10.1, 20.2, 30.3))
)
# Same coordinates as A with a ±epsilon error:
B = (
('1°c', (3.3+epsilon, 2.2-epsilon, 1.1+epsilon)),
('2°c', (10.1-epsilon, 20.2+epsilon, 30.3+epsilon))
)
print(matching_temperatures(A, B))
In this particular example, this will print {'a': '1°c', 'b': '2°c'}
.
But in some cases (for example your errors are greater than the default rel_tol
of 1e-9
) then you will need to specify this: math.isclose(i, j, rel_tol=your_epsilon)
.
Upvotes: 2