Skip to content
Snippets Groups Projects
Commit 91b38b3c authored by acpaquette's avatar acpaquette
Browse files

Added notebook to generate EIS segments

Scrub paths

More path scrubing
parent 459231a4
No related branches found
No related tags found
No related merge requests found
%% Cell type:code id:dc00d6d1-7b58-4b36-a52c-e0dfaa57ad01 tags:
``` python
# %matplotlib inline
import os
isisroot_dir = "/Path/to/isis_data"
os.environ["ISISDATA"] = isisroot_dir
os.environ["ISISROOT"] = "/Path/to/isis_root"
import csv
from glob import glob
import json
import logging
import math
from pathlib import Path
import subprocess
import numpy as np
import plotly
import plotly.graph_objs as go
import matplotlib
matplotlib.use('qtagg')
import matplotlib.pyplot as plt
plotly.offline.init_notebook_mode(connected=True)
import spiceypy as spice
import ale
from ale.drivers.clipper_drivers import ClipperEISWACPBIsisLabelNaifSpiceDriver
from ale import isd_generate
from kalasiris import isis
from knoten.utils import reproject
```
%% Cell type:code id:ab9988b4-9a66-4a16-89be-03f99a7154f1 tags:
``` python
# Define various planet radii as spheres
mars_radii = np.array([3396.2, 3396.2, 3396.2])
europa_radii = np.array([1560.8, 1560.8, 1560.8])
# Get the EIS cube
label_path = "/Path/to/eis/workarea"
clipper_file = os.path.join(label_path, "EIS000XXX_2032116T234928_0000C35F-WAC-PUSHB-IMG_RAW_V1.cub")
# Build kernel set
kernels = ['base/kernels/pck/pck00009.tpc',
'base/kernels/spk/de430.bsp',
'base/kernels/spk/mar097.bsp',
'base/kernels/lsk/naif0012.tls']
kernels = [os.path.join(isisdata_root, kernel) for kernel in kernels]
eis_path = "/Path/to/eis_data/kernels"
eis_kernels = ["sclk/europaclipper_00000.tsc",
"EUROPA_SCLKSCET.00001.tsc",
"ik/clipper_eis_v06.ti",
"fk/clipper_v09.tf",
"iak/eis_data.iak"]
eis_kernels = [os.path.join(eis_path, kernel) for kernel in eis_kernels]
eis_kernels = eis_kernels + kernels
eis_kernels
```
%% Cell type:code id:f7adad53-2e5a-40c2-8932-ae3fd3d19de6 tags:
``` python
def normalize(a):
a = np.array(a)
return a/np.linalg.norm(a)
# Degree coords to center the approach on
latitude = -5
longitude = 75
scale = mars_radii[0]/europa_radii[0]
# Height in km(?)
height = 50 * scale
# Direction of flight use "east" and "west"
# "east" is flying west toward east
# "west" is flygin east toward west
direction = "east"
# spacecraft speed in km/s
speed = 4.5 * scale
# +/- time from closest approach.
# Total time = start + (time_offset * 2)
time_offset = 500
# time_offset = time_offset * 2
# Radius definition to use
radii = mars_radii
# Compute and normalize nadir vector at closest approach
y, x, z = reproject([longitude, latitude, height], radii[0], radii[2], "latlong", "geocent")
spacecraft_point = np.array([x, y, z])
nadir_vector = normalize(spacecraft_point)
# Create a parallel trajectory that is perpendicular with nadir and parallel
# to the x, y axis
normal = np.array([0, 0, 1])
perpendicular_nadir = np.cross(nadir_vector, normal)
# compute fly_distance in km given speed and expected time from
# closest approach
fly_distance = speed * time_offset
# Compute the ending X,Y,Z given by extending the trajectory vector by the fly_distance
if direction == "west":
start_point = spacecraft_point + (perpendicular_nadir * fly_distance)
end_point = spacecraft_point - (perpendicular_nadir * fly_distance)
elif direction == "east":
start_point = spacecraft_point - (perpendicular_nadir * fly_distance)
end_point = spacecraft_point + (perpendicular_nadir * fly_distance)
else:
print("Direction " + direction + " not defined")
# Generate X, Y, Z some number of points from start and end
num_points = 10000
x_line_space = np.linspace(start_point[0], end_point[0], num_points)
y_line_space = np.linspace(start_point[1], end_point[1], num_points)
z_line_space = np.linspace(start_point[2], end_point[2], num_points)
# Zip up X, Y, Z line spaces and compute velocities
positions = np.array(list(zip(x_line_space, y_line_space, z_line_space)))
velocities = np.array([positions[1] - positions[0]] * num_points)
velocities = np.array([normalize(velocity) * speed for velocity in velocities])
times = np.linspace(-time_offset, time_offset, num_points)
times[int((num_points/2) - 1)], positions[int((num_points/2) - 1)], velocities[int((num_points/2) - 1)]
```
%% Cell type:code id:79b66a6c-f6f2-4a9c-9e7f-5b69485fcacc tags:
``` python
# Cell examines computed trajectory and look vector against the radii/wireframe
%matplotlib qt
def WireframeSphere(centre=[0.,0.,0.], radius=[1., 1., 1.],
n_meridians=20, n_circles_latitude=None):
"""
Create the arrays of values to plot the wireframe of a sphere.
Parameters
----------
centre: array like
A point, defined as an iterable of three numerical values.
radius: number
The radius of the sphere.
n_meridians: int
The number of meridians to display (circles that pass on both poles).
n_circles_latitude: int
The number of horizontal circles (akin to the Equator) to display.
Notice this includes one for each pole, and defaults to 4 or half
of the *n_meridians* if the latter is larger.
Returns
-------
sphere_x, sphere_y, sphere_z: arrays
The arrays with the coordinates of the points to make the wireframe.
Their shape is (n_meridians, n_circles_latitude).
Examples
--------
>>> fig = plt.figure()
>>> ax = fig.gca(projection='3d')
>>> ax.set_aspect("equal")
>>> sphere = ax.plot_wireframe(*WireframeSphere(), color="r", alpha=0.5)
>>> fig.show()
>>> fig = plt.figure()
>>> ax = fig.gca(projection='3d')
>>> ax.set_aspect("equal")
>>> frame_xs, frame_ys, frame_zs = WireframeSphere()
>>> sphere = ax.plot_wireframe(frame_xs, frame_ys, frame_zs, color="r", alpha=0.5)
>>> fig.show()
"""
if n_circles_latitude is None:
n_circles_latitude = max(n_meridians/2, 4)
u, v = np.mgrid[0:2*np.pi:n_meridians*1j, 0:np.pi:n_circles_latitude*1j]
sphere_x = centre[0] + radius[0] * np.cos(u) * np.sin(v)
sphere_y = centre[1] + radius[1] * np.sin(u) * np.sin(v)
sphere_z = centre[2] + radius[2] * np.cos(v)
return sphere_x, sphere_y, sphere_z
fig = plt.figure()
ax = fig.add_subplot(projection = '3d')
ax.set_aspect("auto")
x_line_space = positions[:, 0]
y_line_space = positions[:, 1]
z_line_space = positions[:, 2]
look_vectors = np.array([normalize(position) * 1000 for position in positions])
# Plot sphere as x, y, z
frame_xs, frame_ys, frame_zs = WireframeSphere(radius=mars_radii)
sphere = ax.plot_wireframe(frame_xs, frame_ys, frame_zs, color="r", alpha=0.5)
ax.plot3D(x_line_space, y_line_space, z_line_space, 'gray', marker='o')
for i, lv in enumerate(look_vectors):
ax.plot3D([lv[0], positions[i][0]], [lv[1], positions[i][1]], [lv[2], positions[i][2]], 'orange', marker='o')
# Plot radii and center point in ECEF
ax.plot3D(mars_radii[0], 0, 0, 'blue', marker='o')
ax.plot3D(0, mars_radii[1], 0, 'orange', marker='o')
ax.plot3D(0, 0, mars_radii[2], 'green', marker='o')
ax.plot3D(0, 0, 0, 'black', marker='o')
fig.show()
```
%% Cell type:code id:e7dedf0d-46da-4590-aedd-9192bc52e8dc tags:
``` python
spk_file = "/Path/to/custom_clipper_path.spk"
if Path(spk_file).is_file():
os.remove(spk_file)
driver = ClipperEISWACPBIsisLabelNaifSpiceDriver(clipper_file, props={"nadir": True, "kernels": eis_kernels})
with driver as active_driver:
ephem_start = active_driver.ephemeris_start_time
ephemeris_time = [time + ephem_start for time in times]
handle = spice.spkopn(spk_file, "SPK", 512)
states = pyspiceql.concatStates(positions, velocities)
spice.spkw13(handle,
-159,
499,
"IAU_MARS",
ephemeris_time[0],
ephemeris_time[-1],
"Custom Trajectory",
3,
len(ephemeris_time),
states,
ephemeris_time)
spice.spkcls(handle)
eis_kernels.append(spk_file)
```
%% Cell type:code id:0d1609e8-db68-4212-921b-62b200272afa tags:
``` python
def interp_3d(time, xyz_array, times):
f1 = np.interp(time, times, xyz_array[:, 0])
f2 = np.interp(time, times, xyz_array[:, 1])
f3 = np.interp(time, times, xyz_array[:, 2])
return np.array([f1, f2, f3])
def compute_segments_with_trajectory(ts,
radii,
IFOV,
block_size,
smear_fraction,
tset,
hmax,
positions,
velocities,
times):
segment_data = []
# Setup initial conditions
position = interp_3d(ts, positions, times)
velocity = interp_3d(ts, velocities, times)
r = np.linalg.norm(position)
h = r - radii
while (h > hmax):
ts = ts + 0.5
position = interp_3d(ts, positions, times)
velocity = interp_3d(ts, velocities, times)
r = np.linalg.norm(position)
h = r - radii
while h < hmax:
direction = math.copysign(1, ts)
position = interp_3d(ts, positions, times)
velocity = interp_3d(ts, velocities, times)
r = np.linalg.norm(position)
h = r - radii
pixwid = IFOV * h
v = np.linalg.norm(velocity)
unitR = normalize(position)
unitC = normalize(np.cross(position, velocity))
unitI = normalize(np.cross(unitC, unitR))
vg = np.dot(velocity, unitI) * (radii/r)
lts = pixwid / vg
ltm = lts * (1 + direction * smear_fraction)
Nb = 0
smear = smear_fraction
while smear <= smear_fraction:
Nb = Nb + 1
te = ts + ((Nb * block_size) - 1) * ltm
position = interp_3d(te, positions, times)
velocity = interp_3d(te, velocities, times)
r = np.linalg.norm(position)
v = np.linalg.norm(velocity)
h = r - radii
pixwid = IFOV * h
unitR = normalize(position)
unitC = normalize(np.cross(position, velocity))
unitI = normalize(np.cross(unitC, unitR))
vg = np.dot(velocity, unitI) * (radii/r)
lte = pixwid / vg
smear = abs(lte - ltm) / ltm
Nb = max(1, Nb - 1)
te = ts + ((Nb * block_size) - 1) * ltm
data_set = [ts, te, Nb]
segment_data.append(data_set)
ts = te + tset
return segment_data
def compute_segments_const_velocity(ts, radii, speed, IFOV, block_size, smear_fraction, tset, height, hmax):
segment_data = []
v = speed
s = v * ts
r0 = radii + height
r = math.sqrt(r0**2 + s**2)
h = r - radii
while (h > hmax):
ts = ts + 0.5
s = v * ts
r = math.sqrt(r0**2 + s**2)
h = r - radii
while h < hmax:
direction = math.copysign(1, ts)
s = v * ts
r = math.sqrt(r0**2 + s**2)
h = r - radii
pixwid = IFOV * h
vg = v * (radii/r0) / (1 + math.pow((s/r0), 2))
lts = pixwid / vg
ltm = lts * (1 + direction * smear_fraction)
Nb = 0
smear = smear_fraction
while smear <= smear_fraction:
Nb = Nb + 1
te = ts + ((Nb * block_size) - 1) * ltm
s = v * te
r = math.sqrt(r0**2 + s**2)
h = r - radii
pixwid = IFOV * h
vg = v * (radii/r0) / (1 + math.pow((s/r0), 2))
lte = pixwid / vg
smear = abs(lte - ltm) / ltm
Nb = max(1, Nb - 1)
te = ts + ((Nb * block_size) - 1) * ltm
data_set = [ts, te, Nb]
segment_data.append(data_set)
ts = te + tset
return segment_data
R = mars_radii[0]
IFOV = 2.18e-4
block_size = 256
f = 0.05
tset = 0.3
hmax = 1000 * scale
segments_from_trajectory = compute_segments_with_trajectory(-time_offset, R, IFOV, block_size, f, tset, hmax, positions, velocities, times)
segments_from_const_velocity = compute_segments_const_velocity(-time_offset, R, speed, IFOV, block_size, f, tset, height, hmax)
```
%% Cell type:code id:30aa43ca-490d-4689-bd9f-d659ad636c65 tags:
``` python
# Define the fore, nadir, and aft sensor lines
detector_offsets = [0, 1023, 2047]
```
%% Cell type:code id:0a492226-c1d6-47c1-88bd-e8f20d9b836e tags:
``` python
path = "/Path/to/eis_segments/"
spk_file = eis_kernels[-1]
ik_file = eis_kernels[3]
sclk_file = eis_kernels[0]
iak_file = eis_kernels[4]
pck_file = eis_kernels[5]
shape_file = os.path.join(isisroot_dir, "base/dems/molaMarsPlanetaryRadius0005.cub")
for detector_offset in detector_offsets:
i = 0
driver = ClipperEISWACPBIsisLabelNaifSpiceDriver(clipper_file, props={"nadir": True, "kernels": eis_kernels})
with driver as active_driver:
ephem_start = active_driver.ephemeris_start_time
for segment_data in segments_from_trajectory:
image_path = os.path.join(path, f"eis_segment_{detector_offset}_{i:02}.cub")
isis.makecube(to=image_path,
pixels="VALUE",
value=0.0,
samples=4096,
lines=int(segment_data[-1] * block_size),
bands=1)
isis.copylabel(from_=image_path,
source=clipper_file,
instrument=False,
bandbin=True,
kernels=True,
mapping=False,
radiometry=False,
polygon=False,
camstats=False)
try:
isis.editlab(from_=image_path, options="DELG", grpname="AlphaCube")
except:
pass
isis.editlab(from_=image_path, options="ADDG", grpname="Instrument")
# Most of the following PVL keyword edits are hard coded and may require changes
# to the "value" argument to produce the expected/correct label
isis.editlab(from_=image_path,
options="SETKEY",
grpname="Instrument",
keyword="SpacecraftName",
value="Clipper")
isis.editlab(from_=image_path,
options="SETKEY",
grpname="Instrument",
keyword="InstrumentId",
value="WAC-PUSHBROOM")
isis.editlab(from_=image_path,
options="SETKEY",
grpname="Instrument",
keyword="TargetName",
value="Mars")
start_time = spice.et2utc(ephem_start + segment_data[0], 'C', 14)
isis.editlab(from_=image_path,
options="SETKEY",
grpname="Instrument",
keyword="StartTime",
value=start_time)
exposure_duration = segment_data[1] - segment_data[0]
isis.editlab(from_=image_path,
options="SETKEY",
grpname="Instrument",
keyword="ExposureDuration",
value=exposure_duration, units="s")
isis.editlab(from_=image_path,
options="SETKEY",
grpname="Instrument",
keyword="DetectorOffset",
value=detector_offset)
# Create CSV for time table and write using csv2table
csv_file_name = "temp.csv"
with open(csv_file_name, 'w', newline='\n') as csvfile:
fieldnames = ["EphemerisTime", "ExposureTime", "LineStart"]
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({"EphemerisTime": segment_data[0] + ephem_start,
"ExposureTime": exposure_duration/(segment_data[-1] * block_size),
"LineStart": 1})
isis.csv2table(csv=csv_file_name,
tableName="LineScanTimes",
to=image_path,
coltypes="(Double, Double, Integer)")
try:
isis.spiceinit(from_=image_path,
spk=spk_file,
CKNADIR=True,
CKRECON=False,
ik=ik_file,
sclk=sclk_file,
iak=iak_file,
pck=pck_file,
shape="USER",
model=shape_file)
except subprocess.CalledProcessError as err:
print('Had an ISIS error:')
print(' '.join(err.cmd))
print(err.stdout)
print(err.stderr)
raise err
data_image_path = os.path.join(path, f"eis_segment_{detector_offset}_{i:02}.data.cub")
pixel_data = os.path.join(path, "molaCenterShade.resamp.cub")
if i <= 19:
pixel_data = os.path.join(path, "molaRightShade.resamp.cub")
elif i >= 60:
pixel_data = os.path.join(path, "molaLeftShade.resamp.cub")
isis.map2cam(from_=pixel_data,
match=image_path,
to=data_image_path)
i += 1
```
%% Cell type:code id:30dd955e-5c28-4bee-b5df-98c2f062a676 tags:
``` python
for detector_offset in detector_offsets:
files = glob(path, os.path.append(f"eis_segment_{detector_offset}_*.data.cub"))
files.sort()
for file in files:
out_json = os.path.splitext(file)[0] + ".json"
isd_generate.file_to_isd(file, out_json, log_level=logging.INFO, kernels = eis_kernels, only_naif_spice=True, nadir=True)
```
%% Cell type:code id:08086add-a50f-41ff-aa2c-ccb918bb97ea tags:
``` python
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment