5
Copyright 2014-2016 Andreas Würl
7
Licensed under the Apache License, Version 2.0 (the "License");
8
you may not use this file except in compliance with the License.
9
You may obtain a copy of the License at
11
http://www.apache.org/licenses/LICENSE-2.0
13
Unless required by applicable law or agreed to in writing, software
14
distributed under the License is distributed on an "AS IS" BASIS,
15
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
See the License for the specific language governing permissions and
17
limitations under the License.
26
from mock import MagicMock, call
28
import blitzortung.builder
30
import blitzortung.calc
31
import blitzortung.types
34
class TestSignalVelocity(unittest.TestCase):
36
self.signal_velocity = blitzortung.calc.SignalVelocity()
38
def test_get_distance_time(self):
39
self.assertAlmostEqual(33440, self.signal_velocity.get_distance_time(10000.0))
41
def test_get_time_distance(self):
42
self.assertAlmostEqual(29.90429768, self.signal_velocity.get_time_distance(100))
45
class ThreePointSolutionTest(unittest.TestCase):
47
self.timestamp = datetime.datetime.utcnow()
48
event_builder = blitzortung.builder.Event()
49
event_builder.set_x(11.0)
50
event_builder.set_y(49.0)
51
event_builder.set_timestamp(self.timestamp)
52
self.center_event = event_builder.build()
53
self.radians_factor = math.pi / 180
54
self.signal_velocity = blitzortung.calc.SignalVelocity()
56
def test_get_solution_location(self):
57
solution = blitzortung.calc.ThreePointSolution(self.center_event, 0, 100000, self.signal_velocity)
59
self.assertAlmostEqual(solution.x, 11)
60
self.assertAlmostEqual(solution.y, 49.89913151)
62
solution = blitzortung.calc.ThreePointSolution(self.center_event, math.pi / 2, 100000, self.signal_velocity)
64
self.assertAlmostEqual(solution.x, 12.3664992)
65
self.assertAlmostEqual(solution.y, 48.9919072)
67
def test_get_solution_timestamp(self):
68
solution = blitzortung.calc.ThreePointSolution(self.center_event, 0, 100000, self.signal_velocity)
70
timestamp = self.center_event.timestamp
71
total_nanoseconds = timestamp.value - self.signal_velocity.get_distance_time(100000)
72
strike_timestamp = pd.Timestamp(total_nanoseconds, tz=timestamp.tzinfo)
74
self.assertEqual(strike_timestamp, solution.timestamp)
77
class ThreePointSolverTest(unittest.TestCase):
79
self.signal_velocity = blitzortung.calc.SignalVelocity()
80
self.prepare_solution(11.5, 49.5)
82
def prepare_solution(self, x_coord, y_coord):
83
self.simulated_data = blitzortung.calc.SimulatedData(x_coord, y_coord)
84
self.center_event = self.simulated_data.get_event_at(11.0, 49.0)
85
self.event_1 = self.simulated_data.get_event_at(12.0, 49.0)
86
self.event_2 = self.simulated_data.get_event_at(11.0, 50.0)
88
self.events = [self.center_event, self.event_1, self.event_2]
90
def test_solve_with_no_solution(self):
91
self.prepare_solution(11.5, 49.0)
92
self.event_1 = self.simulated_data.get_event_at(10.0, 49.0)
93
self.event_2 = self.simulated_data.get_event_at(12.0, 49.0)
95
self.events = [self.center_event, self.event_1, self.event_2]
97
solver = blitzortung.calc.ThreePointSolver(self.events)
99
solutions = solver.solutions
101
self.assertEqual(0, len(solutions))
103
def test_solve_with_one_solution(self):
104
location = blitzortung.types.Point(11.7, 49.3)
105
self.prepare_solution(location.x, location.y)
107
solver = blitzortung.calc.ThreePointSolver(self.events)
109
solutions = solver.solutions
111
self.assertEqual(1, len(solutions))
112
self.assertEqual(location, solutions[0])
114
def test_solve_with_two_solutions(self):
115
location = blitzortung.types.Point(11.1, 49.1)
116
self.prepare_solution(location.x, location.y)
118
solver = blitzortung.calc.ThreePointSolver(self.events)
120
solutions = solver.solutions
122
self.assertEqual(2, len(solutions))
124
self.assertEqual(location, solutions[0])
126
self.assertNotEqual(0.0, location.distance_to(solutions[1]))
128
def test_get_solution_for_event_list(self):
129
location = blitzortung.types.Point(11.1, 49.1)
130
self.prepare_solution(location.x, location.y)
132
solver = blitzortung.calc.ThreePointSolver(self.events)
134
self.assertEqual(2, len(solver.solutions))
136
solution = solver.get_solution()
138
self.assertAlmostEqual(11.1, solution.x, 5)
139
self.assertAlmostEqual(49.1, solution.y, 5)
141
def test_azimuth_to_angle(self):
142
solver = blitzortung.calc.ThreePointSolver(self.events)
144
self.assertAlmostEqual(math.pi / 2, solver.azimuth_to_angle(0))
145
self.assertAlmostEqual(0, solver.azimuth_to_angle(math.pi / 2))
146
self.assertAlmostEqual(math.pi, solver.azimuth_to_angle(-math.pi / 2))
148
def test_angle_to_azimuth(self):
149
solver = blitzortung.calc.ThreePointSolver(self.events)
151
self.assertAlmostEqual(math.pi / 2, solver.angle_to_azimuth(0))
152
self.assertAlmostEqual(0, solver.angle_to_azimuth(math.pi / 2))
153
self.assertAlmostEqual(-math.pi / 2, solver.angle_to_azimuth(math.pi))
156
class TestFitSeed(unittest.TestCase):
158
self.signal_velocity = blitzortung.calc.SignalVelocity()
160
def generic_combination(self, events, expected_args):
161
fit_seed = blitzortung.calc.FitSeed(events, self.signal_velocity)
162
fit_seed.find_three_point_solution = MagicMock()
164
fit_seed.get_seed_event()
166
self.assertEqual(len(expected_args), len(fit_seed.find_three_point_solution.mock_calls))
168
expected = [call.find_three_point_solution(arg) for arg in expected_args]
169
self.assertTrue(expected == fit_seed.find_three_point_solution.mock_calls)
171
def test_combinations_with_6_events(self):
172
events = [1, 2, 3, 4, 5, 6]
173
expected_args = [[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], [1, 4, 5]]
174
self.generic_combination(events, expected_args)
176
def test_combinations_with_5_events(self):
177
events = [1, 2, 3, 4, 5]
178
expected_args = [[1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], [1, 4, 5]]
179
self.generic_combination(events, expected_args)
181
def test_combinations_with_4_events(self):
182
events = [1, 2, 3, 4]
183
expected_args = [[1, 2, 3], [1, 2, 4], [1, 3, 4]]
184
self.generic_combination(events, expected_args)
186
def test_combinations_with_3_events(self):
188
expected_args = [[1, 2, 3]]
189
self.generic_combination(events, expected_args)
191
def test_combinations_with_2_events(self):
194
self.generic_combination(events, expected_args)
197
class TestLeastSquareFit(unittest.TestCase):
199
self.strike_location = blitzortung.types.Point(11.3, 49.5)
201
self.simulated_data = blitzortung.calc.SimulatedData(self.strike_location)
202
self.source_event = self.simulated_data.get_source_event()
204
self.timestamp = self.simulated_data.get_timestamp()
206
event_builder = blitzortung.builder.Event()
207
event_builder.set_timestamp(self.timestamp)
208
event_builder.set_x(11.4)
209
event_builder.set_y(49.4)
210
self.three_point_solution = event_builder.build()
213
self.events.append(self.simulated_data.get_event_at(11.0, 50.0))
214
self.events.append(self.simulated_data.get_event_at(11.0, 49.0))
215
self.events.append(self.simulated_data.get_event_at(12.0, 49.0))
216
self.events.append(self.simulated_data.get_event_at(12.0, 50.0))
218
self.fit = blitzortung.calc.LeastSquareFit(self.three_point_solution, self.events,
219
blitzortung.calc.SignalVelocity())
221
def test_get_parameter(self):
222
self.assertAlmostEqual(11.4, self.fit.get_parameter(blitzortung.calc.FitParameter.Longitude))
223
self.assertAlmostEqual(49.4, self.fit.get_parameter(blitzortung.calc.FitParameter.Latitude))
224
self.assertAlmostEquals(-199.525, self.fit.get_parameter(blitzortung.calc.FitParameter.Time))
226
def test_get_location(self):
227
self.assertEquals(11.4, self.fit.get_location().x)
228
self.assertEquals(49.4, self.fit.get_location().y)
230
def test_calculate_time_value(self):
231
self.assertEqual(-199.525, self.fit.calculate_time_value(self.timestamp))
232
self.assertEqual(0.0, self.fit.calculate_time_value(self.events[0].timestamp))
234
def test_calculate_residual_time(self):
235
self.assertAlmostEqual(-43.601, self.fit.get_residual_time_at(self.events[0]))
237
def test_leastsquare_fit(self):
238
# for event in self.events:
239
# print event, "%.1f %.3f" % (self.source_event.distance_to(event)/1000.0, self.source_event.ns_difference_to(event)/1000.0)
241
#for parameter_value in self.fit.parameters.items():
242
# print parameter_value
244
while self.fit.requires_another_iteration():
245
self.fit.perform_fit_step()
247
parameter_string = ["%.3f" % self.fit.parameters[index] for index in range(0, len(self.fit.parameters))]
248
print("%.1f, %.3f %s" % (
249
self.fit.get_least_square_sum(), self.fit.get_least_square_change(), ' '.join(parameter_string)))
251
strike_location = self.fit.get_location()
252
self.assertAlmostEqual(11.3, strike_location.x, 4)
253
self.assertAlmostEqual(49.5, strike_location.y, 4)