diff --git a/bin/live/pycbc_live_supervise_collated_trigger_fits b/bin/live/pycbc_live_supervise_collated_trigger_fits index 71398621405..6562d427f3b 100755 --- a/bin/live/pycbc_live_supervise_collated_trigger_fits +++ b/bin/live/pycbc_live_supervise_collated_trigger_fits @@ -270,7 +270,10 @@ def plot_fits( ] fits_plot_arguments += sv.dict_to_args(plot_fit_options) - title = "Fit parameters for pycbc-live, triggers from " + day_title_str + title = "Fit parameters for pycbc-live, triggers from {}, {}".format( + ifo, + day_title_str + ) if smoothed == True: title += ', smoothed' fits_plot_arguments += ['--title', title] diff --git a/bin/plotting/pycbc_plot_bank_corner b/bin/plotting/pycbc_plot_bank_corner index 01fdf9100cf..6d55b2fbcab 100644 --- a/bin/plotting/pycbc_plot_bank_corner +++ b/bin/plotting/pycbc_plot_bank_corner @@ -72,6 +72,13 @@ parser.add_argument("--parameters", "property of that parameter will be used. If not " "provided, will plot all of the parameters in the " "bank.") +parser.add_argument( + '--log-parameters', + nargs='+', + default=[], + help="Which parameters are to be plotted on a log scale? " + "Must be also given in parameters" +) parser.add_argument('--plot-histogram', action='store_true', help="Plot 1D histograms of parameters on the " @@ -103,6 +110,11 @@ parser.add_argument("--color-parameter", help="Color scatter points according to the parameter given. " "May optionally provide a label in the same way as for " "--parameters. Default=No scatter point coloring.") +parser.add_argument( + '--log-colormap', + action='store_true', + help="Should the colorbar be plotted on a log scale?" +) parser.add_argument('--dpi', type=int, default=200, @@ -117,6 +129,13 @@ parser.add_argument('--title', add_style_opt_to_parser(parser) args = parser.parse_args() +for lp in args.log_parameters: + if not lp in args.parameters: + parser.error( + "--log-parameters should be in --parameters. " + f"{lp} not in [{', '.join(args.parameters)}]" + ) + pycbc.init_logging(args.verbose) set_style_from_cli(args) @@ -146,7 +165,7 @@ if args.fits_file is not None: param = fits_f[p][:].astype(float) # We need to check for the cardinal '-1' value which means # that the fit is invalid - param[param <= 0] = 0 if 'count' in p and 'log' not in p else np.nan + param[param <= 0] = np.nan bank[p] = param logging.info("Got %d templates from the bank", banklen) @@ -227,12 +246,21 @@ if cpar: for p in required_minmax: minval = np.nanmin(bank_fa[p][bank_fa[p] != -np.inf]) maxval = np.nanmax(bank_fa[p][bank_fa[p] != np.inf]) - valrange = maxval - minval + if (p in args.log_parameters) or (p == cpar and args.log_colormap): + # Extend the range by 10% in log-space + logvalrange = np.log(maxval) - np.log(minval) + if p not in mins: + mins[p] = np.exp(np.log(minval) - 0.05 * logvalrange) + if p not in maxs: + maxs[p] = np.exp(np.log(maxval) + 0.05 * logvalrange) + else: + # Extend the range by 10% + valrange = maxval - minval + if p not in mins: + mins[p] = minval - 0.05 * valrange + if p not in maxs: + maxs[p] = maxval + 0.05 * valrange - if p not in mins: - mins[p] = minval - 0.05 * valrange - if p not in maxs: - maxs[p] = maxval + 0.05 * valrange # Deal with non-coloring case: zvals = bank_fa[cpar] if cpar else None @@ -247,6 +275,7 @@ fig, axis_dict = create_multidim_plot( plot_scatter=True, plot_contours=False, scatter_cmap="viridis", + scatter_log_cmap=args.log_colormap, marginal_title=False, marginal_percentiles=[], fill_color='g', @@ -258,6 +287,7 @@ fig, axis_dict = create_multidim_plot( hist_color=hist_color, mins=mins, maxs=maxs, + log_parameters=args.log_parameters, ) title_text = f"{os.path.basename(args.bank_file)}" @@ -293,6 +323,19 @@ for i in range(len(args.parameters)): for s0, s1 in zip(sharex_axes[:-1], sharex_axes[1:]): s0.sharex(s1) +for (p1, p2), ax in axis_dict.items(): + if p1 == p2 and p1 in args.log_parameters: + if p1 == args.parameters[-1] and len(args.parameters) == 2: + # This will be turned on its side, so set _y_ axis to log + ax[0].semilogy() + else: + ax[0].semilogx() + else: + if p1 in args.log_parameters: + ax[0].semilogx() + if p2 in args.log_parameters: + ax[0].semilogy() + logging.info("Plot generated") fig.set_dpi(args.dpi) diff --git a/pycbc/results/scatter_histograms.py b/pycbc/results/scatter_histograms.py index f89cc5a563f..dac56ab79cc 100644 --- a/pycbc/results/scatter_histograms.py +++ b/pycbc/results/scatter_histograms.py @@ -43,7 +43,7 @@ if 'matplotlib.backends' not in sys.modules: # nopep8 matplotlib.use('agg') -from matplotlib import (offsetbox, pyplot, gridspec) +from matplotlib import (offsetbox, pyplot, gridspec, colors) from pycbc.results import str_utils from pycbc.io import FieldArray @@ -337,7 +337,7 @@ def create_marginalized_hist(ax, values, label, percentiles=None, linestyle='-', plot_marginal_lines=True, title=True, expected_value=None, expected_color='red', rotated=False, - plot_min=None, plot_max=None): + plot_min=None, plot_max=None, log_scale=False): """Plots a 1D marginalized histogram of the given param from the given samples. @@ -380,6 +380,8 @@ def create_marginalized_hist(ax, values, label, percentiles=None, creates. scalefac : {1., float} Factor to scale the default font sizes by. Default is 1 (no scaling). + log_scale : boolean + Should the histogram bins be logarithmically spaced """ if fillcolor is None: htype = 'step' @@ -389,7 +391,19 @@ def create_marginalized_hist(ax, values, label, percentiles=None, orientation = 'horizontal' else: orientation = 'vertical' - ax.hist(values, bins=50, histtype=htype, orientation=orientation, + if log_scale: + bins = numpy.logspace( + numpy.log10(numpy.nanmin(values)), + numpy.log10(numpy.nanmax(values)), + 50 + ) + else: + bins = numpy.linspace( + numpy.nanmin(values), + numpy.nanmax(values), + 50, + ) + ax.hist(values, bins=bins, histtype=htype, orientation=orientation, facecolor=fillcolor, edgecolor=color, ls=linestyle, lw=2, density=True) if percentiles is None: @@ -545,6 +559,7 @@ def create_multidim_plot(parameters, samples, labels=None, marginal_title=True, marginal_linestyle='-', zvals=None, show_colorbar=True, cbar_label=None, vmin=None, vmax=None, scatter_cmap='plasma', + scatter_log_cmap=False, log_parameters=None, plot_density=False, plot_contours=True, density_cmap='viridis', contour_color=None, label_contours=True, @@ -614,6 +629,10 @@ def create_multidim_plot(parameters, samples, labels=None, zvals. scatter_cmap : {'plasma', string} The color map to use for the scatter points. Default is 'plasma'. + scatter_log_cmap : boolean + Should the scatter point coloring be on a log scale? Default False + log_parameters : list or None + Which parameters should be plotted on a log scale plot_density : {False, bool} Plot the density of points as a color map. plot_contours : {True, bool} @@ -649,6 +668,8 @@ def create_multidim_plot(parameters, samples, labels=None, """ if labels is None: labels = {p: p for p in parameters} + if log_parameters is None: + log_parameters = [] # set up the figure with a grid of axes # if only plotting 2 parameters, make the marginal plots smaller nparams = len(parameters) @@ -732,6 +753,7 @@ def create_multidim_plot(parameters, samples, labels=None, create_marginalized_hist( ax, samples[param], label=labels[param], color=hist_color, fillcolor=fill_color, + log_scale=param in log_parameters, plot_marginal_lines=plot_marginal_lines, linestyle=marginal_linestyle, linecolor=line_color, title=marginal_title, expected_value=expected_value, @@ -749,8 +771,13 @@ def create_multidim_plot(parameters, samples, labels=None, alpha = 0.3 else: alpha = 1. + if scatter_log_cmap: + cmap_norm = colors.LogNorm(vmin=vmin, vmax=vmax) + else: + cmap_norm = colors.Normalize(vmin=vmin, vmax=vmax) + plt = ax.scatter(x=samples[px], y=samples[py], c=zvals, s=5, - edgecolors='none', vmin=vmin, vmax=vmax, + edgecolors='none', norm=cmap_norm, cmap=scatter_cmap, alpha=alpha, zorder=2) if plot_contours or plot_density: