Example #1
0
def main():
    signal.signal(signal.SIGINT, signal.SIG_DFL)

    args = parser.parse_args()

    ##########
    # initial arg processing

    if os.path.splitext(os.path.basename(args.IFO))[1] in DATA_SAVE_FORMATS:
        if args.freq:
            parser.exit(2, "Frequency specification not allowed when loading traces from file.\n")
        if args.ifo:
            parser.exit(2, "IFO parameter specification not allowed when loading traces from file.\n")
        from .io import load_hdf5
        budget = None
        freq, traces, attrs = load_hdf5(args.IFO)
        ifo = attrs.get('ifo')
        # FIXME: deprecate 'IFO'
        ifo = attrs.get('IFO', ifo)
        plot_style = attrs

    else:
        budget = load_budget(args.IFO)
        ifo = budget.ifo
        if args.freq:
            try:
                freq = freq_from_spec(args.freq)
            except IndexError:
                parser.exit(2, "Improper frequency specification: {}\n".format(args.freq))
        else:
            freq = getattr(budget, 'freq', freq_from_spec(FREQ))
        plot_style = getattr(budget, 'plot_style', {})
        traces = None

    if args.ifo:
        for paramval in args.ifo:
            param, val = paramval.split('=', 1)
            ifo[param] = float(val)

    if args.yaml:
        if not ifo:
            parser.exit(2, "IFO structure not provided.\n")
        print(ifo.to_yaml(), end='')
        return
    if args.text:
        if not ifo:
            parser.exit(2, "IFO structure not provided.\n")
        print(ifo.to_txt(), end='')
        return
    if args.diff:
        if not ifo:
            parser.exit(2, "IFO structure not provided.\n")
        dbudget = load_budget(args.diff)
        diffs = ifo.diff(dbudget.ifo)
        if diffs:
            w = max([len(d[0]) for d in diffs])
            fmt = '{{:{}}} {{:>20}} {{:>20}}'.format(w)
            print(fmt.format('', args.IFO, args.diff))
            print(fmt.format('', '-----', '-----'))
            for p in diffs:
                k = str(p[0])
                v = repr(p[1])
                ov = repr(p[2])
                print(fmt.format(k, v, ov))
        return

    out_data_files = set()
    out_plot_files = set()
    if args.save:
        args.plot = False
        for path in args.save:
            if os.path.splitext(path)[1] in DATA_SAVE_FORMATS:
                out_data_files.add(path)
        out_plot_files = set(args.save) - out_data_files

    if args.plot or out_plot_files:
        if out_plot_files:
            # FIXME: this silliness seems to be the only way to have
            # matplotlib usable on systems without a display.  There must
            # be a better way.  'AGG' is a backend that works without
            # displays.  but it has to be set before any other matplotlib
            # stuff is imported.  and we *don't* want it set if we do want
            # to show an interactive plot.  there doesn't seem a way to
            # set this opportunistically.
            import matplotlib
            matplotlib.use('AGG')
        try:
            from matplotlib import pyplot as plt
        except RuntimeError:
            logger.warning("no display, plotting disabled.")
            args.plot = False

    try:
        import inspiral_range
        logger_ir = logging.getLogger('inspiral_range')
        logger_ir.setLevel(logger.getEffectiveLevel())
        handler = logging.StreamHandler()
        handler.setFormatter(logging.Formatter('%(name)s: %(message)s'))
        logger_ir.addHandler(handler)

    except ModuleNotFoundError:
        logger.warning("WARNING: inspiral_range package not available, figure of merit will not be calculated.")
        args.fom = None
    if args.fom:
        try:
            range_func, range_func_args = args.fom.split(':')
        except ValueError:
            range_func = args.fom
            range_func_args = ''
        range_params = {}
        for param in range_func_args.split(','):
            if not param:
                continue
            p, v = param.split('=')
            if not v:
                raise ValueError('missing parameter value "{}"'.format(p))
            try:
                v = float(v)
            except ValueError:
                pass
            range_params[p] = v

    ##########
    # main calculations

    if not traces:
        logger.info("calculating budget...")
        traces = budget.run(freq=freq)

    if args.title:
        plot_style['title'] = args.title
    elif 'title' in plot_style:
        pass
    elif budget:
        plot_style['title'] = "GWINC Noise Budget: {}".format(budget.name)
    else:
        plot_style['title'] = "GWINC Noise Budget: {}".format(args.IFO)

    if args.fom:
        logger.info("calculating inspiral {}...".format(range_func))
        H = inspiral_range.CBCWaveform(freq, **range_params)
        logger.debug("waveform params: {}".format(H.params))
        fom = eval('inspiral_range.{}'.format(range_func))(freq, traces['Total'][0], H=H)
        logger.info("{}({}) = {:.2f} Mpc".format(range_func, range_func_args, fom))
        fom_title = 'inspiral {func} {m1}/{m2} $\mathrm{{M}}_\odot$: {fom:.0f} Mpc'.format(
            func=range_func,
            m1=H.params['m1'],
            m2=H.params['m2'],
            fom=fom,
            )
        plot_style['title'] += '\n{}'.format(fom_title)

    ##########
    # interactive

    # interactive shell plotting
    if args.interactive:
        banner = """GWINC interactive shell

The 'ifo' Struct and 'traces' data objects are available for
inspection.  Use the 'whos' command to view the workspace.
"""
        if not args.plot:
            banner += """
You may plot the budget using the 'plot_noise()' function:

In [.]: plot_noise(freq, traces, **plot_style)
"""
        banner += """
You may interact with the plot using the 'plt' functions, e.g.:

In [.]: plt.title("foo")
In [.]: plt.savefig("foo.pdf")
"""
        from IPython.terminal.embed import InteractiveShellEmbed
        ipshell = InteractiveShellEmbed(
            banner1=banner,
            user_ns={
                'freq': freq,
                'traces': traces,
                'ifo': ifo,
                'plot_style': plot_style,
                'plot_noise': plot_noise,
            },
        )
        ipshell.enable_pylab()
        if args.plot:
            ipshell.ex("fig = plot_noise(freq, traces, **plot_style)")
            ipshell.ex("plt.title(plot_style['title'])")
        ipshell()

    ##########
    # output

    # save noise traces to HDF5 file
    if out_data_files:
        from .io import save_hdf5
        attrs = dict(plot_style)
        for path in out_data_files:
            logger.info("saving budget traces: {}".format(path))
            save_hdf5(
                path=path,
                freq=freq,
                traces=traces,
                ifo=ifo,
                **attrs,
            )

    # standard plotting
    if args.plot or out_plot_files:
        logger.debug("plotting noises...")
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)
        plot_noise(
            freq,
            traces,
            ax=ax,
            **plot_style
        )
        fig.tight_layout()
        if out_plot_files:
            for path in out_plot_files:
                logger.info("saving budget plot: {}".format(path))
                fig.savefig(path)
        else:
            plt.show()
