def Location(et, ingress, sv, when):
    Coords = np.ones(3)
    [tgopos, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE',
                               sv.target)
    [mexpos, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.obs)
    [states, _] = spice.spkezr(sv.target, et - when, sv.fframe, 'NONE', sv.obs)
    sc2scvector = states[0:3]
    velocity = states[3:6]
    relativespeed = np.linalg.norm(velocity)
    # e9 because we are converting from km to m (SPICE outputs km, but constants in m)
    veldopp = (relativespeed / constants.c) * 437.1e9
    displacement = np.linalg.norm(sc2scvector)
    sc2scunitvector = np.true_divide(sc2scvector, displacement)
    # Extract the triaxial dimensions of Mars
    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    # For the ray that connects MEX and TGO, find the point on this ray that is closest to the Martian surface
    [nearestpoint, alt] = spice.npedln(marsrad[1][0], marsrad[1][1],
                                       marsrad[1][2], tgopos, sc2scunitvector)
    # THERE IS MORE SETTINGS ON THIS
    [radius, lon, lat] = spice.reclat(nearestpoint)
    # Rad -> Deg , frame inversion required (hence the negative 180)
    lon = 180 - (lon * (-180 / math.pi))
    lat = lat * (-180 / math.pi)

    MexNadirTGOAngle = spice.vsep(-mexpos, -sc2scvector)
    MexNadirTGOAngle = MexNadirTGOAngle * (180 / math.pi)

    # produce a string of the date and time, because an ephemeris time is not human-readable
    date_time = spice.timout(et, 'MM-DD HR:MN:SC')
    ingress_date_time = spice.timout(ingress, 'MM-DD HR:MN:SC')
    return lon, lat, displacement, nearestpoint, alt, relativespeed, date_time, ingress_date_time, veldopp, MexNadirTGOAngle
예제 #2
0
    def computeDataFrameGeometries(self, data_frames, greg_format_string,
                                   julian_format_string):

        for data_frame in data_frames:
            self.greg_format_string = greg_format_string
            self.julian_format_string = julian_format_string
            greg_split_string = self.greg_format_string.split(' ')
            data_frame.greg_time_system_string = [
                i for i in greg_split_string if '::' in i
            ][0][2:]
            julian_split_string = self.julian_format_string.split(' ')
            data_frame.julian_time_system_string = [
                i for i in julian_split_string if '::' in i
            ][0][2:]
            current_epoch = data_frame.start_epoch
            current_epoch = spice.str2et(current_epoch)
            stop_epoch = spice.str2et(data_frame.stop_epoch)
            time_remaining = stop_epoch - current_epoch

            while time_remaining >= 0.0:
                greg_date_string = spice.timout(current_epoch,
                                                self.greg_format_string)
                JD_date = spice.timout(current_epoch,
                                       self.julian_format_string)
                for body_pair in data_frame.body_pairs:
                    # get target body state
                    body_state, light_times = spice.spkez(
                        spice.bodn2c(body_pair[1]), current_epoch,
                        data_frame.frame, 'NONE', spice.bodn2c(body_pair[0]))
                    distance_km = self.np.linalg.norm(body_state[0:3])
                    distance_AU = distance_km / self.AU
                    data_frame.data[body_pair[0]][body_pair[1]].append([
                        greg_date_string, JD_date, body_state, distance_km,
                        distance_AU
                    ])

                # compute solar geometries
                SEP_angle, SPE_angle = self.computeSEPandSPEangles(
                    current_epoch, data_frame.spacecraft_SPICE_ID)
                data_frame.data['SEP'].append(
                    [greg_date_string, JD_date, SEP_angle])
                data_frame.data['SPE'].append(
                    [greg_date_string, JD_date, SPE_angle])

                # compute any eclipses
                self.computeCircleCircleOccultations(current_epoch,
                                                     greg_date_string, JD_date,
                                                     data_frame)

                if time_remaining == 0.0:
                    break
                else:
                    if time_remaining >= data_frame.time_step:
                        current_epoch += data_frame.time_step
                        time_remaining -= data_frame.time_step
                    else:
                        time_remaining -= stop_epoch - current_epoch
                        current_epoch += stop_epoch - current_epoch
예제 #3
0
    def computeOccultations(self, observer_in, occultation_bodies_in,
                            target_in, target_shape_in, target_frame_in,
                            step_size_in, aberration_correction_in,
                            greg_format_string_in):

        self.greg_format_string = greg_format_string_in
        split_string = self.greg_format_string.split(' ')
        self.time_system_string = [i for i in split_string if '::' in i][0][2:]

        self.observer = str(observer_in)
        self.occultation_bodies = occultation_bodies_in
        self.target = target_in
        self.target_shape = target_shape_in
        self.target_frame = target_frame_in
        self.search_step_size = step_size_in
        self.aberration_correction = aberration_correction_in
        self.cumulative_results = {}
        for body in self.occultation_bodies:
            # add a new key to the results dictionary for this body
            self.cumulative_results[body.name] = []
            for occultation_type in body.occultation_types:
                body.search_start_ET_seconds = spice.str2et(body.search_start)
                body.search_end_ET_seconds = spice.str2et(body.search_end)
                spice.wninsd(body.search_start_ET_seconds,
                             body.search_end_ET_seconds,
                             self.SPICE_search_window)
                spice.gfoclt(occultation_type, body.name, body.shape,
                             body.frame, self.target, self.target_shape,
                             self.target_frame, self.aberration_correction,
                             self.observer, self.search_step_size,
                             self.SPICE_search_window, self.results_window)
                winsiz = spice.wncard(self.results_window)
                for body_index in range(winsiz):
                    [intbeg, intend] = spice.wnfetd(self.results_window,
                                                    body_index)
                    btmstr = spice.timout(intbeg, self.greg_format_string)
                    etmstr = spice.timout(intend, self.greg_format_string)
                    occultation_event = OccultationEvent()
                    occultation_event.start = btmstr
                    occultation_event.stop = etmstr
                    occultation_event.start_JD = greg2Julian(btmstr)
                    occultation_event.stop_JD = greg2Julian(etmstr)
                    occultation_event.duration = intend - intbeg
                    occultation_event.type = occultation_type
                    occultation_event.observer = self.observer
                    occultation_event.occulting_body = body.name
                    occultation_event.occulting_body_shape = body.shape
                    occultation_event.target = self.target
                    occultation_event.target_body_shape = self.target_shape
                    self.cumulative_results[body.name].append(
                        occultation_event)
