Maintenance will be performed on git.ligo.org, chat.ligo.org, containers.ligo.org, and docs.ligo.org on the morning of Tuesday 11th August 2020, starting at approximately 9am PDT. It is expected to take around 20 minutes and there will be a short period of downtime (less than five minutes) towards the end of the maintenance window. Please direct any comments, questions, or concerns to computing-help@ligo.org.

__main__.py 8.59 KB
Newer Older
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
1 2 3 4 5 6 7
"""Finesse command line interface

Sean Leavey
<sean.leavey@ligo.org>
"""

import sys
8
import os
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
9 10 11 12 13 14 15 16
import numpy as np
import click

from . import __version__
from .finesse import kat as katparser

@click.command(help="Python interface and tools for FINESSE")
@click.argument("file", type=click.File())
17
@click.option("--simulate/--no-simulate", is_flag=True, default=True,
18 19
              help="Simulate FILE in Finesse. Can be set to --no-simulate if for example "
              "you only want to display the node graph for the model specified in FILE.")
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
20 21 22 23 24 25 26 27 28 29
@click.option("--xstart", type=float,
              help="Simulation start value. If specified, this overrides the xaxis start "
              "value specified in the parsed file.")
@click.option("--xstop", type=float,
              help="Simulation stop value. If specified, this overrides the xaxis stop "
              "value specified in the parsed file.")
@click.option("--xsteps", type=int,
              help="Number of steps to simulate between --start and --stop. If specified, "
              "this overrides the number of xaxis steps specified in the parsed file.")
@click.option("--xscale", type=click.Choice(["lin", "log"]), help="Scaling for the xaxis.")
30
@click.option("--noxaxis", is_flag=True, default=False, help="Switch off x-axis.")
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
31 32
@click.option("--trace", type=click.Choice(["tem", "cavity", "mismatch", "beams", "gouy",
                                            "coupling", "modechanges", "nodes", "all"]),
Sean Leavey's avatar
Sean Leavey committed
33 34
              multiple=True, help="Show simulation trace results. This option can be specified "
                                  "multiple times. The following values are supported: "
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
35 36 37 38 39 40 41 42 43
                                  "'tem': list TEM modes used, "
                                  "'cavity': cavity eigenvalues and other parameters, "
                                  "'mismatch': mode mismatch parameters for the initial setup, "
                                  "'beams': beam parameters for every node, "
                                  "'gouy': Gouy phases for all spaces, "
                                  "'coupling': coupling coefficients for all components, "
                                  "'modechanges': mode matching parameter changes during calculations, "
                                  "'nodes': nodes found during cavity tracing, "
                                  "'all': all trace results.")
Sean Leavey's avatar
Sean Leavey committed
44
@click.option("--powers", type=click.Choice(["dc", "carrier", "tem00"]),
45
              multiple=True, help="Show powers (W) at each node in the interferometer. This "
Sean Leavey's avatar
Sean Leavey committed
46 47 48 49 50
                                  "option can be specified multiple times. The following "
                                  "values are supported: "
                                  "'dc': list dc powers, "
                                  "'carrier': list powers in the f=0 fields, "
                                  "'tem00': list powers in the TEM00 mode.")
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
51 52
@click.option("--maxtem", type=str, help="Maximum transverse electric mode. Can be either "
              "an integer or 'off'.")
53 54 55 56 57
@click.option("--phase", type=int, help="Set Gouy phase behaviour.")
@click.option("--retrace", type=click.Choice(["force", "off"]),
              help="Set retrace behaviour: 'force' recomputes the Gaussian parameters at each "
              "node for every data point, and will trace a cavity even if it is unstable; 'off' "
              "switches off retracing even if it normally would be done.")
58 59
@click.option("--deriv-h", type=float, help="Step size for numerical differentiation.")
@click.option("--lambda0", type=str, help="Reference wavelength (m). Supports SI prefixes.")
60 61 62 63 64 65
@click.option("--print-frequencies", is_flag=True, default=False,
              help="Print a table listing all the frequencies used in the simulation: carriers, "
              "modulation sidebands and signal/quantum sidebands.")
@click.option("--print-noises", is_flag=True, default=False,
              help="Print a list of all the quantum noise sources being considered in the "
              "simulation and at which components and nodes it is present.")
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
66 67 68 69 70 71
@click.option("--ignore-block", "ignored_blocks", multiple=True,
              help="Ignore the specified block. Can be specified multiple times.")
@click.option("--plot/--no-plot", default=True, show_default=True,
              help="Display results as figure.")
