def test_CartToSph(self): """CartToSph shuld give known output for known input""" np.testing.assert_array_equal(Lgm_Vector.CartToSph(1, 0, 0), (0.0, 0.0, 1.0)) np.testing.assert_array_equal( Lgm_Vector.CartToSph([1, 1], [0, 0], [0, 0]), [[0.0, 0.0, 1.0], [0.0, 0.0, 1.0]])
def _doConversion(pos_in, cdict, cTrans): """ Function that does the conversion .. warning:: This function is not called by the user Parameters ========== pos_in : Lgm_Vector the input position to convert to_str : str a string giving the acronym for the output coordinate system cdict : dict the coordinate transform dictionary cTrans : Lgm_CTrans the Lgm_CTrans object used in the conversion Returns ======= out : Lgm_Vector vector of the new position """ try: Pin = Lgm_Vector.Lgm_Vector(*pos_in) except: Pin = pos_in Pout = Lgm_Vector.Lgm_Vector() Lgm_Convert_Coords(pointer(Pin), pointer(Pout), cdict, pointer(cTrans)) return Pout
def test_dotProduct(self): """dotProduct gives known output""" self.assertEqual(26.0, self.vec1.dotProduct(self.vec2)) self.assertEqual(14.0, self.vec1.dotProduct(self.vec1)) vec3 = Lgm_Vector.Lgm_Vector(1, 0, 0) vec4 = Lgm_Vector.Lgm_Vector(0, 1, 0) self.assertEqual(0.0, vec3.dotProduct(vec4))
def test_pos2Lgm_Vector(self): """pos2Lgm_Vector should have known output""" a = [1.2, 3.4, 4.3] self.assertEqual(Lgm_Vector.Lgm_Vector(*a), utils.pos2Lgm_Vector(a)) self.assertEqual(Lgm_Vector.Lgm_Vector(*a), utils.pos2Lgm_Vector(Lgm_Vector.Lgm_Vector(*a))) self.assertEqual(Lgm_Vector.Lgm_Vector(*a), utils.pos2Lgm_Vector(np.asarray(a))) self.assertEqual([Lgm_Vector.Lgm_Vector(*a)] * 2, utils.pos2Lgm_Vector([a] * 2))
def testLgm_Vector_Type(self): """Lgm_Vector should be of type LgmDouble""" vec1 = Lgm_Vector.Lgm_Vector(3, 1, 0) self.assertTrue(isinstance(vec1.x, float)) self.assertTrue(isinstance(vec1.y, float)) self.assertTrue(isinstance(vec1.z, float)) self.assertRaises(TypeError, Lgm_Vector.Lgm_Vector, 'bad', 0, 1) self.assertRaises(TypeError, Lgm_Vector.Lgm_Vector, 1, 'bad', 0) self.assertRaises(TypeError, Lgm_Vector.Lgm_Vector, 5, 3, 'bad')
def test_Pin_pos_in(self): """I don't understand why this is here but here is a regression test""" in_pos = Lgm_Vector.Lgm_Vector(-4, 0, 0) ans = [-3.608026916281572, 4.163336342344337e-17, -1.7268878861662331] numpy.testing.assert_allclose( ans, magcoords.coordTrans(in_pos, datetime.datetime(2009, 1, 1), 'SM', 'GSM'), atol=1e-8)
def test_Lgm_Convert_CoordsBack(self): """Lgm_Convert_Coords should give known output (and back)""" # taken from CoordQuickStart.c Date = 20040812 UTC = 12.34567 Ugsm = Lgm_Vector.Lgm_Vector(x = -6.6, y = 3.4, z = -2.3) Usm = Lgm_Vector.Lgm_Vector() c = Lgm_CTrans.Lgm_CTrans() Lgm_Set_Coord_Transforms(Date, UTC, ctypes.pointer(c)) Lgm_Convert_Coords(ctypes.pointer(Ugsm), ctypes.pointer(Usm), GSM_TO_SM, ctypes.pointer(c)) self.assertAlmostEqual(-5.5352494753370127, Usm.x, places=5) self.assertAlmostEqual( 3.3999999999999995, Usm.y, places=5) self.assertAlmostEqual(-4.2674363786448328, Usm.z, places=5) Lgm_Convert_Coords(ctypes.pointer(Usm), ctypes.pointer(Ugsm), SM_TO_GSM, ctypes.pointer(c)) self.assertAlmostEqual(-6.6, Ugsm.x) self.assertAlmostEqual( 3.4, Ugsm.y) self.assertAlmostEqual(-2.3, Ugsm.z)
def test_SphToCart(self): """SphToCart should known known output (regression)""" invals = [[0, 0, 5], [90, 0, 5], [90, 90, 5], [90, 180, 5]] ans = [[5.0, 0.0, 0.0], [3.061616997868383e-16, 0.0, 5.0], [1.8746997283273223e-32, 3.061616997868383e-16, 5.0], [-3.061616997868383e-16, 3.7493994566546446e-32, 5.0]] for i, val in enumerate(invals): vec3 = Lgm_Vector.SphToCart(*val) for j, val2 in enumerate(vec3.tolist()): self.assertAlmostEqual(ans[i][j], val2) # test an input check self.assertRaises(ValueError, Lgm_Vector.SphToCart, [1] * 2, [2] * 3, [3] * 2) # test putting in lists ans_tst = Lgm_Vector.SphToCart( zip(*invals)[0], zip(*invals)[1], zip(*invals)[2]) for i, v1 in enumerate(ans_tst): for j, v2 in enumerate(v1.tolist()): self.assertAlmostEqual(ans[i][j], ans_tst[i].tolist()[j])
def NO_test_pos2Lgm_Vector(self): """pos2Lgm_Vector should have known output""" a = Lgm_TS04.Lgm_TS04(self.pos, self.dt, self.kp) self.assertEqual(list(a['Position']), a._Vpos.tolist()) self.assertTrue(isinstance(a._Vpos, Lgm_Vector.Lgm_Vector)) b = Lgm_TS04.Lgm_TS04(a._Vpos, self.dt, self.kp) self.assertEqual(a._Vpos, b._Vpos) # above tested thought __init__ below is raw self.assertEqual(a._pos2Lgm_Vector([1, 2, 3]), Lgm_Vector.Lgm_Vector(1, 2, 3)) self.assertRaises(NotImplementedError, a._pos2Lgm_Vector, numpy.array([1, 2, 3]))
def test_mul(self): """mul gives known output""" ans = Lgm_Vector.Lgm_Vector() ans = self.vec1 * self.vec2 self.assertEqual(-2.0, ans.x) self.assertEqual(4.0, ans.y) self.assertEqual(-2.0, ans.z) vec3 = self.vec1 * 3 self.assertEqual(3, vec3.x) self.assertEqual(6, vec3.y) self.assertEqual(9, vec3.z) self.assertRaises(ArithmeticError, self.vec1.__mul__, 'bad')
def getLatLonRadfromTLE(epochs, TLEpath, options): """ Reads Latitude and Longitude from TLE. Parameters ========== epochs : List of Ticktock objects. TLEpath : Path to TLE file. options : optparse.Values Organized options from the command line. Returns ======= testlat, testlon, testrad : list, list, list Latitude, Longitude, and Radius, respectively, each being a list of float values. """ # now do Mike's setup for getting coords from TLE using SGP4 pos_in = [0, 0, 0] s = _SgpInfo() TLEs = _SgpTLE() # loop over all times testlat = np.asarray(epochs).copy() testlat.fill(0) testlon = testlat.copy() testrad = testlat.copy() testtdiff = testlat.copy() print('Fetching TLEs & converting for range {0} to {1}'.format( epochs[0].isoformat(), epochs[-1].isoformat())) for idx, c_date in enumerate(epochs): #print('Doing {0}'.format(c_date)) # put into JD as SGP4 needs serial time c = Lgm_init_ctrans(0) # now do Mike's setup for getting coords from TLE using SGP4 dstr = int(c_date.strftime('%Y%j')) + c_date.hour / 24.0 + \ c_date.minute / 1440.0 + c_date.second / 86400.0 globstat = os.path.join(TLEpath, '*.txt') TLEfiles = glob.glob(globstat) if not TLEfiles: raise IOError( 'No TLE files found in {0}. Aborting...'.format(TLEpath)) Line0, Line1, Line2 = fTLE.findTLEinfiles( TLEfiles, ParseMethod='UseSatelliteNumber', TargetEpoch=dstr, SatelliteNumber=options.SatNum, Verbose=False, PurgeDuplicates=True) # print("{0}\n{1}\n{2}\n\n".format(Line0,Line1,Line2)) nTLEs = c_int(0) LgmSgp_ReadTlesFromStrings(Line0, Line1, Line2, pointer(nTLEs), pointer(TLEs), 1) LgmSgp_SGP4_Init(pointer(s), pointer(TLEs)) date = Lgm_CTrans.dateToDateLong(c_date) utc = Lgm_CTrans.dateToFPHours(c_date) JD = Lgm_JD(c_date.year, c_date.month, c_date.day, utc, LGM_TIME_SYS_UTC, c) # Set up the trans matrices Lgm_Set_Coord_Transforms(date, utc, c) # get SGP4 output, needs minutes-since-TLE-epoch tsince = (JD - TLEs.JD) * 1440.0 LgmSgp_SGP4(tsince, pointer(s)) pos_in[0] = s.X pos_in[1] = s.Y pos_in[2] = s.Z Pin = Lgm_Vector.Lgm_Vector(*pos_in) Pout = Lgm_Vector.Lgm_Vector() Lgm_Convert_Coords(pointer(Pin), pointer(Pout), TEME_TO_GEO, c) PoutPy = Pout.tolist() PoutPy[0] /= WGS84_A PoutPy[1] /= WGS84_A PoutPy[2] /= WGS84_A nlat, nlon, nrad = Lgm_Vector.CartToSph(*PoutPy) testlat[idx] = nlat testlon[idx] = nlon testrad[idx] = nrad testtdiff[idx] = tsince / 1440.0 return testlat, testlon, testrad
def coordTrans(pos_in, time_in, in_sys, out_sys, de_eph=False): ''' Convert coordinates between almost any system using LanlGeoMag Parameters ---------- position : list a three element vector of positions in input coord system time : datetime a datimetime object representing the time at the desired conversion system_in : str a string giving the acronym for the input coordinate system system_out : str a string giving the acronym for the desired output coordinate system de_eph : bool or int (optional) a boolean stating whether JPL DE421 is to be used for Sun, etc. Returns ------- out : list 3-element list of the converted coordinate Examples -------- >>> from lgmpy import magcoords >>> import datetime >>> magcoords.coordTrans([-4,0,0], datetime.datetime(2009,1,1),'SM','GSM') [-3.60802691..., 2.5673907444...e-16, -1.72688788616...] >>> magcoords.coordTrans([-3.608026916281573, 2.5673907444456745e-16, -1.7268878861662329], datetime.datetime(2009,1,1),'GSM','SM') [-3.99999999..., 4.0592529337...e-16, 8.8817841970...3e-16] TODO ---- extend interface to get necessary args from a MagModel or cTrans structure ''' # change datetime to Lgm Datelong and UTC ct = Lgm_CTrans.Lgm_CTrans(0) if de_eph: Lgm_Set_CTrans_Options(LGM_EPH_DE, LGM_PN_IAU76, pointer(ct)) try: datelong = Lgm_CTrans.dateToDateLong(time_in) utc = Lgm_CTrans.dateToFPHours(time_in) Lgm_Set_Coord_Transforms( datelong, utc, pointer(ct)) # don't need pointer as it is one except AttributeError: raise (TypeError("Date must be a datetime object")) try: conv_val = trans_dict[in_sys] * 100 + trans_dict[out_sys] except KeyError: raise KeyError( 'One of the specified coordinate systems is not recognised') ## do this as WGS uses Cartesian but needs to be converted from desired spherical input if 'WGS84' in in_sys: XYZ = Lgm_Vector.SphToCart(*pos_in) SPH = Lgm_Vector.Lgm_Vector(XYZ.x, XYZ.y, XYZ.z) Pout = _doConversion(SPH, conv_val, cTrans=ct) else: Pout = _doConversion(pos_in, conv_val, ct) if 'WGS84' in out_sys: nlat, nlon, nrad = Lgm_Vector.CartToSph(*Pout.tolist()) Pout = Lgm_Vector.Lgm_Vector(nlat, nlon, nrad) return Pout.tolist()
def Lvalue(*args, **kwargs): ''' Function to return the L-value of a position using either McIlwain or Hilton approximation Parameters ========== pos : list 3-element position int he specified coord_system time : datetime date and time for the calculation alpha : float, optional the pitch angle for the L calculation, default=90 Bfield : str, optional the magnetic field model to use, default=Lgm_B_T89 method : str, optional the L-value formula to use, McIlwain or Hilton, default=Hilton Kp : int Kp index value for the calculation coord_system : str the input coordinate system, default=GSM extended_out : bool keyword specifying short or extended output, default=False Returns ======= out : dict dictionary of the values, see examples for documentation of dictionary Examples ======== >>> from lgmpy import magcoords >>> import datetime >>> magcoords.Lvalue([3, 0, 1], datetime.datetime(2000, 1, 1), extended_out=False) {'I': 0.2434969602..., 'L': 3.195481841...} The ``extended_out=False`` output is: - I : I value at the given point - L : L value at the given point >>> from lgmpy import magcoords >>> import datetime >>> magcoords.Lvalue([3, 0, 1], datetime.datetime(2000, 1, 1), extended_out=True) {'Blocal': 1024.1142193703838, 'Bmin': 921.8869150..., 'Bmirr': 1024.1142193..., 'I': 0.24349696021..., 'L': 3.1954818410..., 'M': 30119.614287...} The ``extended_out=True`` output is: - I : I value at the given point - L : L value at the given point - Bmin : minimum B at the input position (nT) - Bmirror : mirror B at the input position (nT) - M : TODO what exactly and I, magnetic moment? ''' defaults = { 'alpha': 90., 'Bfield': 'Lgm_B_T89', 'method': 'Hilton', 'Kp': 2, 'coord_system': 'GSM', 'extended_out': False } #replace missing kwargs with defaults for dkey in defaults: if dkey not in kwargs: kwargs[dkey] = defaults[dkey] method_dict = {'Hilton': 1, 'McIlwain': 0} # change datetime to Lgm Datelong and UTC mInfo = Lgm_MagModelInfo.Lgm_MagModelInfo() mInfo.Kp = kwargs['Kp'] try: Bfield_dict[kwargs['Bfield']](pointer(mInfo)) except KeyError: raise (NotImplementedError("Only Bfield=%s currently supported" % Bfield_dict.keys())) try: datelong = Lgm_CTrans.dateToDateLong(args[1]) utc = Lgm_CTrans.dateToFPHours(args[1]) Lgm_Set_Coord_Transforms(datelong, utc, mInfo.c) # dont need pointer as it is one except AttributeError: raise (TypeError("Date must be a datetime object")) #else: #ans['Epoch'] = datamodel.dmarray([args[1]]) if kwargs['coord_system'] != 'GSM': in_sys = kwargs['coord_system'] Pout = coordTrans(args[0], args[1], in_sys, 'GSM', de_eph=False) Pgsm = Lgm_Vector.Lgm_Vector(*Pout) else: Pgsm = Lgm_Vector.Lgm_Vector(*args[0]) Iout = c_double() Bm = c_double() M = c_double() ans = Lgm_McIlwain_L(datelong, utc, pointer(Pgsm), kwargs['alpha'], method_dict[kwargs['method']], pointer(Iout), pointer(Bm), pointer(M), pointer(mInfo)) #TODO: decide on format for output -- perhaps use datamodel and have method as attribute? #maybe only return I for extended_out flag=True if kwargs['extended_out']: sunPos_GSM = coordTrans(mInfo.c.contents.Sun, args[1], 'MOD', kwargs['coord_system']) SunMlon = np.rad2deg(np.arctan2(sunPos_GSM[1], sunPos_GSM[0])) SunMlon += 180.0 # flip to midnight MLON = np.rad2deg(np.arctan2(Pgsm.y, Pgsm.x)) if (MLON < 0.0): MLON += 360.0 MLT = np.mod((MLON - SunMlon) / 15.0 + 24.0, 24.0) return { 'L': ans, 'I': Iout.value, 'Bmin': mInfo.Bmin, 'Blocal': mInfo.Blocal, 'Bmirr': mInfo.Bm, 'M': M.value, 'MLon': MLON, 'MLT': MLT } else: return {'L': ans, 'I': Iout.value}
def setUp(self): super(Lgm_VectorTestsWrap, self).setUp() self.vec1 = Lgm_Vector.Lgm_Vector(1, 2, 3) self.vec2 = Lgm_Vector.Lgm_Vector(3, 4, 5)
def test_str(self): """str has known output""" self.vec1 = Lgm_Vector.Lgm_Vector() self.assertEqual(str(self.vec1), '[0.0, 0.0, 0.0]')