예제 #4
0
def secSinceJ20002Greg(secSinceJ2000):
    # returns the TDB Gregorian date
    # secSinceJ2000: TDB julian seconds since J2000
    # delta_days: number of days that you want to advance the Gregorian date string by
    # time_system_string: string representation of the input gregorian_date's time system (e.g. "TDB", "UTC" etc.)

    return spice.timout(secSinceJ2000, "YYYY Mon DD ::TDB HR:MN:SC.###### TDB")
예제 #5
0
    def parse_EMTG_event(self, SampleNumber, CentralBody, myEvent,
                         ThrustMagnitude):
        self.SampleNumber = SampleNumber
        self.CentralBody = CentralBody
        self.Frame = 'EMO2000'
        self.EpochETJulian = myEvent.JulianDate
        self.EpochETGregorian = spiceypy.timout(
            spiceypy.unitim(myEvent.JulianDate, 'JDTDB', 'TDB'),
            'YYYY Mon DD ::TDB HR:MN:SC')

        self.FinalMass = myEvent.Mass
        self.DVmagnitude = myEvent.DVmagorThrottle
        self.StartMass = self.FinalMass * exp(
            self.DVmagnitude * 1000.0 / myEvent.Isp / 9.80665)

        self.Mdot = ThrustMagnitude / 9.80665 / myEvent.Isp
        self.Duration = (self.StartMass - self.FinalMass) / self.Mdot

        self.ThrustX = 0.0
        self.ThrustY = 0.0
        self.ThrustZ = 0.0

        if self.DVmagnitude > 1.0e-25:
            self.ThrustX = myEvent.DeltaVorThrustVectorControl[
                0] / self.DVmagnitude
            self.ThrustY = myEvent.DeltaVorThrustVectorControl[
                1] / self.DVmagnitude
            self.ThrustZ = myEvent.DeltaVorThrustVectorControl[
                2] / self.DVmagnitude

        self.ThrustMagnitude = ThrustMagnitude
예제 #6
0
def julian2Greg(julian_date):
    # returns the TDB Gregorian date
    # julian_date: TDB julian epoch
    # delta_days: number of days that you want to advance the Gregorian date string by
    # time_system_string: string representation of the input gregorian_date's time system (e.g. "TDB", "UTC" etc.)

    return spice.timout((julian_date - 2451545.0) * 86400.0,
                        "YYYY Mon DD ::TDB HR:MN:SC.###### TDB")
예제 #7
0
def print_comet_mpc(c,name):
  RP,ECC,ARGP,LNODE,INC,tp = c
  t_perihelion = spice.unitim(tp,"JDTDB","ET")
  s = spice.timout(t_perihelion,"YYYY MM DD.#### ::RND ::TDB",16)
  year = int(s[0:4])
  month = int(s[5:7])
  day = float(s[8:])
  mag = 8.0
  slope = 4.0
  return '    P%s    %04d %02d %7.4f %9.6f  %8.6f  %8.4f  %8.4f  %8.4f  20171201  %4.1f %4.1f  P/%s' % (name,year,month,day,RP,ECC,ARGP,LNODE,INC,mag,slope,name)
예제 #8
0
def comet(et,p,v):
  state = [p[0],p[1],p[2],v[0],v[1],v[2]]   # km, km/s
  elts = spice.oscelt(state,et,mu)          # compute osculating Keplerian parameters from a state vector
  RP,ECC,INC,LNODE,ARGP,M0,T0,MU = elts
  a = np.abs(RP/(1-ECC))
  n = np.sqrt(MU/(a*a*a))    # rad/s
  TP = T0 - M0/n  #fixme: need a case distinction for the sign of this correction?
  RP = RP/au
  INC = rad2deg(INC)
  LNODE = rad2deg(LNODE)
  ARGP = rad2deg(ARGP)
  TP = float(spice.timout(TP,"JULIAND.######## ::TDB"))  #fixme
  return RP,ECC,ARGP,LNODE,INC,TP
예제 #9
0
def gregDateOffsetCalculator(gregorian_date, delta_days, time_system_string):

    # returns the time_system_string Gregorian date, offset from the input date string by delta_days
    # gregorian_date: SPICE compatible Gregorian date string
    # delta_days: number of days that you want to advance the Gregorian date string by
    # time_system_string: string representation of the output requested for the gregorian_date's time system (e.g. "TDB", "UTC" etc.)

    return spice.timout(
        spice.str2et(
            str(
                spice.str2et(gregorian_date) / 86400.0 + 2451545.0 +
                delta_days) + " JD TDB"),
        "YYYY Mon DD ::" + time_system_string + " HR:MN:SC.######")