Example #2
0
def main():
    signal.signal(signal.SIGINT, signal.SIG_DFL)

    args = parser.parse_args()

    ##########
    # initial arg processing

    if os.path.splitext(os.path.basename(args.IFO))[1] in [".hdf5", ".h5"]:
        Budget = None
        freq, traces, attrs = io.load_hdf5(args.IFO)
        ifo = getattr(attrs, "IFO", None)
        plot_style = attrs

    else:
        Budget, ifo, freq, plot_style = load_ifo(args.IFO)
        # FIXME: this should be done only if specified, to allow for
        # using any FREQ specified in budget module by default
        freq = np.logspace(np.log10(args.flo), np.log10(args.fhi), args.npoints)
        traces = None

    if args.yaml:
        if not ifo:
            parser.exit(2, "no IFO structure available.")
        print(ifo.to_yaml(), end="")
        return
    if args.text:
        if not ifo:
            parser.exit(2, "no IFO structure available.")
        print(ifo.to_txt(), end="")
        return
    if args.diff:
        if not ifo:
            parser.exit(2, "no IFO structure available.")
        fmt = "{:30} {:>20} {:>20}"
        Budget, ifoo, freq, plot_style = load_ifo(args.diff)
        diffs = ifo.diff(ifoo)
        if diffs:
            print(fmt.format("", args.IFO, args.diff))
            for p in diffs:
                k = str(p[0])
                v = repr(p[1])
                ov = repr(p[2])
                print(fmt.format(k, v, ov))
        return

    if args.title:
        plot_style["title"] = args.title
    elif Budget:
        plot_style["title"] = "GWINC Noise Budget: {}".format(Budget.name)
    else:
        plot_style["title"] = "GWINC Noise Budget: {}".format(args.IFO)

    if args.plot:
        if args.save:
            # FIXME: this silliness seems to be the only way to have
            # matplotlib usable on systems without a display.  There must
            # be a better way.  'AGG' is a backend that works without
            # displays.  but it has to be set before any other matplotlib
            # stuff is imported.  and we *don't* want it set if we do want
            # to show an interactive plot.  there doesn't seem a way to
            # set this opportunistically.
            import matplotlib

            matplotlib.use("AGG")
        try:
            from matplotlib import pyplot as plt
        except RuntimeError:
            logging.warning("no display, plotting disabled.")
            args.plot = False

    if args.fom:
        import inspiral_range

        try:
            range_func, fargs = args.fom.split(":")
        except ValueError:
            range_func = args.fom
            fargs = ""
        range_params = {}
        for param in fargs.split(","):
            if not param:
                continue
            p, v = param.split("=")
            if not v:
                raise ValueError('missing parameter value "{}"'.format(p))
            if p != "approximant":
                v = float(v)
            range_params[p] = v

    ##########
    # main calculations

    if not traces:
        if ifo:
            logging.info("precomputing ifo...")
            ifo = precompIFO(freq, ifo)
        logging.info("calculating budget...")
        budget = Budget(freq=freq, ifo=ifo)
        budget.load()
        budget.update()
        traces = budget.calc_trace()

    # logging.info('recycling factor: {: >0.3f}'.format(ifo.gwinc.prfactor))
    # logging.info('BS power:         {: >0.3f} W'.format(ifo.gwinc.pbs))
    # logging.info('arm finesse:      {: >0.3f}'.format(ifo.gwinc.finesse))
    # logging.info('arm power:        {: >0.3f} kW'.format(ifo.gwinc.parm/1000))

    if args.fom:
        logging.info("calculating inspiral {}...".format(range_func))
        H = inspiral_range.CBCWaveform(freq, **range_params)
        logging.debug("params: {}".format(H.params))
        fom = eval("inspiral_range.{}".format(range_func))(freq, noises["Total"], H=H)
        logging.info("{}({}) = {:.2f} Mpc".format(range_func, fargs, fom))
        fom_title = "{func} {m1}/{m2} Msol: {fom:.2f} Mpc".format(
            func=range_func,
            m1=H.params["m1"],
            m2=H.params["m2"],
            fom=fom,
        )
        plot_style["title"] += "\n{}".format(fom_title)

    ##########
    # output

    # save noise traces to HDF5 file
    if args.save and os.path.splitext(args.save)[1] in [".hdf5", ".h5"]:
        logging.info("saving budget traces {}...".format(args.save))
        if ifo:
            plot_style["IFO"] = ifo.to_yaml()
        io.save_hdf5(path=args.save, freq=freq, traces=traces, **plot_style)

    # interactive shell plotting
    elif args.interactive:
        ipshell = InteractiveShellEmbed(
            user_ns={
                "freq": freq,
                "traces": traces,
                "ifo": ifo,
                "plot_style": plot_style,
                "plot_noise": plot_noise,
            },
            banner1="""
GWINC interactive plotter

You may interact with plot using "plt." methods, e.g.:

>>> plt.title("foo")
>>> plt.savefig("foo.pdf")
""",
        )
        ipshell.enable_pylab()
        ipshell.run_code("plot_noise(freq, traces, **plot_style)")
        ipshell.run_code("plt.title('{}')".format(plot_style["title"]))
        ipshell()

    # standard plotting
    elif args.plot:
        logging.info("plotting noises...")
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)
        plot_noise(freq, traces, ax=ax, **plot_style)
        fig.tight_layout()
        if args.save:
            fig.savefig(
                args.save,
            )
        else:
            plt.show()