ObjectNat 1.1.0__py3-none-any.whl → 1.2.1__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.

Potentially problematic release.


This version of ObjectNat might be problematic. Click here for more details.

Files changed (35) hide show
  1. objectnat/__init__.py +9 -13
  2. objectnat/_api.py +14 -13
  3. objectnat/_config.py +47 -47
  4. objectnat/_version.py +1 -1
  5. objectnat/methods/coverage_zones/__init__.py +3 -3
  6. objectnat/methods/coverage_zones/graph_coverage.py +98 -108
  7. objectnat/methods/coverage_zones/radius_voronoi_coverage.py +37 -45
  8. objectnat/methods/coverage_zones/stepped_coverage.py +126 -142
  9. objectnat/methods/isochrones/__init__.py +1 -1
  10. objectnat/methods/isochrones/isochrone_utils.py +167 -167
  11. objectnat/methods/isochrones/isochrones.py +262 -299
  12. objectnat/methods/noise/__init__.py +3 -3
  13. objectnat/methods/noise/noise_init_data.py +10 -10
  14. objectnat/methods/noise/noise_reduce.py +155 -155
  15. objectnat/methods/noise/{noise_sim.py → noise_simulation.py} +452 -448
  16. objectnat/methods/noise/noise_simulation_simplified.py +209 -0
  17. objectnat/methods/point_clustering/__init__.py +1 -1
  18. objectnat/methods/point_clustering/cluster_points_in_polygons.py +115 -116
  19. objectnat/methods/provision/__init__.py +1 -1
  20. objectnat/methods/provision/provision.py +117 -110
  21. objectnat/methods/provision/provision_exceptions.py +59 -59
  22. objectnat/methods/provision/provision_model.py +337 -337
  23. objectnat/methods/utils/__init__.py +1 -0
  24. objectnat/methods/utils/geom_utils.py +173 -130
  25. objectnat/methods/utils/graph_utils.py +306 -206
  26. objectnat/methods/utils/math_utils.py +32 -32
  27. objectnat/methods/visibility/__init__.py +6 -6
  28. objectnat/methods/visibility/visibility_analysis.py +470 -511
  29. {objectnat-1.1.0.dist-info → objectnat-1.2.1.dist-info}/LICENSE.txt +28 -28
  30. objectnat-1.2.1.dist-info/METADATA +115 -0
  31. objectnat-1.2.1.dist-info/RECORD +33 -0
  32. objectnat/methods/noise/noise_exceptions.py +0 -14
  33. objectnat-1.1.0.dist-info/METADATA +0 -148
  34. objectnat-1.1.0.dist-info/RECORD +0 -33
  35. {objectnat-1.1.0.dist-info → objectnat-1.2.1.dist-info}/WHEEL +0 -0