예제 #10
0
def et_to_datetime(et, scale='TDB'):
    """
    convert a SPICE ephemerides epoch (TBD seconds) to a python datetime
    object. The default time scale returned will be TDB but can be set
    to any of the accepted SPICE time scales.

    Args:
        et (float): SPICE ephemerides sceonds (TBD)
        scale (str, optional): time scale of output time (default: TDB)

    Returns:
        datetime: python datetime
    """
    t = spiceypy.timout(et, 'YYYY-MON-DD HR:MN:SC.### ::{}'.format(scale), 41)
    return datetime.strptime(t, '%Y-%b-%d %H:%M:%S.%f')
예제 #11
0
파일: time.py 프로젝트: johnnycakes79/pyops
def et_to_datetime(et, scale='TDB'):
    """
    convert a SPICE ephemerides epoch (TBD seconds) to a python datetime
    object. The default time scale returned will be TDB but can be set
    to any of the accepted SPICE time scales.

    Args:
        et (float): SPICE ephemerides sceonds (TBD)
        scale (str, optional): time scale of output time (default: TDB)

    Returns:
        datetime: python datetime
    """
    t = spice.timout(et, 'YYYY-MON-DD HR:MN:SC.### ::{}'.format(scale), 41)
    return datetime.strptime(t, '%Y-%b-%d %H:%M:%S.%f')
예제 #12
0
def occultations(body1, body2, start, end):
    cnfine = spiceypy.utils.support_types.SPICEDOUBLE_CELL(MAXWIN)
    result = spiceypy.utils.support_types.SPICEDOUBLE_CELL(MAXWIN)

    # Obtain the TDB time bounds of the confinement
    # window, which is a single interval in this case.
    et0 = spiceypy.str2et(start)
    et1 = spiceypy.str2et(end)

    # Insert the time bounds into the confinement window
    spiceypy.wninsd(et0, et1, cnfine)

    # 15-minute step. Ignore any occultations lasting less than 15 minutes.
    # Units are TDB seconds.
    step = 900.0

    obsrvr = "Earth"

    # Loop over the occultation types.
    for occtype in types:
        # For each type, do a search for both transits of
        # Titan across Saturn and occultations of Titan by Saturn.
        for j in range(2):
            if not j:
                front = body1
                fframe = "IAU_" + body1
                back = body2
                bframe = "IAU_" + body2
            else:
                front = body2
                fframe = "IAU_" + body2
                back = body1
                bframe = "IAU_" + body1

            spiceypy.gfoclt(occtype, front, "ellipsoid", fframe, back,
                            "ellipsoid", bframe, "lt", obsrvr, step, cnfine,
                            result)

            # Display the results
            print()
            title = spiceypy.repmc("Condition: # occultation of # by #", "#",
                                   occtype)
            title = spiceypy.repmc(title, "#", back)
            title = spiceypy.repmc(title, "#", front)
            print(title)

            for r in result:
                print(spiceypy.timout(r, "YYYY Mon DD HR:MN:SC"))
예제 #13
0
def et2cal(time, format='UTC', support_ker=False, unload=False):
    """
    Converts Ephemeris Time (ET) into UTC or Calendar TDB (CAL) time. Accepts
    a single time or a lists of times. This function assumes that the support
    kernels (meta-kernel or leapseconds kernel) has been loaded.

    :param time: Input ET time
    :type time: Union[float, list]
    :param format: Desired output format; 'UTC' or 'CAL'
    :type format: str
    :param unload: If True it will unload the input meta-kernel
    :type unload: bool
    :return: Output time in 'UTC', 'CAL' or 'TDB'
    :rtype: Union[str, list]
    """
    timlen = 62
    out_list = []

    if support_ker:
        spiceypy.furnsh(support_ker)

    if isinstance(time, float) or isinstance(time, str):
        time = [time]

    for element in time:

        if format == 'UTC':
            out_elm = spiceypy.et2utc(element, 'ISOC', 3)

        elif format == 'CAL':
            out_elm = spiceypy.timout(element, "YYYY-MM-DDTHR:MN:SC.###::TDB",
                                      timlen)
        else:
            out_elm = element

        out_list.append(out_elm)

    if len(out_list) == 1:
        out_time = out_list[0]
    else:
        out_time = out_list

    if unload:
        spiceypy.unload(support_ker)

    return out_time
