LightCurve1
===========
:stem: latexmath
:source-highlighter: highlight.js

Keywords:

== Summary ==
This demo shows how to use the
http://www.dirsig.org/docs/new/lightcurve_plugin.html[LightCurve] sensor
plugin to generate a 1D (magnitude vs. time) 
https://www.wikipedia.org/wiki/Light_curve[light curve] from a terrestrial
observation location of a simple spherical object in orbit.  The light
curve captures the changing magnitude of the total reflected (and emitted)
light from the object as it traverses the sky.

== Related Materials ==
The following demos, manuals and tutorials can provide additional
information about the topics at the focus of this demo:

* Related Demos
** N/A
* Related Manuals
** The http://www.dirsig.org/docs/new/lightcurve_plugin.html[LightCurve] sensor
   plugin manual.
* Related Tutorials
** N/A

== Details ==
This section explains any technical details of the simulation.

== Important Files ==
This section highlights key files important to the simulation.

=== Scene Geometry
The scene in this demo consists entirely of the orbiting sphere
object.  The sphere itself is a facetized model (see
`geometry/sphere.obj`), which is instanced using
http://www.dirsig.org/docs/new/flex_motion.html[FlexMotion] using
the http://www.dirsig.org/docs/new/flex_motion.html#Sgp4[SGP4]
location engine with a Two-Line Element (TLE) for the SEASAT 1
satellite (NORAD 10967).  Since the sphere is uniform, the orientation
setup for this object is not important (a static Euler angle setup
was used).

.The GLIST setup for the orbiting sphere object.
[source,xml]
----
include::geometry/sphere.glist[]
----

An important attribute of this setup is that the `<dynamicinstance>`
has a tag associated with it (i.e., `tags="sphere"`).  This tag name
(in this case, `sphere`) will be given to the LightCurve sensor plugin
so that it will track it.

=== Sensor Configuration
The LightCurve plugin configuration is shown below.  They key components
of the setup are:

* The location of the observation (see the `sensor_location`),
* The tag associated with the target object to track (see `target_tag`),
* The start, duration and number of time samples for the observation
  (see the `date_time`, `duration` and `sample_count`), and
* The spectral bandpass of the sensor making the observation (see the
  `bandpass`).

.An example configuration for the LightCurve plugin.
[source,json]
----
include::sphere.jsim[lines=13..31]
----

== Simulations and Results ==
=== Running the "Sphere" Simulation
The simulation is run using the `sphere.jsim` file, either from the JSIM
Editor in the graphical user interface (GUI) or from the command-line:

.Running the sphere simulation
----
$ dirsig5 sphere.jsim
----

During the setup phase, the plugin will output the parameters being used
for the simulation:

----
Setting up the 'LightCurve' plugin
    Sensor location (lat,lon,alt) = 35, -106, 0
    Target object requested = 'sphere'
    Start date/time (ISO8601) = 2023-11-16T12:47:00.0000+00:00
    Curve duration = 840s
    Curve samples = 100
    Bandpass (min,max,delta) = 5070, 5950, 1
    Grid size = 100 x 100
    Output filename = test.txt
    Band zeropoint = 3.55e-09 erg/(s cm^2 A)
    Debug grid filename = debug.grid
----

During the simulation, a status message will be print for each time step:

