Main

This module has the code that sets up the application and launches the Bokeh server.

init_cli

Use argparse to define the command line arguments:

  • --action: a verb that defines how the app will run:

    • generate: used to test the code that makes the input file for OptiPass; make the file, print it, and exit
    • run: used to test the code that runs OptiPass; make the input file, then create and run the shell commands that run OptiPass.exe
    • preview: same as run but just prints the shell commands instead of executing them
    • parse: used to test the code that parses the output from OptiPass; requires the --output option to specify the path to files created by OptiPass
    • all: used to run an integration test: generates the input for OptiPass, runs OptiPass, parses the results, displays the plots
    • gui: same as all but puts the results in the GUI
  • --project: path to a CSV file with barrier descriptions (default: static/workbook.csv)

  • --regions: one or more region names (used to test data file generation and parsing)

Command Line

The application needs files in the bin and static folders of the project. To run the application, open a terminal window and cd to the top level folder. The application is in the src folder. Type this command to make sure the application is installed and configured:

$ python3 src/main.py --help

Start the Server

To start the application simply run the program without any command line arguments:

$ python3 src/main.py

Integration Tests

The command line arguments allow the developer to run various integration tests.

This example tests the code that creates the input files for OptiPass by making a file for gates in the Coos region and targets CO and CH.

$ python3 src/main.py --action generate --region Coos --targets CO CH --output test1

Test the code that makes the output panes (data tables and ROI plots) by parsing the results of a previous run, in this case a set of files that start with the string tmpwok9i8rl.

$ python3 src/main.py --action parse --region Coquille --out tmpwok9i8rl 

Source

Use argparse to create the command line API.

Returns:
  • a Namespace object with values of the command line arguments.

src/main.py
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
def init_cli():
    """
    Use argparse to create the command line API.

    Returns:
        a Namespace object with values of the command line arguments. 
    """
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description=desc,
        epilog=epi,
    )

    # NOTE:  no argument can be required -- it should be possible to run this script with no
    # command line arguments, which is how it's run in the Docker container when launching the
    # web app

    parser.add_argument('--action', metavar='A', choices=['generate', 'preview', 'run', 'parse', 'all', 'gui'], help='operation to perform')
    parser.add_argument('--project', metavar='F', default='static/workbook.csv', help='CSV file with barrier data')
    parser.add_argument('--regions', metavar='R', default='all', nargs='+', help='one or more region names')
    parser.add_argument('--targets', metavar='T', nargs='+', default=['CO','FI'], help='one or more restoration targets')
    parser.add_argument('--budget', metavar='N', nargs=2, default=[5000,1000], help='max budget, budget delta')
    parser.add_argument('--climate', metavar='C', choices=['current','future'], default='current', help='climate scenario')
    parser.add_argument('--output', metavar='F', help='base name of output files (optional)')
    parser.add_argument('--scaled', action='store_true', help='compute benefit using scaled amounts')

    return parser.parse_args()

make_app

Instantiate the top level widget.

Returns:
  • a TideGatesApp object

src/main.py
70
71
72
73
74
75
76
77
78
79
80
def make_app():
    """
    Instantiate the top level widget.

    Returns:
        a TideGatesApp object
    """
    return TideGatesApp(
        title='Tide Gate Optimization', 
        sidebar_width=450
    )

start_app

Launch the Bokeh server.

src/main.py
82
83
84
85
86
87
88
89
90
91
92
93
94
def start_app():
    """
    Launch the Bokeh server.
    """
    pn.extension(design='native')
    pn.serve( 
        {'tidegates': make_app},
        port = 5006,
        admin = True,
        verbose = True,
        autoreload = True,
        websocket_origin= '*',
    )

validate_options

Make sure values specified on the command line are valid for that option. Prints an error message and exits if an unknown value is specified.

Example: check the names specified for the "region" option by making sure the values on the command line ("args.region") are in the list of valid names ("region_names").

validate_options('region', args.regions, region_names)
Parameters:
  • name (str) –

    the argument name

  • given (list[str]) –

    the strings typed by the user on the command line

  • expected (list[str]) –

    a list of acceptable values

src/main.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
def validate_options(
    name: str, 
    given: list[str], 
    expected: list[str],
):
    """
    Make sure values specified on the command line are valid for that option.
    Prints an error message and exits if an unknown value is specified.

    Example: check the names specified for the "region" option by making sure
    the values on the command line ("args.region") are in the list of valid
    names ("region_names").

        validate_options('region', args.regions, region_names)

    Args:
        name: the argument name
        given:  the strings typed by the user on the command line
        expected:  a list of acceptable values
    """
    if not all(x in expected for x in given):
        print(f'unknown {name} not in {expected}')
        exit(1)