예제 #14
0
    def __init__(self, start_time, end_time, labels, fig):
        self._panel_labels = labels
        self._panel_bottom = labels[-1]
        self._start_time = start_time
        self._end_time = end_time
        self._width = fig['base'].width.value()
        self._fig = fig
        self._sec_per_cm = (end_time - start_time) / self._width
        self._ticks = None
        self._tick_labels = None
        self._minor_locator = None

        if self._sec_per_cm > (16 * 86400):
            # monthly ticks
            warnings.warn('Monthly ticks not yet implemented')
            pass
        elif self._sec_per_cm > (5 * 86400):
            # Ticks every 5 days, minor ticks every day
            tick_start_time = self.round_up_day(self._start_time)
            self._ticks = np.arange(tick_start_time, self._end_time, 5 * 86400)
            self._tick_labels = [
                spiceypy.timout(t, 'DOY') for t in self._ticks
            ]
            self._minor_locator = matplotlib.ticker.MultipleLocator(86400)
        elif self._sec_per_cm > (2 * 86400):
            # Ticks every 4 days, minor ticks every 12 hours
            tick_start_time = self.round_up_day(self._start_time)
            self._ticks = np.arange(tick_start_time, self._end_time, 4 * 86400)
            self._tick_labels = [
                spiceypy.timout(t, 'DOY') for t in self._ticks
            ]
            self._minor_locator = matplotlib.ticker.MultipleLocator(12 * 3600)
        elif self._sec_per_cm > 86400:
            # Ticks every 2 days, minor ticks every 12 hours
            tick_start_time = self.round_up_day(self._start_time)
            self._ticks = np.arange(tick_start_time, self._end_time, 2 * 86400)
            self._tick_labels = [
                spiceypy.timout(t, 'DOY') for t in self._ticks
            ]
            self._minor_locator = matplotlib.ticker.MultipleLocator(12 * 3600)
        elif self._sec_per_cm > 21600:
            # Ticks every 24 hours, minor ticks every 3 hours
            tick_start_time = self.round_up_day(self._start_time)
            self._ticks = np.arange(tick_start_time, self._end_time, 86400)
            self._tick_labels = [
                spiceypy.timout(t, 'DOY') for t in self._ticks
            ]
            self._minor_locator = matplotlib.ticker.MultipleLocator(10800)
        elif self._sec_per_cm > 3600:
            # Ticks every 3 hours, minor ticks every 30 minutes
            tick_start_time = self.round_up_day(self._start_time)
            self._ticks = np.arange(tick_start_time, self._end_time, 3 * 3600)
            self._tick_labels = [
                spiceypy.timout(t, 'DOY HR:MN') for t in self._ticks
            ]
            self._minor_locator = matplotlib.ticker.MultipleLocator(1800)
        elif self._sec_per_cm > 1800:
            # Ticks every hour, minor ticks every 10 minutes
            tick_start_time = self.round_up_day(self._start_time)
            self._ticks = np.arange(tick_start_time, self._end_time, 3600)
            self._tick_labels = [
                spiceypy.timout(t, 'DOY HR:MN') for t in self._ticks
            ]
            self._minor_locator = matplotlib.ticker.MultipleLocator(600)
        else:
            # Ticks every 10 minutes
            tick_start_time = self.round_up_day(self._start_time)
            self._ticks = np.arange(tick_start_time, self._end_time, 600)
            self._tick_labels = [
                spiceypy.timout(t, 'HR:MN') for t in self._ticks
            ]
            self._minor_locator = matplotlib.ticker.MultipleLocator(6)
예제 #15
0
def greg2Greg(gregorian_date, time_system_string):
    return spice.timout(
        spice.str2et(gregorian_date),
        "YYYY Mon DD ::" + time_system_string + " HR:MN:SC.######")
예제 #16
0
def SaveCarringtonRotations(Date0=19500101,Date1=20500101):
	'''
	Create a list of times when Venus is at a solar longitude of 0,
	defining the start of a Carrington rotation.
	
	'''

	#name the file to save the data in
	outpath = Globals.OutputPath + 'Venus/'
	if not os.path.isdir(outpath):
		os.system('mkdir -pv '+outpath)
	outfile = outpath + '0long.dat'
		
	#list the dates between date0 and date1
	dates = ListDates(Date0,Date1)
	nd = dates.size
	nt = nd*24
	
	#load the kernels
	sp.furnsh(lsk_path)
	sp.furnsh(spk_kernel)
	sp.furnsh(pck_kernel)
	sp.furnsh(hci_kernel)		
	
	#get the ets
	et0 = utc2et(dates[0],0.0)
	et = et0 + np.arange(nt,dtype='float64')*3600
	
	#get the array of longitudes
	lon = np.zeros(nt,dtype='float64')
	for i in range(0,nt):
		print('\rFinding longitude {0} of {1}'.format(i+1,nt),end='')
		pos,lt = sp.spkpos('VENUS',et[i],'IAU_SUN','NONE','SUN')
		lon[i] = np.arctan2(pos[1],pos[0])
	print('')
		
			
	#find the bits where we cross 0
	n=0
	for i in range(0,nt-1):
		print('\rFinding 0s {:6.2f}%'.format(100*np.float32((i+1))/(nt-1)),end='')
		if lon[i] > 0 and lon[i+1] <= 0:
			if i == 0:
				inds = np.array([3,2,1,0])
			elif i >= nt-2:
				inds = np.array([nt-1,nt-2,nt-3,nt-4])
			else:
				inds = np.arange(4)[::-1]+i-1
			f = InterpolatedUnivariateSpline(lon[inds],et[inds])
			if n == 0:
				ets = np.array([f(0.0)],dtype='float64')
			else:
				ets = np.append(ets,f(0.0))
			n+=1

	print('')
	
	
	#store them in a file
	f=open(outfile,'w')
	for i in range(0,n):
		print('\rSaving time {0} of {1}'.format(i+1,n),end='')
		s = sp.timout(ets[i],"YYYYMMDD HRMNSC ::RND",32)
		date,ut = s.split()
		date = np.int32(date)
		ut = TT.HHMMtoDec(np.int32(ut),ss=True)
		utc = ContUT(np.array([date]),np.array([ut]))[0]
		outstr = '{:08d} {:f} {:f}\n'.format(date,ut,utc)
		f.write(outstr)
	f.close()
	print('')

	#unload kernels
	sp.unload(lsk_path)
	sp.unload(spk_kernel)
	sp.unload(pck_kernel)	
	sp.unload(hci_kernel)
