def __get_pixel_values(self, et, pixel_vector): try: spoint, trgepc, srfvec = \ self.__compute_pixel_surface_intercept(et, pixel_vector) trgepc, srfvec, phase, solar, emission = \ self.__compute_illumination_angles(et, spoint) except spiceypy.utils.exceptions.NotFoundError: return np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, \ np.nan rpoint, colatpoint, lonpoint = spice.recsph(spoint) if lonpoint < 0: lonpoint += 2 * np.pi hr, mn, sc, time, ampm = spice.et2lst( et, self.__body, lonpoint, 'planetocentric', timlen=256, ampmlen=256) latitude = np.degrees(np.pi / 2 - colatpoint) longitude = np.degrees(lonpoint) local_time = hr + mn / 60 + sc / 3600 solar_zenith_angle = np.degrees(solar) emission_angle = np.degrees(emission) phase_angle = np.degrees(phase) map_lat = int(np.round(np.degrees(colatpoint), 1) * 10) map_lon = int(np.round(np.degrees(lonpoint), 1) * 10) if map_lat == 1800: map_lat = 1799 if map_lon == 3600: map_lon = 3599 geography_map = self.__geography_map[map_lat, map_lon] field_map = self.__field_map[map_lat, map_lon] return latitude, longitude, local_time, solar_zenith_angle, \ emission_angle, phase_angle, geography_map, field_map
def vector_params(self, vector) : ret = np.full(shape = [len(self.keys)], fill_value = -1000.0) # Calculate the distance of the boresight and the center of the target origin = np.array([0.0, 0.0, 0.0]) nearpoint, rayradius = spice.nplnpt(self.scloc, vector, origin) # Get the intercept to calculate the radius of of the target normal = spice.surfpt(origin, 1000.0 * nearpoint, self.radii[0], self.radii[1], self.radii[2]) ret[self.map['limb_distance']] = rayradius - spice.vnorm(normal) # Calculate the 'occultation' latitude and longitude ret[self.map['bodyintercept']], ret[self.map['limb_lat']], ret[self.map['limb_lon']] = spice.reclat(nearpoint) # Test if the boresight intersects with our target surface try: point = spice.surfpt(self.scloc, vector, self.radii[0], self.radii[1], self.radii[2]) intercept = True except: intercept = False if (intercept) : # Get some angles ret[self.map['phase']], ret[self.map['incidence']], ret[self.map['emission']] = spice.illum(self.target, self.et , self.abcorr, self.spacecraft, point) # Calculate the planetocentric coordinates distance, ret[self.map['lon']], ret[self.map['lat']] = spice.reclat(point) ret[self.map['losdist']] = spice.vnorm(self.scloc - point) # Calculate the planetographic coordinates ret[self.map['lon_graphic']], ret[self.map['lat_graphic']], bodyintercept = spice.recpgr(self.target, point, self.radii[0], self.flattening) # Get the localtime, and convert to decimal hours hr, min, sc, time, ampm = spice.et2lst(self.et, self.target_id, ret[self.map['lon']], 'PLANETOCENTRIC') ret[self.map['localtime']] = hr + min / 60.0 + sc / 3600.0 # For the angles, convert radians to degrees for key in self.angles : if (ret[self.map[key]] != -1000.0) : ret[self.map[key]] = np.rad2deg(ret[self.map[key]]) # Makes sure longitudes wrap 0 to 360, spice returns the Earth-like -180 to 180. longitudes = ['lon', 'limb_lon', 'lon_graphic'] for key in longitudes : ret[self.map[key]] = ret[self.map[key]] % 360 return np.array(ret)
def localST(et,lon): """ Local Solar time and hour angle of the sun et: Ephemeris time lon: Longitude (in degrees) """ import spiceypy as sp # Local solar time lst=sp.et2lst(et,399,lon*DEG,"PLANETOGRAPHIC",51,51) # Hour angle hsun=numpy.mod((s2d(lst[0],lst[1],lst[2])-12.0)/SIDFAC*15,360) return lst,hsun
def sc_pos(self, timestr): # Convert the timestring to ephemeris time self.et = spice.str2et(str(timestr)) self.et = self.et + self.time_offset self.data['sc_wrt_planet'], self.data['target_light_time'] = spice.spkpos(self.spacecraft, self.et, self.iref, 'NONE', self.target) self.data['target_distance'] = spice.vnorm(self.data['sc_wrt_planet']) self.data['sc_wrt_sun'], light_times = spice.spkpos(self.spacecraft, self.et, self.iref, 'NONE', 'SUN') #self.ticks = spice.sce2t(self.sc_id, self.et) # Retrieve the position of the spacecraft relative to the target state, self.ltcorr = spice.spkezr(self.target, self.et, self.iref, self.abcorr, self.spacecraft) scloc = state[0:3] # Get the sub-spacecraft coordinates point, epoch, vector = spice.subpnt('NEAR POINT/ELLIPSOID', self.target, self.et, self.framestring, self.abcorr, self.spacecraft) self.distance, self.data['lon_sc'], self.data['lat_sc'] = spice.reclat(point) # Get the localtime of the spaceship hr, min, sc, time, ampm = spice.et2lst(self.et, self.target_id, self.data['lon_sc'], 'PLANETOCENTRIC') self.data['localtime_sc'] = hr + min / 60.0 + sc / 3600.0 # Get the subsolar coordinates point, epoch, vector = spice.subslr('NEAR POINT/ELLIPSOID', self.target, self.et, self.framestring, self.abcorr, self.spacecraft) distance, self.data['lon_sun'], self.data['lat_sun'] = spice.reclat(point) # Convert angles from radians to degrees for key in ['lat_sc', 'lon_sc', 'lat_sun', 'lon_sun'] : self.data[key] = np.rad2deg(self.data[key]) for key in ['lon_sc', 'lon_sun'] : self.data[key] = self.data[key] % 360 state_planet = spice.spkssb(self.target_id, self.et, self.iref) inert2p = spice.pxform(self.iref, self.framestring, self.et) self.scloc = np.matmul(-inert2p, scloc) self.i2p = spice.pxform(self.instrument, self.framestring, self.et) return self.data
def geometry(et, bsight, target, frame, sensor, observer=''): if not observer: observer = sensor # Time tag [UTC] # pixel id [(x,y)] # corner id [(x,y)] # Requested geometry # lat lon intersection (planetocentric) # lat lon subspacecraft # lat lon subsolar # target distance intersection # target angular diameter # local solar time intersection # phase angle intersection # emission angle intersection # incidence angle intersection # # We retrieve the camera information using GETFOV. More info available: # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/getfov_c.html # sensor_id = spiceypy.bodn2c(sensor) (shape, sensor_frame, ibsight, vectors, bounds) = spiceypy.getfov(sensor_id, 100) visible = spiceypy.fovtrg(sensor, target, 'ELLIPSOID', frame, 'LT+S', observer, et) if not visible: return 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 tarid = spiceypy.bodn2c(target) n, radii = spiceypy.bodvrd(target, 'RADII', 3) re = radii[0] rp = radii[2] f = (re - rp) / re try: # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/sincpt_c.html # # For each pixel we compute the possible intersection with the target, if # the target is intersected we then compute the illumination angles. We # use the following SPICE APIs: SINCPT and ILLUMF # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/sincpt_c.html # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/illumf_c.html # (spoint, trgepc, srfvec) = \ spiceypy.sincpt('ELLIPSOID', target, et, frame, 'LT+S', observer, sensor_frame, bsight) (tarlon, tarlat, taralt) = spiceypy.recgeo(spoint, re, f) tardis = spiceypy.vnorm(srfvec) # # Angular diameter # tarang = np.degrees( 2 * np.arctan(max(radii) / spiceypy.vnorm(spoint + srfvec))) # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/illumf_c.html # (trgenpc, srfvec, phase, incdnc, emissn, visiblef, iluminatedf) = \ spiceypy.illumf('ELLIPSOID', target, 'SUN', et, frame, 'LT+S', observer, spoint) phase *= spiceypy.dpr() incdnc *= spiceypy.dpr() emissn *= spiceypy.dpr() # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/et2lst_c.html # # VARIABLE I/O DESCRIPTION # -------- --- -------------------------------------------------- # et I Epoch in seconds past J2000 epoch. # body I ID-code of the body of interest. # lon I Longitude of surface point (RADIANS). # type I Type of longitude "PLANETOCENTRIC", etc. # timlen I Available room in output time string. # ampmlen I Available room in output `ampm' string. # hr O Local hour on a "24 hour" clock. # mn O Minutes past the hour. # sc O Seconds past the minute. # time O String giving local time on 24 hour clock. # ampm O String giving time on A.M./ P.M. scale. (hr, mn, sc, ltime, ampm) = \ spiceypy.et2lst(et, tarid, tarlon, 'PLANETOCENTRIC', 80, 80) # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/subpnt_c.html # # Variable I/O Description # -------- --- -------------------------------------------------- # method I Computation method. # target I Name of target body. # et I Epoch in TDB seconds past J2000 TDB. # fixref I Body-fixed, body-centered target body frame. # abcorr I Aberration correction flag. # obsrvr I Name of observing body. # spoint O Sub-observer point on the target body. # trgepc O Sub-observer point epoch. # srfvec O Vector from observer to sub-observer point # (spoint, trgepc, srfev) = \ spiceypy.subpnt('INTERCEPT/ELLIPSOID', target, et, frame, 'LT+S', observer) (sublon, sublat, subalt) = spiceypy.recgeo(spoint, re, f) # # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/subslr_c.html # # Variable I/O Description # -------- --- -------------------------------------------------- # method I Computation method. # target I Name of target body. # et I Epoch in ephemeris seconds past J2000 TDB. # fixref I Body-fixed, body-centered target body frame. # abcorr I Aberration correction. # obsrvr I Name of observing body. # spoint O Sub-solar point on the target body. # trgepc O Sub-solar point epoch. # srfvec O Vector from observer to sub-solar point. # (spoint, trgepc, srfev) = \ spiceypy.subslr('INTERCEPT/ELLIPSOID', target, et, frame, 'LT+S', observer) (sunlon, sunlat, sunalt) = spiceypy.recgeo(spoint, re, f) return tarlon, tarlat, sublon, sublat, sunlon, sunlat, tardis, tarang, ltime, phase, emissn, incdnc except: return 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
def highres_swath_geometry(self, hdul, map_data, res=200): """ Generates an artificial high-resolution slit, calculates viewing geometry and surface-intercept map. Parameters ---------- hdul : HDUList Opened FITS file. res : int, optional The desired number of artificial elements along the slit. Defaults to 200. Returns ------- latitude : array Array of latitudes for the centers of each high-resolution artificial pixel. NaNs if pixel doesn't intercept the surface of Mars. longitude : array Array of longitudes for the centers of each high-resolution artificial pixel. NaNs if pixel doesn't intercept the surface of Mars. sza : array Array of solar zenith angles for the centers of each high-resolution artificial pixel. NaNs if pixel doesn't intercept the surface of Mars. ea pa local_time : array Array of local times for the centers of each high-resolution artificial pixel. NaNs if pixel doesn't intercept the surface of Mars. x : array Horizontal coordinate edges in angular space. Has shape (n+1, m+1) for geometry arrays with shape (n,m). y : array Vertical coordinate edges in angular space. Has shape (n+1, m+1) for geometry arrays with shape (n,m). cx : array Horizontal coordinate centers in angular space. Same shape as geometry arrays. cy : array Vertical coordinate centers in angular space. Same shape as geometry arrays. context_map : array High-resolution image of the Mars surface as intercepted by the swath. RGB tuples with shape (n,m,3). """ # get swath vectors, ephemeris times, and mirror angles vec = hdul['pixelgeometry'].data['pixel_vec'] et = hdul['integration'].data['et'] # get dimensions of the input data n_int = hdul['integration'].data.shape[0] n_spa = len(hdul['binning'].data['spapixlo'][0]) # set the high-resolution slit width and calculate the number of high-resolution integrations hifi_spa = res hifi_int = int(hifi_spa / n_spa * n_int) # make arrays of ephemeris time and array to hold the new swath vector calculations # here thru 481 just interpolate et_arr and vec_arr onto new grid (int, pos) and (int, pos, 3) adn they're all just center values et_arr = np.expand_dims(et, 1) * np.ones((n_int, n_spa)) et_arr = resize(et_arr, (hifi_int, hifi_spa), mode='edge') vec_arr = np.zeros((hifi_int + 1, hifi_spa + 1, 3)) # make an artificially-divided swath and create new array of swath vectors if self.__flip: lower_left = vec[0, :, 0, 0] upper_left = vec[-1, :, 0, 1] lower_right = vec[0, :, -1, 2] upper_right = vec[-1, :, -1, 3] else: lower_left = vec[0, :, 0, 1] upper_left = vec[-1, :, 0, 0] lower_right = vec[0, :, -1, 3] upper_right = vec[-1, :, -1, 2] for e in range(3): a = np.linspace(lower_left[e], upper_left[e], hifi_int + 1) b = np.linspace(lower_right[e], upper_right[e], hifi_int + 1) vec_arr[:, :, e] = np.array( [np.linspace(i, j, hifi_spa + 1) for i, j in zip(a, b)]) # resize array to extract centers vec_arr = resize(vec_arr, (hifi_int, hifi_spa, 3), anti_aliasing=True) # make empty arrays to hold geometry calculations latitude = np.zeros((hifi_int, hifi_spa)) * np.nan longitude = np.zeros((hifi_int, hifi_spa)) * np.nan sza = np.zeros((hifi_int, hifi_spa)) * np.nan phase_angle = np.zeros((hifi_int, hifi_spa)) * np.nan emission_angle = np.zeros((hifi_int, hifi_spa)) * np.nan local_time = np.zeros((hifi_int, hifi_spa)) * np.nan context_map = np.zeros((hifi_int, hifi_spa, 4)) * np.nan # calculate intercept latitude and longitude using SPICE, looping through each high-resolution pixel target = 'Mars' frame = 'IAU_Mars' abcorr = 'LT+S' observer = 'MAVEN' body = 499 # Mars IAU code for i in range(hifi_int): for j in range(hifi_spa): et = et_arr[i, j] los_mid = vec_arr[i, j, :] # try to perform the SPICE calculations and record the results try: # calculate surface intercept spoint, trgepc, srfvec = spice.sincpt( 'Ellipsoid', target, et, frame, abcorr, observer, frame, los_mid) # calculate illumination angles trgepc, srfvec, phase_for, solar, emissn = spice.ilumin( 'Ellipsoid', target, et, frame, abcorr, observer, spoint) # convert from rectangular to spherical coordinates rpoint, colatpoint, lonpoint = spice.recsph(spoint) # convert longitude from domain [-pi,pi) to [0,2pi) if lonpoint < 0.: lonpoint += 2 * np.pi # convert ephemeris time to local solar time hr, mn, sc, time, ampm = spice.et2lst(et, body, lonpoint, 'planetocentric', timlen=256, ampmlen=256) # convert spherical coordinates to latitude and longitude in degrees latitude[i, j] = np.degrees(np.pi / 2 - colatpoint) longitude[i, j] = np.degrees(lonpoint) # convert illumination angles to degrees and record sza[i, j] = np.degrees(solar) phase_angle[i, j] = np.degrees(phase_for) emission_angle[i, j] = np.degrees(emissn) # convert local solar time to decimal hour local_time[i, j] = hr + mn / 60 + sc / 3600 # convert latitude and longitude to pixel coordinates map_lat = int(np.round(np.degrees(colatpoint), 1) * 10) map_lon = int(np.round(np.degrees(lonpoint), 1) * 10) # make a corresponding magnetic field topology map context_map[i, j] = map_data[map_lat, map_lon] # if the SPICE calculation fails, this (probably) means it didn't intercept the planet except: # This pixel (or the vector) didn't intercept the planet pass # get mirror angles angles = hdul['integration'].data[ 'mirror_deg'] * 2 # convert from mirror angles to FOV angles dang = np.diff(angles)[0] # create an meshgrid of angular coordinates for the high-resolution pixel edges x, y = np.meshgrid( np.linspace(0, self.__slit_width, hifi_spa + 1), np.linspace(angles[0] - dang / 2, angles[-1] + dang / 2, hifi_int + 1)) # calculate the angular separation between pixels dslit = self.__slit_width / hifi_spa # create an meshgrid of angular coordinates for the high-resolution pixel centers cx, cy = np.meshgrid( np.linspace(0 + dslit, self.__slit_width - dslit, hifi_spa), np.linspace(angles[0], angles[-1], hifi_int)) # beta-flip the coordinate arrays if necessary if self.__flip: x = np.fliplr(x) y = (np.fliplr(y) - 90) / (-1) + 90 cx = np.fliplr(cx) cy = (np.fliplr(cy) - 90) / (-1) + 90 # convert longitude to [-180,180) longitude[np.where(longitude > 180)] -= 360 # return the geometry and coordinate arrays # cx, cy is for a lat/lon grid on top of the map (50, 1) --> (200, 4) # all but x, y, context_map is (n_integrations, n_positions) # the context map has shape (n_integrations, n_positions, 4) # x, y, cx, cy are (n_int +1, n_pos + 1) return latitude, longitude, sza, emission_angle, phase_angle, \ local_time, x, y, cx, cy, context_map
#calculate surface tangent point using pointing vectors and tgo position vs time print("Calculating tangent points") tangent_coords = np.asfarray([ sp.npedln(mars_axes[0], mars_axes[1], mars_axes[2], line_point, line_vector)[0] for line_point, line_vector in zip( list(line_points), list(line_vectors)) ]) tangent_lonlats1 = np.asfarray([ sp.reclat(tangent_coord) for tangent_coord in list(tangent_coords) ]) tangent_lonlats = np.asfarray( [[tangent_lonlat[1] * sp.dpr(), tangent_lonlat[2] * sp.dpr()] for tangent_lonlat in list(tangent_lonlats1)]) tangent_lsts = [ sp.et2lst(time, 499, (tangent_lonlat[0] / sp.dpr()), "PLANETOCENTRIC")[3] for time, tangent_lonlat in zip(list(times), list(tangent_lonlats)) ] tangent_lsts_hours = np.asfarray([ np.float(tangent_lst[0:2]) + np.float(tangent_lst[3:5]) / 60.0 + np.float(tangent_lst[6:8]) / 3600.0 for tangent_lst in tangent_lsts ]) nadir_lonlats = np.asfarray( [sp.reclat(mars2tgo) for mars2tgo in list(mars2tgo_pos)])[:, 1:3] * sp.dpr() nadir_lsts = [ sp.et2lst(time, 499, (nadir_lonlat[0] / sp.dpr()), "PLANETOCENTRIC")[3] for time, nadir_lonlat in zip(list(times), list(nadir_lonlats)) ]
typein = "PLANETOCENTRIC" body = 499 etStart = sp.utc2et("2018MAR24-11:50:00 UTC") etEnd = sp.utc2et("2020MAR24-11:50:00 UTC") ets = np.linspace(etStart, etEnd, num=180) writeOutput("UTC Time, LSubS, Longitude, Latitude, Local Solar Time") for et in list(ets): lSubS = lsubs(et) terminatorPoints = sp.edterm(trmtyp, source, target, et, ref, abcorr, observer, npts) terminatorLatLonsRad = np.asfarray([ sp.reclat(terminatorPoint)[1:3] for terminatorPoint in terminatorPoints[2] ]) terminatorLatLonsDeg = terminatorLatLonsRad * sp.dpr() terminatorLSTs = [ sp.et2lst(et, body, terminatorLatLonRad[0], typein)[3] for terminatorLatLonRad in list(terminatorLatLonsRad) ] for index, terminatorLST in enumerate(terminatorLSTs): writeOutput("%s,%0.2f,%0.2f,%0.2f,%s" % (et2utc(et), lSubS, terminatorLatLonsDeg[index, 0], terminatorLatLonsDeg[index, 1], terminatorLST))
def highres_swath_geometry(hdul, res=200, twilight='discrete'): """ Generates an artificial high-resolution slit, calculates viewing geometry and surface-intercept map. Parameters ---------- hdul : HDUList Opened FITS file. res : int, optional The desired number of artificial elements along the slit. Defaults to 200. twilight : str The appearance of the twilight zone. 'discrete' has a partially transparent zone with sharp edges while 'continuous' smoothes it with a cosine function. The discrete option does not always work on all systems, but I cannot yet say why that is. In those cases you get the continuous appearance. Returns ------- latitude : array Array of latitudes for the centers of each high-resolution artificial pixel. NaNs if pixel doesn't intercept the surface of Mars. longitude : array Array of longitudes for the centers of each high-resolution artificial pixel. NaNs if pixel doesn't intercept the surface of Mars. sza : array Array of solar zenith angles for the centers of each high-resolution artificial pixel. NaNs if pixel doesn't intercept the surface of Mars. local_time : array Array of local times for the centers of each high-resolution artificial pixel. NaNs if pixel doesn't intercept the surface of Mars. x : array Horizontal coordinate edges in angular space. Has shape (n+1, m+1) for geometry arrays with shape (n,m). y : array Vertical coordinate edges in angular space. Has shape (n+1, m+1) for geometry arrays with shape (n,m). cx : array Horizontal coordinate centers in angular space. Same shape as geometry arrays. cy : array Vertical coordinate centers in angular space. Same shape as geometry arrays. context_map : array High-resolution image of the Mars surface as intercepted by the swath. RGB tuples with shape (n,m,3). """ # calculate beta-flip state flipped = beta_flip(hdul) # get swath vectors, ephemeris times, and mirror angles vec = hdul['pixelgeometry'].data['pixel_vec'] et = hdul['integration'].data['et'] # get dimensions of the input data n_int = hdul['integration'].data.shape[0] n_spa = len(hdul['binning'].data['spapixlo'][0]) # set the high-resolution slit width and calculate the number of high-resolution integrations hifi_spa = res hifi_int = int(hifi_spa / n_spa * n_int) # make arrays of ephemeris time and array to hold the new swath vector calculations et_arr = np.expand_dims(et, 1) * np.ones((n_int, n_spa)) et_arr = resize(et_arr, (hifi_int, hifi_spa), mode='edge') vec_arr = np.zeros((hifi_int + 1, hifi_spa + 1, 3)) # make an artificially-divided slit and create new array of swath vectors if flipped: lower_left = vec[0, :, 0, 0] upper_left = vec[-1, :, 0, 1] lower_right = vec[0, :, -1, 2] upper_right = vec[-1, :, -1, 3] else: lower_left = vec[0, :, 0, 1] upper_left = vec[-1, :, 0, 0] lower_right = vec[0, :, -1, 3] upper_right = vec[-1, :, -1, 2] for e in range(3): a = np.linspace(lower_left[e], upper_left[e], hifi_int + 1) b = np.linspace(lower_right[e], upper_right[e], hifi_int + 1) vec_arr[:, :, e] = np.array([np.linspace(i, j, hifi_spa + 1) for i, j in zip(a, b)]) # resize array to extract centers vec_arr = resize(vec_arr, (hifi_int, hifi_spa, 3), anti_aliasing=True) # make empty arrays to hold geometry calculations latitude = np.zeros((hifi_int, hifi_spa))*np.nan longitude = np.zeros((hifi_int, hifi_spa))*np.nan sza = np.zeros((hifi_int, hifi_spa))*np.nan phase_angle = np.zeros((hifi_int, hifi_spa))*np.nan emission_angle = np.zeros((hifi_int, hifi_spa))*np.nan local_time = np.zeros((hifi_int, hifi_spa))*np.nan context_map = np.zeros((hifi_int, hifi_spa, 3))*np.nan # load Mars surface map and switch longitude domain from [-180,180) to [0, 360) mars_surface_map = plt.imread(os.path.join(pkg_resources.resource_filename('maven_iuvs', 'ancillary/'), 'mars_surface_map.jpg')) offset_map = np.zeros_like(mars_surface_map) offset_map[:, :1800, :] = mars_surface_map[:, 1800:, :] offset_map[:, 1800:, :] = mars_surface_map[:, :1800, :] mars_surface_map = offset_map # calculate intercept latitude and longitude using SPICE, looping through each high-resolution pixel target = 'Mars' frame = 'IAU_Mars' abcorr = 'LT+S' observer = 'MAVEN' body = 499 # Mars IAU code for i in range(hifi_int): for j in range(hifi_spa): et = et_arr[i, j] los_mid = vec_arr[i, j, :] # try to perform the SPICE calculations and record the results # noinspection PyBroadException try: # calculate surface intercept spoint, trgepc, srfvec = spice.sincpt('Ellipsoid', target, et, frame, abcorr, observer, frame, los_mid) # calculate illumination angles trgepc, srfvec, phase_for, solar, emissn = spice.ilumin('Ellipsoid', target, et, frame, abcorr, observer, spoint) # convert from rectangular to spherical coordinates rpoint, colatpoint, lonpoint = spice.recsph(spoint) # convert longitude from domain [-pi,pi) to [0,2pi) if lonpoint < 0.: lonpoint += 2 * np.pi # convert ephemeris time to local solar time hr, mn, sc, time, ampm = spice.et2lst(et, body, lonpoint, 'planetocentric', timlen=256, ampmlen=256) # convert spherical coordinates to latitude and longitude in degrees latitude[i, j] = np.degrees(np.pi / 2 - colatpoint) longitude[i, j] = np.degrees(lonpoint) # convert illumination angles to degrees and record sza[i, j] = np.degrees(solar) phase_angle[i, j] = np.degrees(phase_for) emission_angle[i, j] = np.degrees(emissn) # convert local solar time to decimal hour local_time[i, j] = hr + mn / 60 + sc / 3600 # convert latitude and longitude to pixel coordinates map_lat = int(np.round(np.degrees(colatpoint), 1) * 10) map_lon = int(np.round(np.degrees(lonpoint), 1) * 10) # instead of changing an alpha layer, I just multiply an RGB triplet by a scaling fraction in order to # make it darker; determine that scalar here based on solar zenith angle if twilight == 'discrete': if (sza[i, j] > 90) & (sza[i, j] <= 102): twilight = 0.7 elif sza[i, j] > 102: twilight = 0.4 else: twilight = 1 else: if (sza[i, j] > 90) & (sza[i, j] <= 102): tsza = (sza[i, j]-90)*np.pi/2/12 twilight = np.cos(tsza)*0.6 + 0.4 elif sza[i, j] > 102: twilight = 0.4 else: twilight = 1 # place the corresponding pixel from the high-resolution Mars map into the swath context map with the # twilight scaling context_map[i, j, :] = mars_surface_map[map_lat, map_lon, :] / 255 * twilight # if the SPICE calculation fails, this (probably) means it didn't intercept the planet except: pass # get mirror angles angles = hdul['integration'].data['mirror_deg'] * 2 # convert from mirror angles to FOV angles dang = np.diff(angles)[0] # create an meshgrid of angular coordinates for the high-resolution pixel edges x, y = np.meshgrid(np.linspace(0, slit_width_deg, hifi_spa + 1), np.linspace(angles[0] - dang / 2, angles[-1] + dang / 2, hifi_int + 1)) # calculate the angular separation between pixels dslit = slit_width_deg / hifi_spa # create an meshgrid of angular coordinates for the high-resolution pixel centers cx, cy = np.meshgrid( np.linspace(0 + dslit, slit_width_deg - dslit, hifi_spa), np.linspace(angles[0], angles[-1], hifi_int)) # beta-flip the coordinate arrays if necessary if flipped: x = np.fliplr(x) y = (np.fliplr(y) - 90) / (-1) + 90 cx = np.fliplr(cx) cy = (np.fliplr(cy) - 90) / (-1) + 90 # convert longitude to [-180,180) longitude[np.where(longitude > 180)] -= 360 # return the geometry and coordinate arrays return latitude, longitude, sza, local_time, x, y, cx, cy, context_map
def local_soltime(self): return spice.et2lst(self.et, self.target_id, self.coords.lon.value, "PLANETOGRAPHIC")[3]
clearanceangle = np.ones([winsiz - 1, 1]) Rx = np.ones([winsiz - 1, 1]) MexNadirTGOAngle = np.ones([winsiz - 1, 1]) # grazingangle = np.ones([winsiz-1,1]) # HERE for i in tqdm(range(winsiz - 1)): # try to plot the location on a map with cartopy lon[i], lat[i], dist[i], nearestpoint, alt, speed, date_time[ i], ingress_date_time[i], veldopp[i], MexNadirTGOAngle[ i] = main.Location(occs.Time[i], occs.Ingress[i], sv, 0) # FUNCTION NEEDS NEW NAME sza[i] = main.SolarZenithAngles(occs.Time[i], nearestpoint, sv) clearanceangle[i] = main.earlyclearance(occs.Time[i], sv) hour, minute, sec, _, _ = spice.et2lst( occs.Time[i], 499, (lon[i] * (math.pi / 180)), 'PLANETOCENTRIC') # 499 = spice code for Mars localtimevect = [hour, minute, sec] localtime[i] = "%d:%d:%d" % (localtimevect[0], localtimevect[1], localtimevect[2]) # angle[i] = main.grazingangle(occs.Time[i], sv) # this process is probably slow because this function is forming the entire profile. Rx[i] = main.expectedpower(occs.Time[i], sv) # progess = (i/(winsiz-1)) *100 # print('%.2f' %progess) # plot all of the tangent points onto the surface of mars #main.charter(lon, lat, start, stop,here) # Add to dataframe occs['Julian'] = date_time
def _get_local_soltime(self): try: return spice.et2lst(self.et, self.target_id, self.coords.lon, "PLANETOCENTRIC") except SPointNotSetError: raise