Command Line¶
Note
While the information below is referencing Tracktable’s rendering facilities, the command line functionality presented can be applied to other tracktable scripts.
Tracktable’s various rendering facilities have a lot of options. Python makes it easy for us to expose these as command-line options that can be passed to scripts. However, that just pushes the problem out one level: now the user has to remember the values for all of those options, or else write shell scripts that call Python scripts in order to keep track of what parameters were used where.
We introduce two facilities to help tame this morass:
Argument Groups: An argument group is a set of command-line arguments that all pertain to a single capability. For example, the argument group for trajectory assembly has entries for the maximum separation distance, maximum separation time and minimum length as described in the Trajectory Assembly section.
Response Files: A response file is a way to package up arbitrarily many command-line arguments in a file and pass them to a script all at once. It is independent of which script is being run. Since a response file is just text it is easy to place under version control. We provide a slightly modified version of the standard Python
argparse
module that includes support for response files containing comments and response files that load other response files.
Argument Groups¶
The point of an argument group is to save us from having to cut and paste the same potentially-lengthy list of arguments and their respective handlers into each new script we write. When we render a movie of data over time, for example, we will always need several pieces of information including resolution, frame rate, and the duration of our movie.
Since we’re human we are guaranteed to forget an argument here, spell one differently there, and before long we have a dozen scripts that all take completely different command-line arguments. Bundling arguments in an easy-to-reuse fashion makes it easy for us to use the same ones consistently.
We derive another benefit at the same time. By abstracting away a set of arguments into a semi-opaque module, we can add capability to (for example) the mapmaker without having to change our movie-making script. Once the argument group for the mapmaker is updated, any script that uses the mapmaker’s argument group will automatically gain access to the new capability.
There are three parts to using argument groups. First they must be
created and registered. Second, they are applied when we create an
argument parser for a script. Finally, once command-line arguments
have been parsed, we (as the programmers) can extract values for each
argument group that you used. All of these functions are in the
tracktable.script_helpers.argument_groups.utilities
module.
Creating an Argument Group¶
We create an argument group first by declaring it with
create_argument_group()
and then populating it with calls to
add_argument()
.
Here is an example from the movie_rendering
group:
1create_argument_group("movie_rendering",
2 title="Movie Parameters",
3 description="Movie-specific parameters such as frame rate, encoder options, title and metadata")
4
5add_argument("movie_rendering", [ "--duration" ],
6 type=int,
7 default=60,
8 help="How many seconds long the movie should be")
9
10add_argument("movie_rendering", [ "--fps" ],
11 type=int,
12 default=30,
13 help="Movie frame rate in frames/second")
14
15add_argument("movie_rendering", [ "--encoder-args" ],
16 default="-c:v mpeg4 -q:v 5",
17 help="Extra args to pass to the encoder (pass in as a single string)")
All of Tracktable’s standard argument groups are in files in the
Python/tracktable/script_helpers/argument_groups
directory. Look
at __init__.py
in that directory for an example of how to add one
to the registry. You can register your own groups anywhere in your
code that you choose.
Applying Argument Groups¶
We use argument groups by applying their arguments to an
already-instantiated argument parser. That can be an instance of the
standard argparse.ArgumentParser
or our customized version
tracktable.script_helpers.argparse.ArgumentParser
. For example:
1 from tracktable.script_helpers import argparse, argument_groups
2
3 parser = argparse.ArgumentParser()
4 argument_groups.use_argument_group("delimited_text_point_reader", parser)
5 argument_groups.use_argument_group("trajectory_assembly", parser)
6 argument_groups.use_argument_group("trajectory_rendering", parser)
7 argument_groups.use_argument_group("mapmaker", parser)
We can interleave calls to use_argument_group()
freely with calls to other functions defined on
ArgumentParser
.
We recommend reading the code for
use_argument_group()
if you need to do especially complex things with argparse
such
as mutually exclusive sets of options.
Using Parsed Argument Values¶
After we call :py:meth:parser.parse_args()
<argparse.ArgumentParser.parse_args>
we are left with a Namespace
object containing all the values for our command-line options, both
user-supplied and default. We use the :py:func:extract_arguments()
<tracktable.script_helpers.argument_groups.utilities.extract_arguments>
function to retrieve sets of arguments that we configured using
:py:func:use_argument_group()
<tracktable.script_helpers.argument_groups.utilities.use_argument_group>
.
Our practice is to define handler functions that take every argument
in a group so that we can write code like the following:
1def setup_trajectory_source(point_source, args):
2 trajectory_args = argument_groups.extract_arguments("trajectory_assembly", args)
3 source = example_trajectory_builder.configure_trajectory_builder(
4 **trajectory_args
5 )
6 source.input = point_source
7
8 return source.trajectories()
Since we are not required to refer to the individual arguments directly, the user can take advantage of new capabilities added to the underlying modules whether or not we know about them when we write our script.
Todo
Add tracktable.script_helpers.argument_groups to the documentation
Response Files¶
Todo
Document response files in full
Once we start calling scripts with more than 3 or 4 options it becomes
difficult to keep track of all the arguments and difficult to edit the
command line. We address this with response files, textual listings
of command-line options and their values that we can pass to scripts.
The standard Python argparse
module has limited support for
response files. We expand upon it with our own extended argparse
.
Fuller documentation is coming soon. This should be enough to get you started:
$ cd tracktable/Python/tracktable/examples
$ python heatmap_from_csv.py --write-response-file > heatmap_response_file.txt
Now open up heatmap_response_file.txt
in your favorite editor.
Lines that begin with #
are comments. Uncomment any arguments you
please and add or change values for them. After you save the file,
run the script as follows:
$ python heatmap_from_csv.py @heatmap_response_file.txt
That will tell the script to read arguments from
heatmap_response_file.txt
as well as from the command line.
You can freely mix response files and standard arguments on a single command line. You can also use multiple response files. The following command line would be perfectly valid:
$ python make_movie.py @hd_movie_params.txt @my_favorite_map.txt movie_outfile.mkv