예제 #17
0
    def parse_EMTG_event(self, SampleNumber, CentralBody, myEvent):
        self.SampleNumber = SampleNumber
        self.CentralBody = CentralBody
        self.Frame = 'EMO2000'
        self.EpochETJulian = myEvent.JulianDate
        self.EpochETGregorian = spiceypy.timout(
            spiceypy.unitim(myEvent.JulianDate, 'JDTDB', 'TDB'),
            'YYYY Mon DD ::TDB HR:MN:SC')
        self.Mass = myEvent.Mass

        if 'Sun' in self.CentralBody:
            self.X = myEvent.SpacecraftState[0]
            self.Y = myEvent.SpacecraftState[1]
            self.Z = myEvent.SpacecraftState[2]
            self.VX = myEvent.SpacecraftState[3]
            self.VY = myEvent.SpacecraftState[4]
            self.VZ = myEvent.SpacecraftState[5]

        elif 'Earth' in self.CentralBody:
            self.X = myEvent.SpacecraftState[0]
            self.Y = myEvent.SpacecraftState[1]
            self.Z = myEvent.SpacecraftState[2]
            self.VX = myEvent.SpacecraftState[3]
            self.VY = myEvent.SpacecraftState[4]
            self.VZ = myEvent.SpacecraftState[5]

            rvec = numpy.array(myEvent.SpacecraftState[:3])
            vvec = numpy.array(myEvent.SpacecraftState[3:])

            r = numpy.linalg.norm(rvec)
            v = numpy.linalg.norm(vvec)

            h = numpy.cross(rvec, vvec)

            hhat = h / numpy.linalg.norm(h)

            r_dot_v = numpy.dot(rvec, vvec)

            mu = 398600.435436096

            evec = 1.0 / mu * ((v * v - mu / r) * rvec - r_dot_v * vvec)

            e = numpy.linalg.norm(evec)

            Beta = numpy.arccos(1.0 / e)

            h_hat_cross_e = numpy.cross(hhat, evec)

            #compute b-plane coordinates
            Shat = numpy.cos(Beta) * evec / e + numpy.sin(
                Beta) * h_hat_cross_e / numpy.linalg.norm(h_hat_cross_e)

            khat = numpy.array([0.0, 0.0, -1.0])

            T = numpy.cross(Shat, khat)

            That = T / numpy.linalg.norm(T)

            Rhat = numpy.cross(Shat, That)

            Bhat = numpy.cross(Shat, hhat)

            a = 1.0 / (2.0 / r - v * v / mu)

            b = a * numpy.sqrt(e * e - 1.0)

            B = Bhat * b

            self.BR = numpy.dot(B, Rhat)
            self.BT = numpy.dot(B, That)

        else:
            #if the central body is not the Sun then the we are whacking a target
            self.X = 0.0
            self.Y = 0.0
            self.Z = 0.0

            #v-infinity is opposite delta-v
            self.VX = -myEvent.DeltaVorThrustVectorControl[0]
            self.VY = -myEvent.DeltaVorThrustVectorControl[1]
            self.VZ = -myEvent.DeltaVorThrustVectorControl[2]

            #compute the encounter state in the target frame
            encounter_radius = 1000.0
            if ('Polymele' in self.CentralBody):
                encounter_radius = 399.0

            Spacecraft_State_Target_Frame = numpy.array(
                [0.0, 0.0, encounter_radius])

            #compute the basis vectors of the target frame
            Vinfinity = numpy.array([self.VX, self.VY, self.VZ])
            VectorToSun = numpy.array([
                -myEvent.SpacecraftState[0], -myEvent.SpacecraftState[1],
                -myEvent.SpacecraftState[2]
            ])

            Xhat = Vinfinity / numpy.linalg.norm(Vinfinity)
            Yhat = numpy.cross(VectorToSun, Xhat) / numpy.linalg.norm(
                numpy.cross(VectorToSun, Xhat))
            Zhat = numpy.cross(Xhat, Yhat)

            R_from_Ecliptic_to_Target = numpy.matrix([Xhat.T, Yhat.T, Zhat.T])

            R_from_Target_to_Ecliptic = R_from_Ecliptic_to_Target.T

            #rotate the target state into the ecliptic frame
            Spacecraft_State_Ecliptic_Frame = R_from_Target_to_Ecliptic * numpy.matrix(
                Spacecraft_State_Target_Frame).T

            #set the output states
            self.X = Spacecraft_State_Ecliptic_Frame[0]
            self.Y = Spacecraft_State_Ecliptic_Frame[1]
            self.Z = Spacecraft_State_Ecliptic_Frame[2]

            #compute b-plane coordinates
            Shat = Vinfinity / numpy.linalg.norm(Vinfinity)
            hhat = numpy.cross(numpy.array(Spacecraft_State_Ecliptic_Frame.T),
                               Shat) / encounter_radius

            Bhat = numpy.cross(Shat, hhat)

            khat = numpy.array([0.0, 0.0, 1.0])

            That = numpy.cross(Shat, khat)

            Rhat = numpy.cross(Shat, That)

            Bmagnitude = numpy.linalg.norm(
                numpy.cross(
                    Shat,
                    numpy.cross(numpy.array(Spacecraft_State_Ecliptic_Frame.T),
                                Shat)))
            self.BR = Bmagnitude * numpy.dot(Bhat, Rhat)
            self.BT = Bmagnitude * numpy.dot(Bhat, That)
예제 #18
0
### Convert list to string
s_kernels = '[{}]'.format(','.join(bn_kernels))

### Constants:  NH SCLK sub-ticks per NH tick second
tps = 5e4

met0, et0, rate0, met1, et1, rate1 = sp.gdpool('SCLK01_COEFFICIENTS_98', 0, 6)

assert met0 == 0

correct_et0 = (et1 - ((met1 - met0) * rate0 / tps))
error0 = et0 - correct_et0

tpictr = '@YR-MON-DD-HR:MN:SC.##### ::TDB ::RND'

correct_tdb0 = sp.timout(correct_et0, tpictr, 99)

print(dict(error0=error0, correct_tdb0=correct_tdb0))

abscissa = list()
ordinate = list()

et1s = [et1, et0 + ((met1 - met0) * rate0 / tps)]
start_et = min(et1s) - abs(error0)
stop_et = max(et1s) + abs(error0)

