def test_geodetic(self): ecef = ECEF(x=6378137, y=0, z=0) geod = Geodetic(ecef, reference="ELLIPSOID") ecef1 = geod.geodetic_to_ecef() geod1 = ecef.ecef_to_geodetic(reference="ELLIPSOID") horz = geod.geodetic_to_horizontal() grnd = geod.geodetic_to_grandcs() ltpf = LTP(location=self.location, orientation="NWU") ltp = geod.geodetic_to_ltp(ltpf) # Check the method transformation self.assertQuantity(geod, self.location, 6) self.assertQuantity(geod1, self.location, 6) self.assertQuantity(ecef, ecef1, 6) self.assertCartesian(ecef, ecef1, 6) # RK TODO: Add more test. self.assertEqual(geod.reference, "ELLIPSOID") self.assertQuantity(ltp.location, ecef) # check input value is either number or array of numbers. with self.assertRaises(TypeError) as context: Geodetic(azimuth="zero", elevation=0, norm=0) # check input argument is of knonw coordinate system. with self.assertRaises(TypeError) as context: Geodetic(numpy.ones(10))
def test_zhaires(self): path = self.get_data("zhaires") shower = ShowerEvent.load(path) self.assertIsInstance(shower.frame, LTP) self.assertIsNotNone(shower.geomagnet) self.assertAlmostEqual(numpy.linalg.norm(shower.geomagnet), 0.054021) spherical = SphericalRepresentation(shower.geomagnet) self.assertQuantity(spherical.theta, numpy.array([147.43])) self.assertIsNotNone(shower.core) self.assertIsNotNone(shower.maximum) self.assertEqual(shower.frame.declination, 0.72) shower = ZhairesShower.load(path) shower.dump(self.path) tmp = shower.load(self.path) a, b = shower.fields[9], tmp.fields[9] self.assertField(a, b) frame = shower.shower_frame() ev = shower.core - shower.maximum ev /= numpy.linalg.norm(ev) ev = ev.T[0] evB = numpy.cross(ev, shower.geomagnet.T[0]) evB /= numpy.linalg.norm(evB) evvB = numpy.cross(ev, evB) # evB is already transposed. evB = LTP(x=evB[0], y=evB[1], z=evB[2], frame=shower.frame) evB = evB.ltp_to_ltp(frame) self.assertArray(evB, numpy.array((1, 0, 0)), 7) evvB = LTP(x=evvB[0], y=evvB[1], z=evvB[2], frame=shower.core) evvB = evvB.ltp_to_ltp(frame) self.assertArray(evvB, numpy.array((0, 1, 0)), 7) ev = LTP( x=ev[0], y=ev[1], z=ev[2], frame=shower.core ) # TODO: this step is redundant as ev is already in LTP. Fix this. ev = ev.ltp_to_ltp(frame) self.assertArray(ev, numpy.array((0, 0, 1)), 7)
def test_topography_elevation(self): # Fetch a test tile # geo = GeodeticRepresentation(latitude=39.5 * u.deg, # longitude=90.5 * u.deg) geo = Geodetic(latitude=39.5, longitude=90.5, height=0) c = ECEF(geo) topography.update_data(c) # Test the global topography getter # z0 = topography.elevation(c) z0 = topography.elevation(geo) self.assertEqual(z0.size, 1) # self.assertEqual(z0.unit, u.m) self.assertFalse(numpy.isnan(z0)) z1 = topography.elevation(geo, reference="ELLIPSOID") z1 -= topography.geoid_undulation(geo) self.assertEqual(z1.size, 1) # self.assertEqual(z1.unit, u.m) self.assertFalse(numpy.isnan(z1)) self.assertQuantity(z0, z1) o = numpy.ones(10) # cv = ECEF(GeodeticRepresentation(latitude=geo.latitude * o, # longitude=geo.longitude * o)) cv = ECEF( Geodetic( latitude=geo.latitude * o, longitude=geo.longitude * o, height=geo.height * o, )) z2 = topography.elevation(cv) self.assertEqual(z2.size, o.size) # self.assertEqual(z2.unit, u.m) for i in range(o.size): self.assertQuantity(z2[i], z0) # Test the local topography getter # cl = LTP(0 << u.m, 0 << u.m, 0 << u.m, location=c) cl = LTP(x=0, y=0, z=0, location=c, orientation="NWU") z3 = topography.elevation(cl, "LOCAL") self.assertEqual(z3.size, 1) # self.assertEqual(z3.unit, u.m) self.assertQuantity(z3, z1, 7)
def test_antenna(self): ts, delta, Es = 502.5, 5, 100 t = numpy.array([ -6.5e-08, -6.3e-08, -6.1e-08, -5.9e-08, -5.7e-08, -5.5e-08, -5.3e-08, -5.1e-08, -4.9e-08, -4.7e-08, -4.5e-08, -4.3e-08, -4.1e-08, -3.9e-08, -3.7e-08, -3.5e-08, -3.3e-08, -3.1e-08, -2.9e-08, -2.7e-08, -2.5e-08, -2.3e-08, -2.1e-08, -1.9e-08, -1.7e-08, -1.5e-08, -1.3e-08, -1.1e-08, -9.0e-09, -7.0e-09, -5.0e-09, -3.0e-09, -1e-09, 1e-09, 3.0e-09, 5.0e-09, 7.0e-09, 9.0e-09, 1.1e-08, 1.3e-08, 1.5e-08, 1.7e-08, 1.9e-08, 2.1e-08, 2.3e-08, 2.5e-08, 2.7e-08, 2.9e-08, 3.1e-08, 3.3e-08, 3.5e-08, 3.7e-08, 3.9e-08, 4.1e-08, 4.3e-08, 4.5e-08, 4.7e-08, 4.9e-08, 5.1e-08, 5.3e-08, 5.5e-08, 5.7e-08, 5.9e-08, 6.1e-08, 6.3e-08, 6.5e-08, 6.7e-08, 6.9e-08, 7.1e-08, 7.3e-08, 7.5e-08, 7.7e-08, 7.9e-08, 8.1e-08, 8.3e-08, 8.5e-08, 8.7e-08, 8.9e-08, 9.1e-08, 9.3e-08, 9.5e-08, 9.7e-08, 9.9e-08, 1.01e-07, 1.03e-07, 1.05e-07, 1.07e-07, 1.09e-07, 1.11e-07, 1.13e-07, 1.15e-07, 1.17e-07, 1.19e-07, 1.21e-07, 1.23e-07, 1.25e-07, 1.27e-07, 1.29e-07, 1.31e-07, 1.33e-07, 1.35e-07, 1.37e-07, 1.39e-07, 1.41e-07, 1.43e-07, 1.45e-07, 1.47e-07, 1.49e-07, 1.51e-07, 1.53e-07, 1.55e-07, 1.57e-07, 1.59e-07, 1.61e-07, 1.63e-07, 1.65e-07, 1.67e-07, 1.69e-07, 1.71e-07, 1.73e-07, 1.75e-07, 1.77e-07, 1.79e-07, 1.81e-07, 1.83e-07, 1.85e-07, 1.87e-07, 1.89e-07, 1.91e-07, 1.93e-07, 1.95e-07, 1.97e-07, 1.99e-07, 2.01e-07, 2.03e-07, 2.05e-07, 2.07e-07, 2.09e-07, 2.11e-07, 2.13e-07, 2.15e-07, 2.17e-07, 2.19e-07, 2.21e-07, 2.23e-07, 2.25e-07, 2.27e-07, 2.29e-07, 2.31e-07, 2.33e-07, 2.35e-07, 2.37e-07, 2.39e-07, 2.41e-07, 2.43e-07, 2.45e-07, 2.47e-07, 2.49e-07, 2.51e-07, 2.53e-07, 2.55e-07, 2.57e-07, 2.59e-07, 2.61e-07, 2.63e-07, 2.65e-07, 2.67e-07, 2.69e-07, 2.71e-07, 2.73e-07, 2.75e-07, 2.77e-07, 2.79e-07, 2.81e-07, 2.83e-07, 2.85e-07, 2.87e-07, 2.89e-07, 2.91e-07, 2.93e-07, 2.95e-07, 2.97e-07, 2.99e-07, 3.01e-07, 3.03e-07, 3.05e-07, 3.07e-07, 3.09e-07, 3.11e-07, 3.13e-07, 3.15e-07, 3.17e-07, 3.19e-07, 3.21e-07, 3.23e-07, 3.25e-07, 3.27e-07, 3.29e-07, 3.31e-07, 3.33e-07, 3.35e-07, 3.37e-07, 3.39e-07, 3.41e-07, 3.43e-07, 3.45e-07, 3.47e-07, 3.49e-07, 3.51e-07, 3.53e-07, 3.55e-07, 3.57e-07, 3.59e-07, 3.61e-07, 3.63e-07, 3.65e-07, 3.67e-07, 3.69e-07, 3.71e-07, 3.73e-07, 3.75e-07, 3.77e-07, 3.79e-07, 3.81e-07, 3.83e-07, 3.85e-07, 3.87e-07, 3.89e-07, 3.91e-07, 3.93e-07, 3.95e-07, 3.97e-07, 3.99e-07, 4.01e-07, 4.03e-07, 4.05e-07, 4.07e-07, 4.09e-07, 4.11e-07, 4.13e-07, 4.15e-07, 4.17e-07, 4.19e-07, 4.21e-07, 4.23e-07, 4.25e-07, 4.27e-07, 4.29e-07, 4.31e-07, 4.33e-07, 4.35e-07, 4.37e-07, 4.39e-07, 4.41e-07, 4.43e-07, 4.45e-07 ]) Ex = numpy.array([ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.634e-06, 8.327e-06, -0.0001962, -0.001593, 0.001595, -0.001423, 0.002508, -0.01132, 0.0005137, 0.003592, -0.01067, -0.0009633, 0.008882, 0.01466, -0.007593, 0.0002477, -0.01432, 0.0004441, -0.005924, 0.001146, 0.008704, 0.008442, -0.00348, -0.002316, 0.001836, -0.004856, 0.007674, 0.01774, 0.05312, 0.111, 0.004729, 0.008051, 0.003123, -0.01139, -0.01326, 0.005622, -0.01499, -0.01029, -0.00238, -0.01578, -0.01478, -0.0102, -0.01188, 0.007526, -0.01554, -0.005519, -0.004631, -0.01298, 0.004591, 0.01252, -0.01035, -0.007446, 0.0005477, 0.002052, 0.002545, -0.007815, -0.001831, -0.0079, -0.00876, -0.008696, -0.002208, -0.01397, -0.0136, -0.004355, -0.003452, 0.01309, 0.003015, -0.006622, -0.007464, -0.006257, -0.003579, -0.002314, 0.001303, -0.004935, -0.002793, -0.01587, 0.005295, -0.008781, 0.002756, 0.01451, -0.01102, -0.01542, 0.004564, 0.006329, -0.001169, -0.005177, -0.008236, -0.01028, 0.01354, 0.002981, 0.003809, -0.0136, -0.004548, -0.003293, -0.01541, -0.01023, 0.008453, 0.007639, -0.003952, -0.005495, 0.006424, 0.005166, 0.002028, 0.0004013, -0.0061, -0.002726, -0.001718, 0.001021, -0.01483, -0.006085, 0.004861, 0.003833, -0.0005193, -0.006949, 0.004709, -0.001642, -0.006724, -0.0007832, 0.006581, 0.001882, -0.02022, -0.0008376, 0.01225, -0.004236, -0.004128, 0.0006207, -0.001163, -0.004435, 0.002362, -0.004299, 0.001443, -0.007266, 0.0009821, -0.006581, 0.003486, 0.0006452, 0.003584, -0.003828, 0.000949, -0.00451, -0.002225, -0.001442, 0.001595, -0.002558, 0.004587, 0.000634, -0.004932, -0.006465, 0.004321, -0.0007782, -0.001376, 0.0007583, -0.002453, -0.007857, -0.004844, -0.001436, 0.006736, -0.0004207, -0.001258, 0.00227, 0.007231, 0.002765, -0.0002397, -0.002203, -0.003719, 0.0005649, 0.006208, -0.01643, 0.00235, 0.008098, -0.003094, -0.0002576, 0.007339, 0.0008796, 0.004763, -0.005941, 0.003939, -0.0191, 0.002277, -0.002524, 0.004373, -0.0001035, -0.001342, 0.0004123, 0.0001047, 0.002963, 0.008776, -0.004753, -0.004972, -0.005379, -0.002264, 0.0003036, -0.001602, -0.005375, -0.002347, 0.003754, 0.003124, 0.001916, -0.007459, 0.007283, -0.006275, -0.000778, -0.002005, 0.003565, 7.714e-05, 0.0002261, 0.003431, 0.0008743, 9.367e-05, -0.0007756, -0.00193, 0.006717, -0.001539, -0.003396, 0.0007952, -0.000142, -0.000166, 0.001825, 0.001112, -0.001891, -2.25e-05, -0.0001333, 0.001353, -0.006866 ]) Ey = numpy.array([ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -4.004e-05, -0.002111, -0.00833, 0.03305, 0.06562, 0.00397, -0.02981, 0.2314, 0.006861, -0.02816, 0.1393, -0.03429, -0.05913, -0.06653, 0.04426, -0.05904, 0.001477, 0.01868, -0.02357, 0.04089, 0.000957, 0.09581, 0.3788, 0.6436, 0.9285, 0.5444, 3.36, 15.66, 39.98, 47.27, 19.58, -0.4214, -2.18, -1.526, -1.326, -1.047, -0.8405, -1.028, -1.02, -0.8764, -0.8678, -0.7837, -1.019, -1.077, -0.9168, -0.8808, -0.8705, -1.015, -0.8274, -0.8673, -0.8105, -0.8563, -0.7707, -0.874, -0.8658, -0.8078, -0.8194, -0.6849, -0.7642, -0.6243, -0.7599, -0.7714, -0.7753, -0.6276, -0.668, -0.7181, -0.694, -0.7112, -0.7242, -0.6823, -0.6923, -0.6441, -0.5732, -0.5515, -0.6058, -0.6454, -0.6271, -0.6595, -0.6679, -0.496, -0.5917, -0.5355, -0.5882, -0.5143, -0.5156, -0.5622, -0.4582, -0.4633, -0.5584, -0.5986, -0.5187, -0.5535, -0.5166, -0.3849, -0.5549, -0.5604, -0.414, -0.483, -0.437, -0.4592, -0.4556, -0.3951, -0.3855, -0.5039, -0.503, -0.4456, -0.4159, -0.3664, -0.571, -0.4996, -0.4005, -0.367, -0.445, -0.5083, -0.3691, -0.3752, -0.4564, -0.3326, -0.4353, -0.3896, -0.4696, -0.4032, -0.3062, -0.4324, -0.4379, -0.3959, -0.284, -0.3376, -0.3755, -0.4941, -0.3793, -0.4004, -0.2819, -0.3459, -0.3031, -0.3248, -0.2656, -0.3641, -0.3444, -0.3266, -0.38, -0.3073, -0.2708, -0.3633, -0.2837, -0.3671, -0.3648, -0.2912, -0.3716, -0.2566, -0.3025, -0.3055, -0.3328, -0.3391, -0.3425, -0.3461, -0.2184, -0.2784, -0.2874, -0.3376, -0.2785, -0.2948, -0.1786, -0.285, -0.3101, -0.2867, -0.2785, -0.3562, -0.2681, -0.1715, -0.229, -0.3124, -0.2421, -0.2055, -0.1944, -0.2236, -0.2895, -0.3677, -0.2767, -0.2667, -0.2302, -0.2823, -0.2436, -0.2248, -0.2795, -0.2585, -0.2383, -0.2197, -0.2169, -0.2209, -0.2551, -0.2062, -0.2398, -0.2319, -0.1828, -0.2452, -0.2123, -0.168, -0.2161, -0.2357, -0.2168, -0.2806, -0.197, -0.2072, -0.176, -0.2427, -0.2165, -0.202, -0.2389, -0.2072, -0.1953, -0.2087, -0.2033, -0.1917, -0.1898, -0.1701, -0.1772, -0.173, -0.1933, -0.184, -0.1878, -0.1594, -0.2037, -0.2085 ]) Ez = numpy.array([ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -4.277e-05, 4.058e-05, 0.002583, 0.01059, -0.02968, 0.01995, -0.002003, 0.03808, -0.01932, -0.06695, 0.05944, 0.01247, -0.1083, -0.09392, 0.04629, 0.0296, 0.1009, -0.0126, 0.09194, -0.06074, -0.05238, -0.04936, -0.03231, 0.0265, 0.003196, 0.08489, 0.02912, 0.1918, 0.2604, -0.4283, 0.3312, -0.1353, -0.1169, 0.06986, 0.1159, -0.1207, 0.19, 0.07899, -0.03117, 0.178, 0.1613, 0.04654, 0.05853, -0.04882, 0.1449, 0.05281, 0.06354, 0.1317, -0.08383, -0.1403, 0.04402, 0.06162, -0.001736, -0.02754, -0.06483, 0.08051, -0.005419, 0.06474, 0.09024, 0.04725, 0.03429, 0.125, 0.09307, 0.01346, 0.007365, -0.1909, -0.04796, 0.06946, 0.06571, 0.04984, 0.02719, 0.0129, -0.03278, 0.03152, -0.00311, -0.01878, -0.03724, 0.08011, 0.02747, -0.07971, 0.09449, 0.05258, -0.07572, 0.06557, 0.06355, -0.02068, 0.09576, 0.05547, -0.135, -0.08763, -0.09347, 0.16, 0.005236, 0.08473, -0.06194, 0.03389, 0.01433, 0.03786, 0.04849, 0.01706, 0.01813, 0.00544, -0.01666, -0.07187, 0.08493, 0.04315, 0.009544, -0.0008193, 0.1132, 0.05515, 0.007662, 0.01622, 0.02174, 0.00476, 0.01119, 0.02759, 0.04854, -0.006816, -0.08824, -0.02941, 0.04098, -0.01158, -0.1016, -0.0163, 0.04852, -0.017, 0.03268, -0.01625, -0.02907, 0.03254, 0.003674, 0.08031, -0.03811, 0.01698, 0.0004391, 0.04493, -0.03649, 0.03086, -0.0234, 0.04497, 0.02401, 0.006412, -0.03529, 0.03595, -0.03768, -0.02905, -0.001122, 0.02955, -0.04571, 0.002896, 0.008968, -0.001767, 0.0263, 0.05726, 0.0218, 0.01412, -0.04857, 0.001231, 0.01568, -0.05731, -0.05964, -0.004911, 0.01501, 0.0477, 0.04102, -0.02059, -0.02657, 0.003155, 0.02848, 0.01089, 0.01957, 0.000879, -0.04418, -0.01665, 0.004753, 0.04192, -0.02233, 0.04461, 0.0004942, 0.001844, -0.07743, -0.03439, -0.03239, 0.02355, -0.03998, -0.01652, -0.04388, 0.04547, -0.004156, -0.02404, -0.05274, 0.007553, 0.04107, 0.07093, 0.03636, -0.05789, -0.02469, -0.006849, 0.06134, -0.02288, -0.02765, 0.01904, 0.03419, -0.04615, -0.02832, -0.002096, -0.01513, 0.01203, -0.02213, -0.02701, 0.009911, -0.06074, 0.0138, 0.02905, -0.02465, 0.01798, -0.005557, -0.02162, -0.01465, 0.003988, -0.0005852, 0.003069, -0.004647, 0.02929 ]) E = CartesianRepresentation(x=Ex, y=Ey, z=Ez) #loc = Geodetic(latitude=44, longitude=90, height=0) loc = ECEF(x=-202152.62, y=4968285.91, z=3981091.07) ant_loc = LTP(x=0, y=270.45, z=2900, location=loc, orientation='NWU', declination=0.72) shower_frame = LTP(x=0, y=0, z=0, location=loc, orientation='NWU', declination=0.72) antenna_frame = LTP(x=0, y=0, z=0, location=ant_loc, orientation='NWU', declination=0.72) xmax = LTP(x=150750., y=0, z=15560., frame=shower_frame) def check(voltage): imin, imax = numpy.argmin(voltage.V), numpy.argmax(voltage.V) t0 = 0.5 * (voltage.t[imax] + voltage.t[imin]) Vpp = voltage.V[imax] - voltage.V[imin] self.assertLess(t0 - ts, delta) self.assertGreater(Vpp, 6E-02 * Es) field = ElectricField(t, E, frame=shower_frame) antenna = Antenna(model=self.model, frame=antenna_frame) check(antenna.compute_voltage(xmax, field, shower_frame)) with self.assertRaises(MissingFrameError) as context: antenna.compute_voltage(xmax, field) antenna = Antenna(model=self.model, frame=None) with self.assertRaises(MissingFrameError) as context: antenna.compute_voltage(xmax, field, shower_frame) antenna = Antenna(model=self.model, frame=antenna_frame) check(antenna.compute_voltage(xmax, field, shower_frame)) with self.assertRaises(MissingFrameError) as context: antenna.compute_voltage(xmax, field) # added by RK voltage = antenna.compute_voltage(xmax, field, shower_frame) self.assertIsInstance(voltage, Voltage) self.assertIsInstance(field, ElectricField) effective_length = antenna.effective_length(xmax, field, shower_frame) self.assertIsInstance(effective_length, CartesianRepresentation)
# Loop over electric fields and compute the corresponding voltages for antenna_index, field in shower.fields.items(): counter += 1 if counter == 2: break # Compute the antenna local frame # # The antenna is placed within the shower frame. It is oriented along the # local magnetic North by using an ENU/LTP frame (x: East, y: North, z: Upward) antpos_wrt_shower = ( field.electric.r ) # RK: if antenna location was saved in LTP frame in zhaires.py, next step would not required. antenna_location = LTP( x=antpos_wrt_shower.x, y=antpos_wrt_shower.y, z=antpos_wrt_shower.z, frame=shower.frame, ) antenna_frame = LTP( location=antenna_location, orientation="NWU", magnetic=True, obstime=shower.frame.obstime, ) antenna = Antenna(model=antenna_model, frame=antenna_frame) print(antenna_index, "Antenna pos in shower frame", antpos_wrt_shower.flatten()) print( vars(antenna_location), antenna_location.flatten(), "antenna pos LTP in shower frame",
# Get the corresponding topography data. Note that does are dowloaded from the # web and cached which might take some time. Reducing the area results in less # data to be downloaded, i.e. speeding up this step radius = 200000 # m topography.update_data(origin, radius=radius) # Generate a grid of local coordinates using numpy.meshgrid x = np.linspace(-1 * radius, radius, 1001) y = np.linspace(-1 * radius, radius, 1001) X, Y = np.meshgrid(x, y) coordinates = LTP( x=X.flatten(), y=Y.flatten(), z=np.zeros(X.size), location=origin, orientation="ENU", magnetic=False, ) # Get the local ground elevation. Note that local coordinates naturally account # for the Earth curvature. zg = topography.elevation(coordinates, reference="local") zg = zg.reshape(X.shape) # Plot the result using contour levels. The Earth curvature is clearly visible # at large distances from the origin. pl.figure() pl.contourf(x / 1000, y / 1000, zg / 1000, 40, cmap="terrain") pl.colorbar(label="Local Altitude (km)") pl.xlabel("Easting (km)")
def test_readwrite(self): r0 = CartesianRepresentation(x=1, y=2, z=3) u0 = SphericalRepresentation(theta=90, phi=-90, r=1) c = numpy.array((1, 2)) r1 = CartesianRepresentation(x=c, y=c, z=c) c = 90 u1 = SphericalRepresentation(theta=c, phi=c, r=1) loc = Geodetic(latitude=45, longitude=6, height=0) elements = { "primary": "pà", "bytes": b"0100011", "id": 1, "energy0": 1.0, "energy1": 1, "data": numpy.array(((1, 2, 3), (4, 5, 6))), "position0": r0, "position1": [r0.x, r0.y, r0.z], "position2": r0, "position3": r1, "direction0": u0, "direction1": u1, "frame0": ECEF(x=0, y=0, z=0, obstime="2010-01-01"), "frame1": LTP( x=0, y=0, z=0, location=loc, obstime="2010-01-01", magnetic=True, orientation="NWU", ) # rotation=Rotation.from_euler('z', 90 * u.deg)) #RK. TODO. } with io.open(self.path, "w") as root: for k, v in elements.items(): root.write(k, v) with io.open(self.path) as root: for name, element in root.elements: a = elements[name] print(a, type(a)) if hasattr(a, "shape"): self.assertEqual(a.shape, element.shape) # RK: TODO: ECEF, LTP is not detected by isinstance, instead # they are seen as CartesianRepresentation objects. if isinstance(a, CartesianRepresentation): self.assertCartesian(a, element) elif isinstance(a, SphericalRepresentation): self.assertSpherical(a, element) elif isinstance(a, numpy.ndarray): self.assertEqual(a.shape, element.shape) self.assertArray(a, element) elif isinstance(a, ECEF): self.assertEqual(a.obstime, element.obstime) elif isinstance(a, LTP): self.assertEqual(a.obstime, element.obstime) self.assertCartesian(a.location, element.location, 8) self.assertEqual(a.orientation, element.orientation) self.assertEqual(a.magnetic, element.magnetic) # self.assertArray(a.rotation.matrix, element.rotation.matrix) self.assertArray(a.basis, element.basis) else: self.assertEqual(a, element)
def test_ltp(self): loc = self.location location_ref0 = self.location.reference loc_ref0 = loc.reference ecef = ECEF(self.location) # Check the constructor & to ECEF transform ltp = LTP( x=0, y=0, z=0, location=self.location, orientation="NWU", magnetic=False, obstime=self.obstime, ) r = ltp.ltp_to_ecef() self.assertEqual(r.obstime, ltp.obstime) self.assertCartesian(r, ecef, 6) # Check the from ECEF transform ltp_frame = LTP( location=self.location, orientation="ENU", magnetic=False, obstime=self.obstime, ) # ltp = ecef.ecef_to_ltp(ltp_frame) ltp = LTP(ecef, frame=ltp_frame) # RK Note: # self.location.reference can suddenly changes from ELLIPSOID to GEOID # reference changes if it is stored as class attribute instead of instance # attribute. Always check reference consitency for a Geodetic coordinate. self.assertEqual(self.location.reference, "ELLIPSOID") self.assertEqual(loc.reference, "ELLIPSOID") # attributes can change if they are class attribute instead of instance attribute. # always check attributes consitency for a LTP coordinate. self.assertEqual(ltp.obstime, self.obstime) self.assertQuantity(ltp.x, numpy.zeros(1), 6) self.assertQuantity(ltp.y, numpy.zeros(1), 6) self.assertQuantity(ltp.z, numpy.zeros(1), 6) # Check the Earth location conversion loc = ECEF(ltp) self.assertCartesian(ecef, loc, 2) # Check the affine transform. points = ((0, 0, 1), (1, 0, 0), (0, 1, 0), (1, 1, 0), (1, 1, 1), (0, 1, 1)) for point in points: cart = CartesianRepresentation(x=point[0], y=point[1], z=point[2]) ltp = LTP( x=cart.x, y=cart.y, z=cart.z, location=self.location, obstime=self.obstime, orientation="NWU", magnetic=False, ) ecef0 = ECEF(ltp) ecef1 = ltp.ltp_to_ecef() self.assertEqual(ecef0.obstime, ecef1.obstime) self.assertCartesian(ecef0, ecef1, 4) # Check the orientation point = (1, -1, 2) ltp = LTP( x=point[0], y=point[1], z=point[2], location=self.location, obstime=self.obstime, orientation="NEU", ) ecef0 = ltp.ltp_to_ecef() for (orientation, sign) in ( ("NEU", (1, 1, 1)), ("NED", (1, 1, -1)), ("SEU", (-1, 1, 1)), ("NWU", (1, -1, 1)), ): ltp = LTP( x=sign[0] * point[0], y=sign[1] * point[1], z=sign[2] * point[2], location=self.location, obstime=self.obstime, orientation=orientation, magnetic=False, ) ecef1 = ECEF(ltp) self.assertCartesian(ecef0, ecef1, 4) # Check the unit vector case. # RK TODO: Develop HorizontalRepresentation, it is not complete and might have some error. uy = Horizontal(azimuth=0, elevation=0, location=self.location) ecef = uy.horizontal_to_ecef() ltp = LTP(ecef, location=self.location, obstime=self.obstime, orientation="ENU") self.assertQuantity(ltp.x, numpy.zeros(1), 9) self.assertQuantity(ltp.y, numpy.ones(1), 9) self.assertQuantity(ltp.z, numpy.zeros(1), 9) # r = ECEF(ltp) #RK. Use this or the next. r = ltp.ltp_to_ecef() # RK self.assertEqual(r.obstime, ltp.obstime) self.assertQuantity(r.norm(), 6378137.0, 6) # RK # check input argument is of knonw coordinate system. with self.assertRaises(TypeError) as context: LTP(numpy.ones(10), frame=ltp) # check input argument is of knonw coordinate system. with self.assertRaises(TypeError) as context: LTP(location=numpy.ones(10), orientation="NWU") # RK: Horizontal coordinate system is incomplete and need more work. """ ecef = ECEF(uy, obstime=self.obstime) #ltp = LTP(ecef, location=self.location, orientation='ENU', magnetic=False) #RK, or ltp = ecef.ecef_to_ltp(ltp_frame) #RK self.assertEqual(ltp.obstime, ecef.obstime) self.assertQuantity(ltp.cartesian.norm(), 1 * u.one, 6) # Check the magnetic north case ltp0 = LTP(uy, location=self.location, obstime=self.obstime, orientation='ENU', magnetic=False) frame1 = LTP(location=self.location, obstime=self.obstime, orientation='ENU', magnetic=True) ltp1 = ltp0.transform_to(frame1) self.assertEqual(ltp0.obstime, ltp1.obstime) declination = numpy.arcsin(ltp0.cartesian.cross(ltp1.cartesian).norm()) self.assertQuantity(declination.to(u.deg), 0.10 * u.deg, 2) # Test the magnetic case with no obstime ltp1 = LTP(uy, location=self.location, orientation='ENU', magnetic=True) self.assertIsNone(ltp1.obstime) # Test the invalid frame case with self.assertRaises(ValueError) as context: LTP(uy, location=self.location, orientation=('T', 'O', 'T', 'O')) self.assertRegex(context.exception.args[0], '^Invalid frame') """ # Test the ltp round trip with a position frame0 = LTP(location=self.location, orientation="ENU", magnetic=False) frame1 = LTP( location=self.location, obstime=self.obstime, orientation="ENU", magnetic=True, ) ltp0 = LTP( x=1, y=2, z=3, location=self.location, orientation="ENU", magnetic=False, obstime=self.obstime, ) # RK ltp1_ = ltp0.ltp_to_ltp(frame1) # RK ltp1 = ltp1_.ltp_to_ltp(frame0) # RK self.assertCartesian(ltp0, ltp1, 8) # Test the same frame case ltp1 = ltp0.ltp_to_ltp(frame0) # RK self.assertCartesian(ltp0, ltp1, 8) self.assertEqual(ltp0.obstime, ltp1.obstime) # Test an LTP permutation ltp0 = LTP( x=1, y=2, z=3, location=self.location, orientation="ENU", magnetic=False ) # RK frame1 = LTP(location=self.location, orientation="NED", magnetic=False) ltp1 = ltp0.ltp_to_ltp(frame1) # RK self.assertQuantity(ltp0.x, ltp1.y, 6) self.assertQuantity(ltp0.y, ltp1.x, 6) self.assertQuantity(ltp0.z, -ltp1.z, 6) """