.Output of the LightCurve sensor plugin during the simulation.
----
[|][#-------------------------------------------------]
[/][##------------------------------------------------]
[-][###-----------------------------------------------]
...
[lines deleted for documentation purposes]
...
[-][################################################--]
[\][#################################################-]
[|][##################################################]

Setup time: 0m 0.367s
Render time: 0m 23.610s
Total run time: 0m 23.976s
----

Note that enabling debug output via the command-line `--log_level=debug` 
option will produce additional information for each time (capture) step:

----
[debug] LightCurve::captureStarted:
[debug]   Target center in ENU  = -3.144e+05, 9.463e+05, 6.791e+05
[debug]   Target center in ECEF = -1.748e+06, -4.954e+06, 4.803e+06
[debug]   Target radius     = 6.928 [meters]
[debug]   Target distance   = 1206482.011 [meters]
[debug]   Target half angle = 3.356e-04 [degrees]
----

==== Light Curve Output
The primary output of the simulation is a multi-column, ASCII/Text file
containing the following values for each time sample:

. The relative capture time in seconds
. The magnitude (see note on units and zero point below)
. The spectrally integrated radiance (Watts per cm^2^ per steradian)
. The radius of the bounding volume for the target (in radians), and
. The solid angle of the bounding volume for the target (in steradians).

The default output filename for the plugin is `lightcurve.dat`. This
filename can be overridden via the `output_filename` variable in the
input configuration.

The default zero point for the magnitude is for Vega in the V band (~5556Å) 
is `3.55e-09` erg per second per cm^2^ per Angstrom.  This zero point can
be overridden via the `band_zeropoint` in the input configuration.

.The output `lightcurve.dat` file for this demo.
----
include::lightcurve.dat[lines=1..3]
...
include::lightcurve.dat[lines=98..101]
----

TIP: The `0` value for the radiances and corresponding `inf` value for
     the magnitude indicates that the target was unobservable (below the
     horizon) at that time.

The magnitude vs. time data from the output file is plotted below:

.Plot of the magnitude vs. time (converted to UTC) for the demo.
image::images/curve.png[]

==== Visualizing the Field-of-View
In some situations it is helpful to visualize the samples within
the field-of-view (FOV) being used to compute the total radiance
(and resulting magnitude) for the FOV of the sensor.  The plugin
provides two options for this.

An optional debug "grid file" can be generated during the
simulation (see the optional `debug_filename` variable in the input
configuration).  The FOV was sampled with a M x M uniform grid
(`100` is the default, but can be changed via the `grid_size`
variable).  The format of this debug grid file is ASCII/Text, with
each line containing the spectrally integrated radiance for each
of the M samples in a row of the FOV sampling grid.  M lines with
M values captures all the samples for a given time.  These blocks
of M lines of M values repeats for each time.  Hence, a simulation
with N time samples will result in a file with N x M lines and N x
(M x M) samples.  Below, these samples for this demo were plotted
and animated as a function of time to show how the solar loading
on the sphere changes as a function of position as it traverses the
sky.

.An animation of the sub-IFOV samples on the sphere target as a function of time.
image::images/grid.gif[]

TIP: This animation was created using GNUplot.  See the `plot_grid.gp`
     script used to create this animation. 


=== Running the "Spinning Box" Simulation
The second primary simulation is configured to emulate a "spectral waterfall"
collection, resulting in a 2D "light curve" where one dimension is time and
the other is the spectral radiance.  To accomplish this, the spectral
data cube output is enabled, which will then be post-processed with Python
to produce the waterfall image.  The target object in this case is a box
that is attributed with shiny red, green and blue car paints that is
tumbling as a function of time. Hence, as the object passes from horizon to
horizon, different colored sides are facing the ground-based sensor.

The spectral data cube output is configured by setting the `image_basename`
variable to a non-zero length string (in this case, `"cube"`).

.Running the sphere simulation
----
$ dirsig5 box_spin.jsim
----

For this simulation, at each time step, a spatial-spectral data
cube is produced in the ENVI image file format.  This output is
generated when the user sets the optional `image_basename` variable
to the base name of the image file sequence to be produced.

NOTE: If the `image_basename` is set to `test`, then the resulting
      image files will be `test_000.img`, `test_001.img`, etc.  The
      number of digits in the sequence portion of the filename will
      be sized to hold the number of samples in the light curve.

The spatial dimensions of the images are `grid_size` x `grid_size`.
The spectral dimension is the number of wavelengths in the `bandpass`.
These spatial-spectral data cubes can be used by the user to introduce
arbitrary spectral weightings, apply spatial MTFs, produce
temporal-spectral waterfall visualations, etc.

As a reminder, the LightCurve plugin automatically adjusts the FOV
on a frame-to-frame basis to span the extents of the target object.  
The traditional 1D lightcurve output can be reproduced as the spatial
and spectral integral of these spectral data cube files.

.An RGB made from the spatial-spectral data cube for step #436.
image::images/box_436.png[width=320]

The video below shows the colored cube tumbling as a function of time
(and, hence, position) as it traverses from horizon to horizon in this
simulation:

.A video of the colored cube tumbling as a function of time (position).
video::images/box_spin.mp4[width=320]

The `sp_waterfall.py` Python script leverages the
https://www.spectralpython.net[SpectralPython (SPy)] module to
process the spatial-spectral data cubes into a spectral waterfall
image by reading each 3D datacube and averaging the two spatial
dimensions to produce a 1D spectral curve.  These spectral curves
are then appended as rows to the waterfall image to produce a
spectral vs. time image file.

.The `sp_waterfall.py` Python script.
[source,python]
----
include::sp_waterfall.py[]
----

The resulting `waterfall.img` ENVI image file can then be loaded in the
DIRSIG image viewer or any other ENVI compatible image data viewer.  The
vertical dimension of the image is time and the horizontal dimension is
wavelength. The variation in orientation and illumination produces the
characteristic patterns in this data product.

.The spectral waterfall image.
image::images/waterfall.png[]