det = 0.
ddet = 0.1

et = start_et + det
예제 #19
0
### Convert list to string
s_kernels = '[{}]'.format(','.join(bn_kernels))

### Constants:  NH SCLK sub-ticks per NH tick second, seconds per year
tps, spy = 5e4, sp.jyear()

### Interpret datetime.datetime string as UTC and convert to MET seconds
date2met = lambda dayt: sp.sce2t(
    -98, sp.utc2et(dayt.strftime('%Y-%m-%dT%H:%M:%S'))) / tps

### Fudge factor; NH MET clock shifts 2s during the launch day
met_fudge = -2

### ET and date and MET, all 1d after SCLK zero time
et = sp.sct2e(-98, 0.) - met_fudge
s_0 = sp.timout(et, 'Sun MON DD HR:MN:SC YYYY', 99)
date0 = datetime.datetime.strptime(s_0, '%c')
met0 = date2met(date0) + met_fudge

### Year, as a floating point value, at that time
offset_to_launch = 2000 + (
    (date0 - datetime.datetime(2000, 1, 1, 12)).total_seconds() / spy)

### Time of leapsecond events, from LSK
leapsecs_met_y = [
    offset_to_launch + (sp.sce2t(-98, sp.utc2et(s.strip())) / (tps * spy))
    for s in """
2009-JAN-1/00:00:00
2012-JUL-1/00:00:00
2015-JUL-1/00:00:00
2017-JAN-1/00:00:00
예제 #20
0
파일: espec.py 프로젝트: npbarnes/pd-idl
def _espec_v4(data, options=None):
    if options is None:
        options= {'colorbars':['Blues','Greens','Reds']}

    # Load data from IDL
    spectrograms_by_species = data['spectrograms_by_species']
    t = data['times']
    x = data['positions'][0,:]
    y = data['positions'][1,:]
    z = data['positions'][2,:]
    o = data['orientations']
    ebins = data['ebins']

    # Separate parts
    H = spectrograms_by_species[:,:,0]
    He = spectrograms_by_species[:,:,1]
    CH4 = spectrograms_by_species[:,:,2]

    cnt_arr = H+He+CH4

    # Build masked arrays for plotting the dominant species
    mH = masked_array(cnt_arr, mask=(~logical_and(H>He,H>CH4)))
    mHe = masked_array(cnt_arr, mask=(~logical_and(He>H,He>CH4)))
    mCH4 = masked_array(cnt_arr, mask=~logical_and(CH4>H,CH4>He))
    
    # Setup subplot and colorbar axes
#    fig = plt.figure(figsize = (rcParams['figure.figsize'][0], 2*rcParams['figure.figsize'][1]))
#    gs = gridspec.GridSpec(8,1)
#    ax_spec  = plt.subplot(gs[0,0])
#    ax_theta = plt.subplot(gs[1,0], sharex=ax_spec)
#    ax_phi   = plt.subplot(gs[2,0], sharex=ax_spec)
#    ax_spin  = plt.subplot(gs[3,0], sharex=ax_spec)
#
#    ax_xy    = plt.subplot(gs[4:6,0])
#    ax_xz    = plt.subplot(gs[6:8,0], sharex=ax_xy)


    fig, (ax_spec, ax_theta, ax_phi, ax_spin, ax_xy, ax_xz) = plt.subplots(nrows=6, sharex=True, 
            gridspec_kw={'height_ratios':[1,1,1,1,2,3]}, 
            figsize=(rcParams['figure.figsize'][0], 2.25*rcParams['figure.figsize'][1]))

    fig.subplots_adjust(right=0.8, hspace=0.05)

    spec_pos = ax_spec.get_position()
    cbar_CH4 = fig.add_axes([spec_pos.x1+.01, spec_pos.y0+.01, 0.1/3, spec_pos.height-.02])
    cbar_CH4_pos = cbar_CH4.get_position()
    cbar_He = fig.add_axes([cbar_CH4_pos.x1, spec_pos.y0+.01, 0.1/3, spec_pos.height-.02])
    cbar_He_pos = cbar_He.get_position()
    cbar_H = fig.add_axes([cbar_He_pos.x1, spec_pos.y0+.01, 0.1/3,spec_pos.height-.02])

    # Plot spectrograms and make colorbars
    Hhist = ax_spec.pcolormesh(t, ebins, mH, norm=LogNorm(), cmap=options['colorbars'][0],
            vmin=1e-3, vmax=1e4)
    Hcb = fig.colorbar(Hhist, cax=cbar_H)
    Hcb.ax.minorticks_on()

    Hehist = ax_spec.pcolormesh(t, ebins, mHe, norm=LogNorm(), cmap=options['colorbars'][1],
            vmin=1e-3, vmax=1e4)
    Hecb = fig.colorbar(Hehist, cax=cbar_He, format="")

    CH4hist = ax_spec.pcolormesh(t, ebins, mCH4, norm=LogNorm(), cmap=options['colorbars'][2],
            vmin=1e-3, vmax=1e4)
    CH4cb = fig.colorbar(CH4hist, cax=cbar_CH4, format="")

    # Plot orientations
    ax_theta.plot(t, o[0], marker='o', markersize=1.3, linestyle='None', color='black')
    ax_phi.plot(t,   o[1], marker='o', markersize=1.3, linestyle='None', color='black')
    ax_spin.plot(t,  o[2], marker='o', markersize=1.3, linestyle='None', color='black')

    ax_theta.set_ylim(-180,180)
    ax_phi.set_ylim(-180,180)
    ax_spin.set_ylim(-180,180)

    # Plot positions
    h = hr('/home/nathan/data/2017-Wed-Aug-30/pluto-1/databig','np')
    n = h.get_last_timestep()[-1]

    # Get grid spacing
    qx = h.para['qx']
    qy = h.para['qy']
    qzrange = h.para['qzrange']

    # Find the center index of the grid
    cx = h.para['nx']/2
    cy = h.para['ny']/2
    cz = h.para['zrange']/2

    # the offset of pluto from the center isn't always availible
    try:
        po = h.para['pluto_offset']
    except KeyError:
        print("Couldn't get pluto_offset. It has been assumed to be 30, but it probably isn't.")
        po = 30

    # Set constatnt for Pluto radius 
    Rp = 1187. # km

    # Shift grid so that Pluto lies at (0,0,0) and convert from km to Rp
    qx = (qx - qx[len(qx)/2 + po])/Rp
    qy = (qy - qy[len(qy)/2])/Rp
    qzrange = (qzrange - qzrange[len(qzrange)/2])/Rp

    qt = [NH_tools.time_at_pos(x*Rp) for x in qx]

    T,Y = np.meshgrid(qt,qy)
    ax_xy.pcolormesh(T,Y,n[:,:,cz].transpose(), cmap='viridis', norm=LogNorm())

    T,Z = np.meshgrid(qt,qzrange)
    ax_xz.pcolormesh(T,Z,n[:,cy,:].transpose(), cmap='viridis', norm=LogNorm())

    ax_xy.plot(t, y/Rp-np.max(qy), color='black', linewidth=2)
    ax_xz.plot(t, np.zeros(z.shape), color='black', linewidth=2)

    # Set title, labels and adjust figure
    ax_spec.set_xlim(np.min(t), np.max(t))
    ax_spec.set_ylim(5e1, 1e4)
    ax_spec.set_title("Synthetic SWAP Energy Spectrogram", y=1.4)
    Hecb.ax.set_title('COIN (Hz)', fontdict={'fontsize':'small'})
    ax_spec.set_yscale('log')
    ax_spec.set_ylabel('Energy/Q ($eV/q$)')
    ax_theta.set_ylabel('Sun Theta\nAngle (deg)')
    ax_phi.set_ylabel('Sun Phi\nAngle (deg)')
    ax_spin.set_ylabel('Spin\nAngle (deg)')
    ax_xz.set_xlabel('Time (UTC)')

    ax_xy.set_ylabel('Y ($R_p$)')
    ax_xz.set_ylabel('Z ($R_p$)')
    ax_xy.set_ylim(np.min(qy), np.max(qy))
    ax_xz.set_ylim(1.5*np.min(qy), 1.5*np.max(qy))

    ax_xz.set_xticklabels([sp.timout(et, 'HR:MN:SC') for et in ax_spec.get_xticks()], rotation=-20, horizontalalignment='left')

    ax_twin = ax_spec.twiny()
    ax_twin.set_xlabel('X ($R_p$)')
    ax_twin.set_xlim(*ax_spec.get_xlim())
    ax_twin.set_xticks(ax_spec.get_xticks())
    ax_twin.set_xticklabels(['{0:.2f}'.format(NH_tools.pos_at_time(et)/1187) for et in ax_spec.get_xticks()], y=1.05)

    # This breaks the convention of previous versions
    return fig, None
예제 #21
0
    ra = ra0.hms()
    dec = dec0.dms()
    dra = (ra1._degrees - ra0._degrees) / 5  # fixme: take modulo 24 hours
    ddec = (dec1.degrees - dec0.degrees) / 5
    dra = dra / (180 / np.pi)
    ddec = ddec / (180 / np.pi)

    number = satellite.model.satnum

    err0, err1, elts = orbit_comet.comet_orbit_search(
        et + acp_time_bias + acp_lag_bias, ra, dec, dra, ddec)

    print('; satellite: <%s> alt: %.0f az: %.0f' %
          (satellite.name, alt.degrees, az.degrees))
    print('; time: %s' %
          spice.timout(et, "YYYY-MM-DDTHR:MN:SC.### ::RND ::UTC", 24))
    print('; ra %d %d %.2f   dec %d %d %.2f   dra %.3f ddec %.3f' %
          (ra[0], ra[1], ra[2], dec[0], dec[1], dec[2], dra *
           (180 / np.pi) * 3600, ddec * (180 / np.pi) * 3600))
    x = orbit_comet.print_comet_mpc(elts, number)
    print('#INTERVAL %d' % t_small_exposure
          )  # take a short exposure after a (potentially) large slew
    print(
        '#TRACKOFF'
    )  # no orbital tracking: round stars (possibly useful for an initial astrometric estimate), trailed satellite (if visible)
    print(x)
    print('#INTERVAL %d' %
          t_large_exposure)  # take the main exposure after a smaller slew
    print('#TRACKON')  # orbital tracking: round satellite, trailed stars
    print(x)
예제 #22
0
dpi  = 50  # Size of the output picture. 200 for cathy. 50 for web. 100 for high-res web.

file_out_base = os.path.join(dir_frames, f'movie_w{width}_d{dpi}_{cmap}')

file_out_gif = f'{file_out_base}_n{len(reqids)}_f{fps}.gif'

for i,reqid_i in enumerate(reqids):

    # Convert from DOY to calendar day

    file_out_frame = f'{file_out_base}_{i:03}.png'
    
    doy = reqid_i.split('_')[-1][-3:]
    
    et = sp.utc2et(f'2018::{doy} 12:00:00')
    utc = sp.timout(et, "Month DD, YYYY", 20)
    utc = utc.replace(' 0', ' ')
    
    # Draw the frame

    f = plt.figure(frameon=False, figsize=(10, 5), dpi=dpi)  # Change dpi to change output size
    # f.patch.set_facecolor('pink')
    canvas_width, canvas_height = f.canvas.get_width_height()
    ax = f.add_axes([0, 0, 1, 1])
    ax.axis('off')
    # ax.set_facecolor('pink')

    plt.subplot(1,2,1)
    ax = plt.gca()
    # ax.set_facecolor('pink')
    
예제 #23
0
def print_comet_horizons(c,name,et):
  RP,ECC,ARGP,LNODE,INC,TP = c
  T0 = float(spice.timout(et,"JULIAND.#### ::TDB"))
  print("EPOCH=%.4f EC=%.6f QR=%.6f TP=%.4f OM=%.4f W=%.4f IN=%.4f" % (T0,ECC,RP,TP,LNODE,ARGP,INC))
# just run cosmo
import spiceypy as spice
from os import *
import main
A = 657605100
B = 658560507
C = 659891734
D = 660118099
et = A
here = path.abspath(path.dirname(__file__))
PathtoMetaKernel1 = here + '/TGO/mk/em16_plan.tm'
PathtoMetaKernel2 = here + '/MEX/krns/mk/MEX_OPS.tm'
spice.furnsh(PathtoMetaKernel1)
spice.furnsh(PathtoMetaKernel2)
sv = main.SpiceVariables()
main.CosmographiaCatalogFormer(et, sv)
JulianTime = spice.timout(et, sv.TFMT)
print('Gas Volumes Visualised for A ' + JulianTime)
def CosmographiaCatalogFormer(et, sv):

    # Select and occultation of interest, calculate the shape of it's profile, then add this to a dateframe

    result = occgradient(sv.front, et, sv.fframe, sv.obs, sv.target)
    profile = result[0]
    lowesttime = result[1]
    highesttime = result[2]
    lowesttimeFMT = spice.timout((et - result[1]), sv.TFMT)
    highesttimeFMT = spice.timout((et - result[2]), sv.TFMT)
    endtimeFMT = spice.timout(et, sv.TFMT)
    profile = np.transpose(profile)
    profiledataframe = pd.DataFrame(profile[:][0:highesttime],
                                    columns=['X', 'Y', 'Z'])
    # Example polygon velocities [this effects the dynamic texture of the profile, purely aesthetic]. These values have
    # been chosen to be slow and variable
    vs = np.array([[1.4236, -2.4657, 6.3948], [1.6404, -2.2997, 6.4047],
                   [1.8386, -2.1150, 6.4145], [2.0166, -1.9136, 6.4243],
                   [2.1730, -1.6977, 6.4339], [2.3068, -1.4696, 6.4435],
                   [2.4170, -1.2315, 6.4530], [2.5029, -0.9859, 6.4625],
                   [2.5029, -0.9859, 6.4625], [2.5029, -0.9859, 6.4625]])

    # Iterate the polygon velocity states to be the length of profile and then combine with the positions
    vs = vs.repeat(200, axis=0)
    vt = vs[:][0:highesttime]
    velocitiesdataframe = pd.DataFrame(vt, columns=['dX', 'dY', 'dZ'])
    finalprofile = pd.concat([profiledataframe, velocitiesdataframe], axis=1)

    # Construct a JSON template depending on the size of the profile, split into sections of 10 points [smaller sections,
    # more smoothly the profile forms over time]
    blockcount = math.floor(highesttime / 10) * 10
    i = 0
    while i < (blockcount / 10):
        JS.JSONiterated = JS.JSONiterated + JS.JSONiterable
        i = i + 1
    JSONtemplate = JS.JSONstart + JS.JSONiterated + JS.JSONend

    template = json.loads(
        JSONtemplate
    )  # load the template created above  so it can be editted as JSON

    itemcounter = 0

    # convert states into single string for cosmographia to understand [cosmogrpahia computes as
    # 3 postions and 3 velocities, no need for '\n']
    for i in range(0, blockcount, 10):
        block = (finalprofile[i:i + 10].to_numpy()) * (
            -1)  # inverse due to reference frame inversion
        ProfileBlock = block.tolist()  # convert to list for the JSON format

        states = []
        for p in range(10):
            states.extend(
                ProfileBlock[p]
            )  # turn states into one long line to remove the '\n', which confuses cosmographia

        # vary the spread and intensity of the profile as it increases with alitude and the atmosphere becomes less dense
        profilespread = math.floor(itemcounter * (5 / (blockcount / 10)))
        profileintensity = math.floor(itemcounter * (30 / (blockcount / 10)))

        # edit the large JSON file iterativly, with 'itemcounter'moving down the JSON items (blocks of 10 profile points).
        # adding the states(position and velocity of the polygons), name of item (so comsmographia doesnt overwrite them),
        # the start time, end time(epoch of occultation), the spread and finally the intensity of colour
        template['items'][itemcounter]['geometry']['emitters'][0]['generator'][
            'states'] = states
        template['items'][itemcounter]['name'] = 'Profile ' + str(itemcounter)
        template['items'][itemcounter]['geometry']['emitters'][0][
            'startTime'] = spice.timout((et - i), sv.TFMT)
        template['items'][itemcounter]['geometry']['emitters'][0][
            'endTime'] = endtimeFMT
        template['items'][itemcounter]['geometry']['emitters'][0][
            'velocityVariation'] = (profilespread + 1)
        template['items'][itemcounter]['geometry']['emitters'][0][
            'endSize'] = profileintensity
        itemcounter = itemcounter + 1

    # serialise the formed profile into a .json that cosmographia can read
    with open(' Profile.json', 'w') as file:
        json.dump(template, file, indent=3)