@@ -1,155 +1,155 @@
1
- import numpy as np
2
- from scipy.optimize import fsolve
3
-
4
- from objectnat import config
5
-
6
- from .noise_init_data import air_resist_ratio
7
-
8
- logger = config.logger
9
-
10
-
11
- def get_air_resist_ratio(temp, freq, check_temp_freq=False):
12
- if check_temp_freq:
13
- if temp > max(air_resist_ratio.columns) or temp < min(air_resist_ratio.columns):
14
- logger.warning(
15
- f"The specified temperature of {temp}°C is outside the tabulated data range. "
16
- f"The air resistance coefficient for these values may be inaccurate. "
17
- f"Recommended temperature range: {min(air_resist_ratio.columns)}°C "
18
- f"to {max(air_resist_ratio.columns)}°C."
19
- )
20
-
21
- if freq > max(air_resist_ratio.index) or freq < min(air_resist_ratio.index):
22
- logger.warning(
23
- f"The specified geometric mean frequency of {freq} Hz is outside the tabulated data range."
24
- f" The air resistance coefficient for these values may be inaccurate."
25
- f" Recommended frequency range: {min(air_resist_ratio.index)} Hz to {max(air_resist_ratio.index)} Hz."
26
- )
27
-
28
- def get_nearest_values(array, value):
29
- sorted_array = sorted(array)
30
- if value in sorted_array:
31
- return [value]
32
- if value > max(sorted_array):
33
- return [sorted_array[-1]]
34
- if value < min(sorted_array):
35
- return [sorted_array[0]]
36
-
37
- for i, val in enumerate(sorted_array):
38
- if value < val:
39
- return sorted_array[max(i - 1, 0)], sorted_array[i]
40
- return sorted_array[-2], sorted_array[-1]
41
-
42
- nearest_temp = get_nearest_values(air_resist_ratio.columns, temp)
43
- nearest_freq = get_nearest_values(air_resist_ratio.index, freq)
44
-
45
- if len(nearest_temp) == 1 and len(nearest_freq) == 1:
46
- return air_resist_ratio.loc[nearest_freq[0], nearest_temp[0]]
47
-
48
- if len(nearest_temp) == 2 and len(nearest_freq) == 2:
49
- freq1, freq2 = nearest_freq
50
- temp1, temp2 = nearest_temp
51
-
52
- coef_temp1_freq1 = air_resist_ratio.loc[freq1, temp1]
53
- coef_temp1_freq2 = air_resist_ratio.loc[freq2, temp1]
54
- coef_temp2_freq1 = air_resist_ratio.loc[freq1, temp2]
55
- coef_temp2_freq2 = air_resist_ratio.loc[freq2, temp2]
56
-
57
- weight_temp1 = (temp2 - temp) / (temp2 - temp1)
58
- weight_temp2 = (temp - temp1) / (temp2 - temp1)
59
- weight_freq1 = (freq2 - freq) / (freq2 - freq1)
60
- weight_freq2 = (freq - freq1) / (freq2 - freq1)
61
-
62
- coef_freq1 = coef_temp1_freq1 * weight_temp1 + coef_temp2_freq1 * weight_temp2
63
- coef_freq2 = coef_temp1_freq2 * weight_temp1 + coef_temp2_freq2 * weight_temp2
64
-
65
- final_coef = coef_freq1 * weight_freq1 + coef_freq2 * weight_freq2
66
-
67
- return final_coef
68
-
69
- if len(nearest_temp) == 2 and len(nearest_freq) == 1:
70
- temp1, temp2 = nearest_temp
71
- freq1 = nearest_freq[0]
72
-
73
- coef_temp1 = air_resist_ratio.loc[freq1, temp1]
74
- coef_temp2 = air_resist_ratio.loc[freq1, temp2]
75
-
76
- weight_temp1 = (temp2 - temp) / (temp2 - temp1)
77
- weight_temp2 = (temp - temp1) / (temp2 - temp1)
78
-
79
- return coef_temp1 * weight_temp1 + coef_temp2 * weight_temp2
80
-
81
- if len(nearest_temp) == 1 and len(nearest_freq) == 2:
82
- temp1 = nearest_temp[0]
83
- freq1, freq2 = nearest_freq
84
-
85
- coef_freq1 = air_resist_ratio.loc[freq1, temp1]
86
- coef_freq2 = air_resist_ratio.loc[freq2, temp1]
87
-
88
- weight_freq1 = (freq2 - freq) / (freq2 - freq1)
89
- weight_freq2 = (freq - freq1) / (freq2 - freq1)
90
-
91
- return coef_freq1 * weight_freq1 + coef_freq2 * weight_freq2
92
-
93
-
94
- def dist_to_target_db(
95
- init_noise_db, target_noise_db, geometric_mean_freq_hz, air_temperature, return_desc=False, check_temp_freq=False
96
- ) -> float | str:
97
- """
98
- Calculates the distance required for a sound wave to decay from an initial noise level to a target noise level,
99
- based on the geometric mean frequency of the sound and the air temperature. Optionally, can return a description
100
- of the sound propagation behavior.
101
-
102
- Args:
103
- init_noise_db (float): The initial noise level of the source in decibels (dB). This is the starting sound
104
- intensity.
105
- target_noise_db (float): The target noise level in decibels (dB), representing the level to which the sound
106
- decays over distance.
107
- geometric_mean_freq_hz (float): The geometric mean frequency of the sound (in Hz). This frequency influences
108
- the attenuation of sound over distance. Higher frequencies decay faster than lower ones.
109
- air_temperature (float): The temperature of the air in degrees Celsius. This influences the air's resistance
110
- to sound propagation.
111
- return_desc (bool, optional): If set to `True`, the function will return a description of the sound decay
112
- process instead of the calculated distance.
113
- check_temp_freq (bool, optional): If `True`, the function will check whether the temperature and frequency
114
- are within valid ranges.
115
-
116
- Returns:
117
- float or str: If `return_desc` is `False`, the function returns the distance (in meters) over which the sound
118
- decays from `init_noise_db` to `target_noise_db`. If `return_desc` is `True`, a descriptive string is returned
119
- explaining the calculation and the conditions.
120
- """
121
-
122
- def equation(r):
123
- return l - l_ist + 20 * np.log10(r) + k * r
124
-
125
- l_ist = init_noise_db
126
- l = target_noise_db
127
- k = get_air_resist_ratio(air_temperature, geometric_mean_freq_hz, check_temp_freq)
128
- initial_guess = 1
129
- r_solution = fsolve(equation, initial_guess)
130
- if return_desc:
131
- string = (
132
- f"Noise level of {init_noise_db} dB "
133
- f"with a geometric mean frequency of {geometric_mean_freq_hz} Hz "
134
- f"at an air temperature of {air_temperature}°C decays to {target_noise_db} dB "
135
- f"over a distance of {r_solution[0]} meters. Air resistance coefficient: {k}."
136
- )
137
- return string
138
- return r_solution[0]
139
-
140
-
141
- def green_noise_reduce_db(geometric_mean_freq_hz, r_tree) -> float:
142
- """
143
- Calculates the amount of noise reduction (in dB) provided by vegetation of a given thickness at a specified
144
- geometric mean frequency. The function models the reduction based on the interaction of the sound with trees or
145
- vegetation.
146
-
147
- Args:
148
- geometric_mean_freq_hz (float): The geometric mean frequency of the sound (in Hz).
149
- r_tree (float): The thickness or density of the vegetation (in meters).
150
-
151
- Returns:
152
- float: The noise reduction (in dB) achieved by the vegetation. This value indicates how much quieter the sound
153
- will be after passing through or interacting with the vegetation of the specified thickness.
154
- """
155
- return round(0.08 * r_tree * ((geometric_mean_freq_hz ** (1 / 3)) / 8), 1)
1
+ import numpy as np
2
+ from scipy.optimize import fsolve
3
+
4
+ from objectnat import config
5
+
6
+ from .noise_init_data import air_resist_ratio
7
+
8
+ logger = config.logger
9
+
10
+
11
+ def get_air_resist_ratio(temp, freq, check_temp_freq=False):
12
+ if check_temp_freq:
13
+ if temp > max(air_resist_ratio.columns) or temp < min(air_resist_ratio.columns):
14
+ logger.warning(
15
+ f"The specified temperature of {temp}°C is outside the tabulated data range. "
16
+ f"The air resistance coefficient for these values may be inaccurate. "
17
+ f"Recommended temperature range: {min(air_resist_ratio.columns)}°C "
18
+ f"to {max(air_resist_ratio.columns)}°C."
19
+ )
20
+
21
+ if freq > max(air_resist_ratio.index) or freq < min(air_resist_ratio.index):
22
+ logger.warning(
23
+ f"The specified geometric mean frequency of {freq} Hz is outside the tabulated data range."
24
+ f" The air resistance coefficient for these values may be inaccurate."
25
+ f" Recommended frequency range: {min(air_resist_ratio.index)} Hz to {max(air_resist_ratio.index)} Hz."
26
+ )
27
+
28
+ def get_nearest_values(array, value):
29
+ sorted_array = sorted(array)
30
+ if value in sorted_array:
31
+ return [value]
32
+ if value > max(sorted_array):
33
+ return [sorted_array[-1]]
34
+ if value < min(sorted_array):
35
+ return [sorted_array[0]]
36
+
37
+ for i, val in enumerate(sorted_array):
38
+ if value < val:
39
+ return sorted_array[max(i - 1, 0)], sorted_array[i]
40
+ return sorted_array[-2], sorted_array[-1]
41
+
42
+ nearest_temp = get_nearest_values(air_resist_ratio.columns, temp)
43
+ nearest_freq = get_nearest_values(air_resist_ratio.index, freq)
44
+
45
+ if len(nearest_temp) == 1 and len(nearest_freq) == 1:
46
+ return air_resist_ratio.loc[nearest_freq[0], nearest_temp[0]]
47
+
48
+ if len(nearest_temp) == 2 and len(nearest_freq) == 2:
49
+ freq1, freq2 = nearest_freq
50
+ temp1, temp2 = nearest_temp
51
+
52
+ coef_temp1_freq1 = air_resist_ratio.loc[freq1, temp1]
53
+ coef_temp1_freq2 = air_resist_ratio.loc[freq2, temp1]
54
+ coef_temp2_freq1 = air_resist_ratio.loc[freq1, temp2]
55
+ coef_temp2_freq2 = air_resist_ratio.loc[freq2, temp2]
56
+
57
+ weight_temp1 = (temp2 - temp) / (temp2 - temp1)
58
+ weight_temp2 = (temp - temp1) / (temp2 - temp1)
59
+ weight_freq1 = (freq2 - freq) / (freq2 - freq1)
60
+ weight_freq2 = (freq - freq1) / (freq2 - freq1)
61
+
62
+ coef_freq1 = coef_temp1_freq1 * weight_temp1 + coef_temp2_freq1 * weight_temp2
63
+ coef_freq2 = coef_temp1_freq2 * weight_temp1 + coef_temp2_freq2 * weight_temp2
64
+
65
+ final_coef = coef_freq1 * weight_freq1 + coef_freq2 * weight_freq2
66
+
67
+ return final_coef
68
+
69
+ if len(nearest_temp) == 2 and len(nearest_freq) == 1:
70
+ temp1, temp2 = nearest_temp
71
+ freq1 = nearest_freq[0]
72
+
73
+ coef_temp1 = air_resist_ratio.loc[freq1, temp1]
74
+ coef_temp2 = air_resist_ratio.loc[freq1, temp2]
75
+
76
+ weight_temp1 = (temp2 - temp) / (temp2 - temp1)
77
+ weight_temp2 = (temp - temp1) / (temp2 - temp1)
78
+
79
+ return coef_temp1 * weight_temp1 + coef_temp2 * weight_temp2
80
+
81
+ if len(nearest_temp) == 1 and len(nearest_freq) == 2:
82
+ temp1 = nearest_temp[0]
83
+ freq1, freq2 = nearest_freq
84
+
85
+ coef_freq1 = air_resist_ratio.loc[freq1, temp1]
86
+ coef_freq2 = air_resist_ratio.loc[freq2, temp1]
87
+
88
+ weight_freq1 = (freq2 - freq) / (freq2 - freq1)
89
+ weight_freq2 = (freq - freq1) / (freq2 - freq1)
90
+
91
+ return coef_freq1 * weight_freq1 + coef_freq2 * weight_freq2
92
+
93
+
94
+ def dist_to_target_db(
95
+ init_noise_db, target_noise_db, geometric_mean_freq_hz, air_temperature, return_desc=False, check_temp_freq=False
96
+ ) -> float | str:
97
+ """
98
+ Calculates the distance required for a sound wave to decay from an initial noise level to a target noise level,
99
+ based on the geometric mean frequency of the sound and the air temperature. Optionally, can return a description
100
+ of the sound propagation behavior.
101
+
102
+ Args:
103
+ init_noise_db (float): The initial noise level of the source in decibels (dB). This is the starting sound
104
+ intensity.
105
+ target_noise_db (float): The target noise level in decibels (dB), representing the level to which the sound
106
+ decays over distance.
107
+ geometric_mean_freq_hz (float): The geometric mean frequency of the sound (in Hz). This frequency influences
108
+ the attenuation of sound over distance. Higher frequencies decay faster than lower ones.
109
+ air_temperature (float): The temperature of the air in degrees Celsius. This influences the air's resistance
110
+ to sound propagation.
111
+ return_desc (bool, optional): If set to `True`, the function will return a description of the sound decay
112
+ process instead of the calculated distance.
113
+ check_temp_freq (bool, optional): If `True`, the function will check whether the temperature and frequency
114
+ are within valid ranges.
115
+
116
+ Returns:
117
+ float or str: If `return_desc` is `False`, the function returns the distance (in meters) over which the sound
118
+ decays from `init_noise_db` to `target_noise_db`. If `return_desc` is `True`, a descriptive string is returned
119
+ explaining the calculation and the conditions.
120
+ """
121
+
122
+ def equation(r):
123
+ return l - l_ist + 20 * np.log10(r) + k * r
124
+
125
+ l_ist = init_noise_db
126
+ l = target_noise_db
127
+ k = get_air_resist_ratio(air_temperature, geometric_mean_freq_hz, check_temp_freq)
128
+ initial_guess = 1
129
+ r_solution = fsolve(equation, initial_guess)
130
+ if return_desc:
131
+ string = (
132
+ f"Noise level of {init_noise_db} dB "
133
+ f"with a geometric mean frequency of {geometric_mean_freq_hz} Hz "
134
+ f"at an air temperature of {air_temperature}°C decays to {target_noise_db} dB "
135
+ f"over a distance of {r_solution[0]} meters. Air resistance coefficient: {k}."
136
+ )
137
+ return string
138
+ return r_solution[0]
139
+
140
+
141
+ def green_noise_reduce_db(geometric_mean_freq_hz, r_tree) -> float:
142
+ """
143
+ Calculates the amount of noise reduction (in dB) provided by vegetation of a given thickness at a specified
144
+ geometric mean frequency. The function models the reduction based on the interaction of the sound with trees or
145
+ vegetation.
146
+
147
+ Args:
148
+ geometric_mean_freq_hz (float): The geometric mean frequency of the sound (in Hz).
149
+ r_tree (float): The thickness or density of the vegetation (in meters).
150
+
151
+ Returns:
152
+ float: The noise reduction (in dB) achieved by the vegetation. This value indicates how much quieter the sound
153
+ will be after passing through or interacting with the vegetation of the specified thickness.
154
+ """
155
+ return round(0.08 * r_tree * ((geometric_mean_freq_hz ** (1 / 3)) / 8), 1)