def make_spectrum_plot(model_plot, data_plot, desc, xmin_clamp=0.01,
                       min_valid_x=None, max_valid_x=None):
    """Make a plot of a spectral model and data.

    *model_plot*
      A model plot object returned by Sherpa from a call like `ui.get_model_plot()`
      or `ui.get_bkg_model_plot()`.
    *data_plot*
      A data plot object returned by Sherpa from a call like `ui.get_source_plot()`
      or `ui.get_bkg_plot()`.
    *desc*
      Text describing the origin of the data; will be shown in the plot legend
      (with "Model" and "Data" appended).
    *xmin_clamp*
      The smallest "x" (energy axis) value that will be plotted; default is 0.01.
      This is needed to allow the plot to be shown on a logarithmic scale if
      the energy axes of the model go all the way to 0.
    *min_valid_x*
      Either None, or the smallest "x" (energy axis) value in which the model and
      data are valid; this could correspond to a range specified in the "notice"
      command during analysis. If specified, a gray band will be added to the plot
      showing the invalidated regions.
    *max_valid_x*
      Like *min_valid_x* but for the largest "x" (energy axis) value in which the
      model and data are valid.
    Returns:
      A tuple ``(plot, xlow, xhigh)``, where *plot* an OmegaPlot RectPlot
      instance, *xlow* is the left edge of the plot bounds, and *xhigh* is the
      right edge of the plot bounds.

    """
    import omega as om

    model_x = np.concatenate((model_plot.xlo, [model_plot.xhi[-1]]))
    model_x[0] = max(model_x[0], xmin_clamp)
    model_y = np.concatenate((model_plot.y, [0.]))

    # Sigh, sometimes Sherpa gives us bad values.
    is_bad = ~np.isfinite(model_y)
    if is_bad.sum():
        from .cli import warn
        warn('bad Sherpa model Y value(s) at: %r', np.where(is_bad)[0])
        model_y[is_bad] = 0

    data_left_edges = data_plot.x - 0.5 * data_plot.xerr
    data_left_edges[0] = max(data_left_edges[0], xmin_clamp)
    data_hist_x = np.concatenate((data_left_edges, [data_plot.x[-1] + 0.5 * data_plot.xerr[-1]]))
    data_hist_y = np.concatenate((data_plot.y, [0.]))

    log_bounds_pad_factor = 0.9
    xlow = model_x[0] * log_bounds_pad_factor
    xhigh = model_x[-1] / log_bounds_pad_factor

    p = om.RectPlot()

    if min_valid_x is not None:
        p.add(om.rect.XBand(1e-3 * xlow, min_valid_x, keyText=None), zheight=-1, dsn=1)
    if max_valid_x is not None:
        p.add(om.rect.XBand(max_valid_x, xhigh * 1e3, keyText=None), zheight=-1, dsn=1)

    csp = om.rect.ContinuousSteppedPainter(keyText=desc + ' Model')
    csp.setFloats(model_x, model_y)
    p.add(csp)

    csp = om.rect.ContinuousSteppedPainter(keyText=None)
    csp.setFloats(data_hist_x, data_hist_y)
    p.add(csp)
    p.addXYErr(data_plot.x, data_plot.y, data_plot.yerr, desc + ' Data', lines=0, dsn=1)

    p.setLabels(data_plot.xlabel, data_plot.ylabel)
    p.setLinLogAxes(True, False)
    p.setBounds (xlow, xhigh)
    return p, xlow, xhigh
def make_spectrum_plot ( model_plot , data_plot , desc , xmin_clamp = 0.01 , min_valid_x = None , max_valid_x = None ) : import omega as om model_x = np . concatenate ( ( model_plot . xlo , [ model_plot . xhi [ - 1 ] ] ) ) model_x [ 0 ] = max ( model_x [ 0 ] , xmin_clamp ) model_y = np . concatenate ( ( model_plot . y , [ 0. ] ) ) is_bad = ~ np . isfinite ( model_y ) if is_bad . sum ( ) : from . cli import warn warn ( 'bad Sherpa model Y value(s) at: %r' , np . where ( is_bad ) [ 0 ] ) model_y [ is_bad ] = 0 data_left_edges = data_plot . x - 0.5 * data_plot . xerr data_left_edges [ 0 ] = max ( data_left_edges [ 0 ] , xmin_clamp ) data_hist_x = np . concatenate ( ( data_left_edges , [ data_plot . x [ - 1 ] + 0.5 * data_plot . xerr [ - 1 ] ] ) ) data_hist_y = np . concatenate ( ( data_plot . y , [ 0. ] ) ) log_bounds_pad_factor = 0.9 xlow = model_x [ 0 ] * log_bounds_pad_factor xhigh = model_x [ - 1 ] / log_bounds_pad_factor p = om . RectPlot ( ) if min_valid_x is not None : p . add ( om . rect . XBand ( 1e-3 * xlow , min_valid_x , keyText = None ) , zheight = - 1 , dsn = 1 ) if max_valid_x is not None : p . add ( om . rect . XBand ( max_valid_x , xhigh * 1e3 , keyText = None ) , zheight = - 1 , dsn = 1 ) csp = om . rect . ContinuousSteppedPainter ( keyText = desc + ' Model' ) csp . setFloats ( model_x , model_y ) p . add ( csp ) csp = om . rect . ContinuousSteppedPainter ( keyText = None ) csp . setFloats ( data_hist_x , data_hist_y ) p . add ( csp ) p . addXYErr ( data_plot . x , data_plot . y , data_plot . yerr , desc + ' Data' , lines = 0 , dsn = 1 ) p . setLabels ( data_plot . xlabel , data_plot . ylabel ) p . setLinLogAxes ( True , False ) p . setBounds ( xlow , xhigh ) return p , xlow , xhigh
Make a plot of a spectral model and data.

    *model_plot*
      A model plot object returned by Sherpa from a call like `ui.get_model_plot()`
      or `ui.get_bkg_model_plot()`.
    *data_plot*
      A data plot object returned by Sherpa from a call like `ui.get_source_plot()`
      or `ui.get_bkg_plot()`.
    *desc*
      Text describing the origin of the data; will be shown in the plot legend
      (with "Model" and "Data" appended).
    *xmin_clamp*
      The smallest "x" (energy axis) value that will be plotted; default is 0.01.
      This is needed to allow the plot to be shown on a logarithmic scale if
      the energy axes of the model go all the way to 0.
    *min_valid_x*
      Either None, or the smallest "x" (energy axis) value in which the model and
      data are valid; this could correspond to a range specified in the "notice"
      command during analysis. If specified, a gray band will be added to the plot
      showing the invalidated regions.
    *max_valid_x*
      Like *min_valid_x* but for the largest "x" (energy axis) value in which the
      model and data are valid.
    Returns:
      A tuple ``(plot, xlow, xhigh)``, where *plot* an OmegaPlot RectPlot
      instance, *xlow* is the left edge of the plot bounds, and *xhigh* is the
      right edge of the plot bounds.