@click.option("--save-figure", type=click.File("wb", lazy=False),
              help="Save image of figure to file.")
72
@click.option("--display-graph", is_flag=True, help="Generate and display model node graph.")
73 74 75 76
@click.option("--save-input", is_flag=True, default=False,
              help="Save generated Finesse input file.")
@click.option("--save-output", is_flag=True, default=False,
              help="Save generated Finesse output file.")
77 78 79
@click.option("--finesse-dir", type=click.Path(exists=True, file_okay=False, dir_okay=True),
              envvar='FINESSE_DIR', help="Path to directory containing the Finesse 'kat' "
              "executable. If not specified, the environment variable FINESSE_DIR is used.")
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
80
@click.version_option(version=__version__, prog_name="Pykat")
81
def cli(file, simulate, xstart, xstop, xsteps, xscale, noxaxis, trace, powers, maxtem, phase,
82 83
        retrace, deriv_h, lambda0, print_frequencies, print_noises, ignored_blocks, plot,
        save_figure, display_graph, save_input, save_output, finesse_dir):
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
84
    """Base CLI command group"""
85 86 87 88
    if finesse_dir is None:
        # Use default as required by kat object.
        finesse_dir = ""
    kat = katparser(katdir=finesse_dir)
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
89
    kat.load(file.name)
90
    has_xaxis = hasattr(kat, "xaxis") and not noxaxis
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
91 92 93 94 95

    if ignored_blocks:
        for block in ignored_blocks:
            kat.removeBlock(block)

96 97 98 99 100
    if display_graph:
        from .tools.plotting.graph import NodeGraph
        nodegraph = NodeGraph(kat)
        nodegraph.view_pdf()

101
    if simulate:
102 103 104
        # Default flag for showing simulation output. Overridden below as necessary.
        output_to_show = False

105 106
        if xstart is not None or xstop is not None or xsteps is not None or xscale is not None:
            if not has_xaxis:
107 108
                click.echo("Limits can only be overridden when an xaxis is defined in FILE and "
                           "when --noxaxis is unset.", err=True)
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
                sys.exit(1)
            # Override xaxis.
            limits = kat.xaxis.limits
            set_limits = False
            if xstart is not None:
                limits[0] = xstart
                set_limits = True
            if xstop is not None:
                limits[1] = xstop
                set_limits = True
            if xsteps is not None:
                kat.xaxis.steps = xsteps
            if xscale is not None:
                kat.xaxis.scale = xscale
            
            if set_limits:
                kat.xaxis.limits = np.array(limits).astype(float)

127
        if not has_xaxis:
128
            kat.noxaxis = True
129 130 131 132
            if save_figure is not None:
                click.echo("Cannot plot or save figure without an xaxis defined in FILE.",
                           err=True)
                sys.exit(1)
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
133

134
        if maxtem is not None:
135
            kat.maxtem = maxtem
136 137 138 139 140
        if phase is not None:
            kat.phase = phase
        if retrace is not None:
            kat.retrace = retrace
        if deriv_h is not None:
141
            kat.deriv_h = deriv_h
142
        if lambda0 is not None:
143
            kat.lambda0 = lambda0
144 145 146 147 148 149
        if print_frequencies:
            kat.parse("frequency")
            output_to_show = True
        if print_noises:
            kat.parse("printnoises")
            output_to_show = True
Sean Leavey's avatar
Add CLI  
Sean Leavey committed
150

151 152 153 154 155 156 157 158 159 160
        if trace:
            traceval = 0
            if "all" in trace:
                traceval = 255
            else:
                traceints = {"tem": 1, "cavity": 2, "mismatch": 4, "beams": 8,
                            "gouy": 16, "coupling": 32, "modechanges": 64, "nodes": 128}
                for tracetype in trace:
                    traceval |= traceints[tracetype]
            kat.trace = traceval
161 162
            output_to_show = True

Sean Leavey's avatar
Sean Leavey committed
163 164 165 166 167 168
        if powers:
            powerval = 0
            powerints = {"dc": 1, "carrier": 2, "tem00": 4}
            for powertype in powers:
                powerval |= powerints[powertype]
            kat.parse("powers %i" % powerval)
169
            output_to_show = True
170

171
        results = kat.run(save_output=save_output, save_kat=save_input)
172

173
        if output_to_show and results.rundata:
174
            click.echo(results.rundata)
175

176 177
        if has_xaxis and (plot or save_figure is not None):
            results.plot(show=plot, filename=save_figure)
178
        elif not output_to_show and not display_graph:
179
            click.echo("No output requested.")