Exemplo n.º 1
0
def _misfit_page(config):
    """Generate an HTML page with misfit plots."""
    # Read template files
    template_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                'html_report_template')
    misfit_html = os.path.join(template_dir, 'misfit.html')
    misfit_html_out = os.path.join(config.options.outdir, 'misfit.html')

    # Version and run completed
    ssp_version = get_versions()['version']
    run_completed = '{} {}'.format(
        config.end_of_run.strftime('%Y-%m-%d %H:%M:%S'), config.end_of_run_tz)

    # event info
    hypo = config.hypo
    evid = hypo.evid

    # 1d conditional misfit plots
    misfit_plot_files = glob(
        os.path.join(config.options.outdir, 'misfit',
                     '{}.cond_misfit_*.png'.format(evid)))
    one_d_misfit_table_rows = _misfit_table_rows(misfit_plot_files)

    # 2d conditional misfit plots: fc-Mw
    misfit_plot_files = glob(
        os.path.join(config.options.outdir, 'misfit',
                     '{}.misfit_fc-Mw_*.png'.format(evid)))
    two_d_misfit_table_rows_fc_mw = _misfit_table_rows(misfit_plot_files)

    # 2d conditional misfit plots: fc-tstar
    misfit_plot_files = glob(
        os.path.join(config.options.outdir, 'misfit',
                     '{}.misfit_fc-t_star_*.png'.format(evid)))
    two_d_misfit_table_rows_fc_tstar = _misfit_table_rows(misfit_plot_files)

    # 2d conditional misfit plots: tstar-Mw
    misfit_plot_files = glob(
        os.path.join(config.options.outdir, 'misfit',
                     '{}.misfit_t_star-Mw_*.png'.format(evid)))
    two_d_misfit_table_rows_tstar_mw = _misfit_table_rows(misfit_plot_files)

    # Main HTML page
    replacements = {
        '{VERSION}': ssp_version,
        '{RUN_COMPLETED}': run_completed,
        '{EVENTID}': evid,
        '{1D_MISFIT_TABLE_ROWS}': one_d_misfit_table_rows,
        '{2D_MISFIT_TABLE_ROWS_FC_MW}': two_d_misfit_table_rows_fc_mw,
        '{2D_MISFIT_TABLE_ROWS_FC_TSTAR}': two_d_misfit_table_rows_fc_tstar,
        '{2D_MISFIT_TABLE_ROWS_TSTAR_MW}': two_d_misfit_table_rows_tstar_mw
    }
    misfit = open(misfit_html).read()
    misfit = _multireplace(misfit, replacements)
    with open(misfit_html_out, 'w') as fp:
        fp.write(misfit)
Exemplo n.º 2
0
def _make_fig(config, nlines, ncols):
    if nlines <= 3:
        figsize = (16, 9)
    else:
        figsize = (16, 18)
    fig = plt.figure(figsize=figsize, dpi=300)
    # Create an invisible axis and use it for title and footer
    ax0 = fig.add_subplot(111, label='ax0')
    ax0.set_axis_off()
    # Add event information as a title
    hypo = config.hypo
    textstr = 'evid: {} lon: {:.3f} lat: {:.3f} depth: {:.1f} km'
    textstr = textstr.format(
        hypo.evid, hypo.longitude, hypo.latitude, hypo.depth)
    try:
        textstr += ' time: {}'.format(
            hypo.origin_time.format_iris_web_service())
    except AttributeError:
        pass
    ax0.text(0., 1.06, textstr, fontsize=12,
             ha='left', va='top', transform=ax0.transAxes)
    if config.options.evname is not None:
        textstr = config.options.evname
        ax0.text(0., 1.1, textstr, fontsize=14,
                 ha='left', va='top', transform=ax0.transAxes)
    # Add code information at the figure bottom
    textstr = 'SourceSpec v{} '.format(get_versions()['version'])
    ax0.text(1., -0.1, textstr, fontsize=10,
             ha='right', va='top', transform=ax0.transAxes)
    axes = []
    for n in range(nlines*ncols):
        plotn = n+1
        if plotn == 1:
            ax = fig.add_subplot(nlines, ncols, plotn)
        else:
            ax = fig.add_subplot(nlines, ncols, plotn, sharex=axes[0])
        ax.grid(True, which='both', linestyle='solid', color='#DDDDDD',
                zorder=0)
        ax.set_axisbelow(True)
        ax.xaxis.set_tick_params(which='both', labelbottom=False)
        ax.yaxis.set_tick_params(which='both', labelleft=True)
        ax.tick_params(width=2)  # FIXME: ticks are below grid lines!
        ax.tick_params(labelsize=8)
        ax.yaxis.offsetText.set_fontsize(8)
        yfmt = ScalarFormatter()
        yfmt.set_powerlimits((-1, 1))
        ax.yaxis.set_major_formatter(yfmt)
        axes.append(ax)
    fig.subplots_adjust(hspace=.1, wspace=.20)
    return fig, axes
Exemplo n.º 3
0
def _update_parser(parser, progname):
    if progname == 'source_spec':
        parser.add_argument(
            '-o', '--outdir', dest='outdir',
            action='store', default='sspec_out',
            help='save output to OUTDIR (default: sspec_out)',
            metavar='OUTDIR'
        )
    elif progname == 'source_model':
        parser.add_argument(
            '-f', '--fmin', dest='fmin', action='store',
            type=float, default='0.01',
            help='minimum frequency (Hz, default 0.01)',
            metavar='FMIN'
        )
        parser.add_argument(
            '-F', '--fmax', dest='fmax', action='store',
            type=float, default='50.0',
            help='maximum frequency (Hz, default 50.0)',
            metavar='FMAX'
        )
        parser.add_argument(
            '-k', '--fc', dest='fc', action='store',
            default='10.0',
            help='(list of) corner frequency (Hz, default 10.0)',
            metavar='Fc'
        )
        parser.add_argument(
            '-m', '--mag', dest='mag', action='store',
            default='2.0',
            help='(list of) moment magnitude (default 2.0)',
            metavar='Mw'
        )
        parser.add_argument(
            '-M', '--moment', dest='Mo', action='store',
            default='NaN',
            help='(list of) seismic moment (N.m, default undefined)',
            metavar='Mo'
        )
        parser.add_argument(
            '-*', '--tstar', dest='t_star', action='store',
            default='0.0',
            help='(list of) t-star (attenuation, default 0.0)',
            metavar='T-STAR'
        )
        parser.add_argument(
            '-a', '--alpha', dest='alpha', action='store',
            default='1.0',
            help='(list of) alpha (exponent for frequency dependence\n'
                 'of attenuation, default 1.0)',
            metavar='1.0'
        )
        parser.add_argument(
            '-C', '--combine', dest='combine',
            action='store_true', default=False,
            help='generate all the combinations of fc, mag, Mo, tstar, alpha'
        )
        parser.add_argument(
            '-P', '--plot', dest='plot', action='store_true',
            default=False, help='plot results'
        )
    parser.add_argument(
        '-v', '--version', action='version',
        version=get_versions()['version']
    )
Exemplo n.º 4
0
def _make_fig(config, plot_params):
    nlines = plot_params.nlines
    ncols = plot_params.ncols
    stack_plots = plot_params.stack_plots
    if nlines <= 3 or stack_plots:
        figsize = (16, 9)
    else:
        figsize = (16, 18)
    fig = plt.figure(figsize=figsize, dpi=300)
    # Create an invisible axis and use it for title and footer
    ax0 = fig.add_subplot(111, label='ax0')
    ax0.set_axis_off()
    # Add event information as a title
    hypo = config.hypo
    textstr = 'evid: {} lon: {:.3f} lat: {:.3f} depth: {:.1f} km'
    textstr = textstr.format(
        hypo.evid, hypo.longitude, hypo.latitude, hypo.depth)
    try:
        textstr += ' time: {}'.format(
            hypo.origin_time.format_iris_web_service())
    except AttributeError:
        pass
    ax0.text(0., 1.06, textstr, fontsize=12,
             ha='left', va='top', transform=ax0.transAxes)
    if config.options.evname is not None:
        textstr = config.options.evname
        ax0.text(0., 1.1, textstr, fontsize=14,
                 ha='left', va='top', transform=ax0.transAxes)
    # Add code information at the figure bottom
    textstr = 'SourceSpec v{} '.format(get_versions()['version'])
    if not stack_plots:
        textstr += '– {} {}\n'.format(
            config.end_of_run.strftime('%Y-%m-%d %H:%M:%S'),
            config.end_of_run_tz)
    ax0.text(1., -0.1, textstr, fontsize=10,
             ha='right', va='top', transform=ax0.transAxes)
    axes = []
    for n in range(nlines*ncols):
        plotn = n+1
        # ax1 has moment units (or weight)
        if plotn == 1:
            if stack_plots:
                ax = fig.add_subplot(1, 1, 1, label='ax')
            else:
                ax = fig.add_subplot(nlines, ncols, plotn)
        else:
            if not stack_plots:
                ax = fig.add_subplot(
                    nlines, ncols, plotn,
                    sharex=axes[0][0], sharey=axes[0][0])
        ax.set_xlim(plot_params.freq_minmax)
        ax.set_ylim(plot_params.moment_minmax)
        ax.grid(
            True, which='both', linestyle='solid', color='#DDDDDD', zorder=0)
        ax.set_axisbelow(True)
        ax.xaxis.set_tick_params(which='both', labelbottom=False)
        ax.yaxis.set_tick_params(which='both', labelleft=False)
        ax.tick_params(width=2)  # FIXME: ticks are below grid lines!
        # ax2 has magnitude units
        if plot_params.plot_type != 'weight':
            if ((stack_plots and plotn == 1) or not stack_plots):
                ax2 = ax.twinx()
                ax2.set_ylim(plot_params.mag_minmax)
                ax2.yaxis.set_tick_params(
                    which='both', labelright=False, width=0)
        else:
            ax2 = None
        ax.has_station_text = False
        axes.append((ax, ax2))
    fig.subplots_adjust(hspace=.025, wspace=.03)
    plot_params.figures.append(fig)
    plot_params.axes = axes
    plot_params.ax0 = ax0
    plot_params.plotn = 0
Exemplo n.º 5
0
def _plot_stations(config, lonlat_dist, st_ids, values, vmean, verr, vname):
    maxdist = np.max(lonlat_dist[:, 2])
    ax, circle_texts = _make_basemap(config, maxdist)

    if config.options.evname is not None:
        textstr = '{} — '.format(config.options.evname)
    else:
        textstr = ''
    if vname == 'mag':
        verr_minus = verr_plus = verr
        textstr += 'Mw {:.2f} ± {:.2f}'.format(vmean, verr)
    elif vname == 'fc':
        verr_minus, verr_plus = verr
        textstr += 'fc {:.3f} [- {:.3f}, + {:.3f}] Hz'.format(
            vmean, verr_minus, verr_plus)
    ax.text(0.,
            1.22,
            textstr,
            fontsize=14,
            ha='left',
            va='top',
            transform=ax.transAxes)

    if vname == 'mag':
        vmax = np.max(np.abs(values - vmean))
        vmin = -vmax
        vmax += vmean
        vmin += vmean
        if vmax == vmin:
            vmax = vmean + 0.5
            vmin = vmean - 0.5
        cbar_extend = 'neither'
        cmap = cm.Spectral_r
    elif vname == 'fc':
        vmin = np.min(values)
        vmax = np.max(values)
        cbar_extend = 'neither'
        # limit colorbar to ±3sigma
        if vmax > vmean + 3 * verr_plus:
            vmax = vmean + 3 * verr_plus
            cbar_extend = 'max'
        if vmin < vmean - 3 * verr_minus:
            vmin = vmean - 3 * verr_minus
            if cbar_extend == 'max':
                cbar_extend = 'both'
            else:
                cbar_extend = 'min'
        if vmax == vmin:
            vmax = vmean + 1
            vmin = vmean - 1
        midpoint = (vmean - vmin) / (vmax - vmin)
        cmap = _shiftedColorMap(cm.PRGn, midpoint=midpoint)
    # Corner case, when errorbars are larger than vmin or vmax
    if vmin > vmean - verr_minus:
        vmin = vmean - (verr_minus * 1.1)
    if vmax < vmean + verr_plus:
        vmax = vmean + (verr_plus * 1.1)
    norm = colors.Normalize(vmin=vmin, vmax=vmax)

    trans = ccrs.PlateCarree()
    lonlat = lonlat_dist[:, :2]
    ax.scatter(lonlat[:, 0],
               lonlat[:, 1],
               marker='^',
               s=100,
               color=cmap(norm(values)),
               edgecolor='k',
               zorder=99,
               transform=trans)
    if config.plot_station_names_on_map:
        texts = []
        for ll, id in zip(lonlat, st_ids):
            id = '.'.join(id.split('.')[:2])
            id = '  ' + id
            station_text_size = config.plot_station_text_size
            t = ax.text(ll[0],
                        ll[1],
                        id,
                        size=station_text_size,
                        weight='bold',
                        va='center',
                        zorder=999,
                        transform=trans)
            t.set_path_effects([
                PathEffects.Stroke(linewidth=0.8, foreground='white'),
                PathEffects.Normal()
            ])
            texts.append(t)

    # Add a colorbar
    ax_divider = make_axes_locatable(ax)
    cax = ax_divider.append_axes('right',
                                 size='6%',
                                 pad='15%',
                                 axes_class=plt.Axes)
    sm = cm.ScalarMappable(cmap=cmap, norm=norm)
    sm.set_array([])
    fig = ax.get_figure()
    fig.colorbar(sm, cax=cax, extend=cbar_extend)
    cax.get_yaxis().set_visible(True)
    cax.axhline(vmean, lw=2, color='black')
    linestyle = (0, (2, 1))
    linewidth = 1.5
    color = _contrast_color(cmap(norm(vmean - verr_minus)))
    cax.axhline(vmean - verr_minus,
                lw=linewidth,
                linestyle=linestyle,
                color=color)
    color = _contrast_color(cmap(norm(vmean + verr_plus)))
    cax.axhline(vmean + verr_plus,
                lw=linewidth,
                linestyle=linestyle,
                color=color)
    if vname == 'mag':
        cm_label = 'Magnitude'
    elif vname == 'fc':
        cm_label = 'Corner Frequency (Hz)'
    cax.set_ylabel(cm_label)
    # Add code information at the figure bottom
    textstr = 'SourceSpec v{} '.format(get_versions()['version'])
    textstr += '– {} {}\n'.format(
        config.end_of_run.strftime('%Y-%m-%d %H:%M:%S'), config.end_of_run_tz)
    cax.text(1.,
             -0.1,
             textstr,
             fontsize=8,
             ha='right',
             va='top',
             transform=cax.transAxes)

    if config.plot_station_names_on_map:
        # first adjust text labels relatively to each other
        adjust_text(texts, ax=ax, maxshift=1e3)
        # then, try to stay away from circle texts
        adjust_text(texts, add_objects=circle_texts, ax=ax, maxshift=1e3)

    evid = config.hypo.evid
    figfile_base = os.path.join(config.options.outdir, evid)
    figfile_base += '.map_{}.'.format(vname)
    fmt = config.PLOT_SAVE_FORMAT
    if fmt == 'pdf_multipage':
        fmt = 'pdf'
    figfile = figfile_base + fmt
    if config.PLOT_SHOW:
        plt.show()
    if config.PLOT_SAVE:
        savefig(fig, figfile, fmt, quantize_colors=False, bbox_inches='tight')
        if vname == 'mag':
            logger.info('Station-magnitude map saved to: ' + figfile)
        elif vname == 'fc':
            logger.info('Station-corner_freq map saved to: ' + figfile)
Exemplo n.º 6
0
def setup_logging(config, basename=None, progname='source_spec'):
    """
    Set up the logging infrastructure.

    This function is typically called twice: the first time without basename
    and a second time with a basename (typically the eventid).
    When called the second time, the previous logfile is renamed using the
    given basename.
    """
    global oldlogfile
    global logger
    global PYTHON_VERSION_STR
    global OBSPY_VERSION_STR
    global NUMPY_VERSION_STR
    global SCIPY_VERSION_STR
    global MATPLOTLIB_VERSION_STR
    global CARTOPY_VERSION_STR
    # Create outdir
    if not os.path.exists(config.options.outdir):
        os.makedirs(config.options.outdir)

    if basename:
        logfile = os.path.join(config.options.outdir, '%s.ssp.log' % basename)
    else:
        datestring = datetime.now().strftime('%Y%m%d_%H%M%S')
        logfile = os.path.join(config.options.outdir,
                               '%s.ssp.log' % datestring)

    logger_root = logging.getLogger()
    if oldlogfile:
        hdlrs = logger_root.handlers[:]
        for hdlr in hdlrs:
            hdlr.flush()
            hdlr.close()
            logger_root.removeHandler(hdlr)
        # Copy old logfile to new
        shutil.copyfile(oldlogfile, logfile)
        # Remove old logfile from old and new dir
        os.remove(oldlogfile)
        oldlogfile = os.path.join(
            config.options.outdir, os.path.basename(oldlogfile))
        os.remove(oldlogfile)
        filemode = 'a'
    else:
        filemode = 'w'

    # captureWarnings is not supported in old versions of python
    try:
        logging.captureWarnings(True)
    except Exception:
        pass
    logger_root.setLevel(logging.DEBUG)
    filehand = logging.FileHandler(filename=logfile, mode=filemode)
    filehand.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s %(name)-20s '
                                  '%(levelname)-8s %(message)s')
    filehand.setFormatter(formatter)
    logger_root.addHandler(filehand)

    console = logging.StreamHandler()
    console.setLevel(logging.INFO)

    # Add logger color coding on all platforms but win32
    if sys.platform != 'win32' and sys.stdout.isatty():
        console.emit = _color_handler_emit(console.emit)
    logger_root.addHandler(console)

    logger = logging.getLogger(progname)

    # Only write these debug infos for a new logfile
    if not oldlogfile:
        logger.debug('source_spec START')
        logger.debug('SourceSpec version: ' + get_versions()['version'])
        uname = platform.uname()
        uname_str = '{} {} {}'.format(uname[0], uname[2], uname[4])
        logger.debug('Platform: ' + uname_str)
        logger.debug('Python version: ' + PYTHON_VERSION_STR)
        logger.debug('ObsPy version: ' + OBSPY_VERSION_STR)
        logger.debug('NumPy version: ' + NUMPY_VERSION_STR)
        logger.debug('SciPy version: ' + SCIPY_VERSION_STR)
        logger.debug('Matplotlib version: ' + MATPLOTLIB_VERSION_STR)
        if CARTOPY_VERSION_STR is not None:
            logger.debug('Cartopy version: ' + CARTOPY_VERSION_STR)
        logger.debug('Running arguments:')
        logger.debug(' '.join(sys.argv))
    oldlogfile = logfile

    # See if there are warnings to deliver
    for _ in range(len(config.warnings)):
        msg = config.warnings.pop(0)
        logger.warning(msg)
Exemplo n.º 7
0
def html_report(config, sourcepar):
    """Generate an HTML report."""
    # Read template files
    template_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                'html_report_template')
    style_css = os.path.join(template_dir, 'style.css')
    index_html = os.path.join(template_dir, 'index.html')
    index_html_out = os.path.join(config.options.outdir, 'index.html')
    traces_plot_html = os.path.join(template_dir, 'traces_plot.html')
    spectra_plot_html = os.path.join(template_dir, 'spectra_plot.html')
    station_table_row_html = os.path.join(template_dir,
                                          'station_table_row.html')
    quakeml_file_link_html = os.path.join(template_dir,
                                          'quakeml_file_link.html')

    # Copy CSS to output dir
    shutil.copy(style_css, config.options.outdir)

    # Version and run completed
    ssp_version = get_versions()['version']
    run_completed = '{} {}'.format(
        config.end_of_run.strftime('%Y-%m-%d %H:%M:%S'), config.end_of_run_tz)

    # Output files and maps
    hypo = config.hypo
    evid = hypo.evid
    config_file = '{}.ssp.conf'.format(evid)
    out_file = '{}.ssp.out'.format(evid)
    log_file = '{}.ssp.log'.format(evid)
    quakeml_file = '{}.xml'.format(evid)
    map_mag = '{}.map_mag.png'.format(evid)
    map_fc = '{}.map_fc.png'.format(evid)
    box_plots = '{}.boxplot.png'.format(evid)

    # Trace plot files
    traces_plot = open(traces_plot_html).read()
    traces_plot_files = glob(
        os.path.join(config.options.outdir, '*.traces.png'))
    traces_plot_files += glob(
        os.path.join(config.options.outdir, '*.traces.??.png'))
    traces_plots = ''
    traces_plot_id = ''
    for traces_plot_file in sorted(traces_plot_files):
        traces_plot_file = os.path.basename(traces_plot_file)
        traces_plots += traces_plot.replace('{TRACES_PLOT_ID}',
                                            traces_plot_id).replace(
                                                '{TRACES_PLOT_FILE}',
                                                traces_plot_file)
        traces_plot_id = ' id="print"'

    # Spectral plot files
    spectra_plot = open(spectra_plot_html).read()
    spectra_plot_files = glob(os.path.join(config.options.outdir, '*.ssp.png'))
    spectra_plot_files += glob(
        os.path.join(config.options.outdir, '*.ssp.??.png'))
    spectra_plots = ''
    spectra_plot_id = ''
    for spectra_plot_file in sorted(spectra_plot_files):
        spectra_plot_file = os.path.basename(spectra_plot_file)
        spectra_plots += spectra_plot.replace('{SPECTRA_PLOT_ID}',
                                              spectra_plot_id).replace(
                                                  '{SPECTRA_PLOT_FILE}',
                                                  spectra_plot_file)
        spectra_plot_id = ' id="print"'

    # Station table
    station_table_row = open(station_table_row_html).read()
    station_table_rows = ''
    stationpar = sourcepar.station_parameters
    for statId in sorted(stationpar.keys()):
        if statId in ['means', 'errors', 'means_weight', 'errors_weight']:
            continue
        par = stationpar[statId]
        id, type = statId.split()
        Mw_text, Mw_err_text = _value_and_err_text(par, 'Mw', '{:.3f}')
        fc_text, fc_err_text = _value_and_err_text(par, 'fc', '{:.3f}')
        t_star_text, t_star_err_text =\
            _value_and_err_text(par, 't_star', '{:.3f}')
        Qo_text, Qo_err_text = _value_and_err_text(par, 'Qo', '{:.1f}')
        Mo_text, Mo_err_text = _value_and_err_text(par, 'Mo', '{:.3e}')
        bsd_text, bsd_err_text = _value_and_err_text(par, 'bsd', '{:.3e}')
        ra_text, ra_err_text = _value_and_err_text(par, 'ra', '{:.3f}')
        hyp_dist_text, _ = _value_and_err_text(par, 'hyp_dist', '{:.3f}')
        az_text, _ = _value_and_err_text(par, 'az', '{:.3f}')
        Er_text, _ = _value_and_err_text(par, 'Er', '{:.3e}')
        replacements = {
            '{STATION_ID}': id,
            '{STATION_TYPE}': type,
            '{STATION_MW}': Mw_text,
            '{STATION_MW_ERR}': Mw_err_text,
            '{STATION_FC}': fc_text,
            '{STATION_FC_ERR}': fc_err_text,
            '{STATION_TSTAR}': t_star_text,
            '{STATION_TSTAR_ERR}': t_star_err_text,
            '{STATION_Q0}': Qo_text,
            '{STATION_Q0_ERR}': Qo_err_text,
            '{STATION_M0}': Mo_text,
            '{STATION_M0_ERR}': Mo_err_text,
            '{STATION_BSD}': bsd_text,
            '{STATION_BSD_ERR}': bsd_err_text,
            '{STATION_RA}': ra_text,
            '{STATION_RA_ERR}': ra_err_text,
            '{STATION_DIST}': hyp_dist_text,
            '{STATION_AZ}': az_text,
            '{STATION_ER}': Er_text,
        }
        station_table_rows += _multireplace(station_table_row, replacements)

    # Main HTML page
    means = sourcepar.means
    errors = sourcepar.errors
    means_weight = sourcepar.means_weight
    errors_weight = sourcepar.errors_weight
    Mw_mean = means['Mw']
    Mw_error = errors['Mw']
    Mw_mean_weight = means_weight['Mw']
    Mw_error_weight = errors_weight['Mw']
    Mo_mean = means['Mo']
    Mo_minus, Mo_plus = errors['Mo']
    Mo_mean_weight = means_weight['Mo']
    Mo_minus_weight, Mo_plus_weight = errors_weight['Mo']
    fc_mean = means['fc']
    fc_minus, fc_plus = errors['fc']
    fc_mean_weight = means_weight['fc']
    fc_minus_weight, fc_plus_weight = errors_weight['fc']
    t_star_mean = means['t_star']
    t_star_error = errors['t_star']
    t_star_mean_weight = means_weight['t_star']
    t_star_error_weight = errors_weight['t_star']
    Qo_mean = means['Qo']
    Qo_error = errors['Qo']
    Qo_mean_weight = means_weight['Qo']
    Qo_error_weight = errors_weight['Qo']
    ra_mean = means['ra']
    ra_minus, ra_plus = errors['ra']
    ra_mean_weight = means_weight['ra']
    ra_minus_weight, ra_plus_weight = errors_weight['ra']
    bsd_mean = means['bsd']
    bsd_minus, bsd_plus = errors['bsd']
    bsd_mean_weight = means_weight['bsd']
    bsd_minus_weight, bsd_plus_weight = errors_weight['bsd']
    Er_mean = means['Er']
    Er_minus, Er_plus = errors['Er']
    replacements = {
        '{VERSION}':
        ssp_version,
        '{RUN_COMPLETED}':
        run_completed,
        '{EVENTID}':
        evid,
        '{EVENT_LONGITUDE}':
        '{:8.3f}'.format(hypo.longitude),
        '{EVENT_LATITUDE}':
        '{:7.3f}'.format(hypo.latitude),
        '{EVENT_DEPTH}':
        '{:5.1f}'.format(hypo.depth),
        '{ORIGIN_TIME}':
        '{}'.format(hypo.origin_time),
        '{MW}':
        '{:.2f}'.format(Mw_mean),
        '{MW_ERR}':
        '{:.2f}'.format(Mw_error),
        '{MW_WEIGHT}':
        '{:.2f}'.format(Mw_mean_weight),
        '{MW_WEIGHT_ERR}':
        '{:.2f}'.format(Mw_error_weight),
        '{M0}':
        '{:.3e}'.format(Mo_mean),
        '{M0_ERR_MINUS}':
        '{}'.format(_format_exponent(Mo_minus, Mo_mean)),
        '{M0_ERR_PLUS}':
        '{}'.format(_format_exponent(Mo_plus, Mo_mean)),
        '{M0_WEIGHT}':
        '{:.3e}'.format(Mo_mean_weight),
        '{M0_WEIGHT_ERR_MINUS}':
        '{}'.format(_format_exponent(Mo_minus_weight, Mo_mean_weight)),
        '{M0_WEIGHT_ERR_PLUS}':
        '{}'.format(_format_exponent(Mo_plus_weight, Mo_mean_weight)),
        '{FC}':
        '{:.3f}'.format(fc_mean),
        '{FC_ERR_MINUS}':
        '{:.3f}'.format(fc_minus),
        '{FC_ERR_PLUS}':
        '{:.3f}'.format(fc_plus),
        '{FC_WEIGHT}':
        '{:.3f}'.format(fc_mean_weight),
        '{FC_WEIGHT_ERR_MINUS}':
        '{:.3f}'.format(fc_minus_weight),
        '{FC_WEIGHT_ERR_PLUS}':
        '{:.3f}'.format(fc_plus_weight),
        '{TSTAR}':
        '{:.3f}'.format(t_star_mean),
        '{TSTAR_ERR}':
        '{:.3f}'.format(t_star_error),
        '{TSTAR_WEIGHT}':
        '{:.3f}'.format(t_star_mean_weight),
        '{TSTAR_WEIGHT_ERR}':
        '{:.3f}'.format(t_star_error_weight),
        '{Q0}':
        '{:.1f}'.format(Qo_mean),
        '{Q0_ERR}':
        '{:.1f}'.format(Qo_error),
        '{Q0_WEIGHT}':
        '{:.1f}'.format(Qo_mean_weight),
        '{Q0_WEIGHT_ERR}':
        '{:.1f}'.format(Qo_error_weight),
        '{RADIUS}':
        '{:.3f}'.format(ra_mean),
        '{RADIUS_ERR_MINUS}':
        '{:.3f}'.format(ra_minus),
        '{RADIUS_ERR_PLUS}':
        '{:.3f}'.format(ra_plus),
        '{RADIUS_WEIGHT}':
        '{:.3f}'.format(ra_mean_weight),
        '{RADIUS_WEIGHT_ERR_MINUS}':
        '{:.3f}'.format(ra_minus_weight),
        '{RADIUS_WEIGHT_ERR_PLUS}':
        '{:.3f}'.format(ra_plus_weight),
        '{BSD}':
        '{:.3e}'.format(bsd_mean),
        '{BSD_ERR_MINUS}':
        '{}'.format(_format_exponent(bsd_minus, bsd_mean)),
        '{BSD_ERR_PLUS}':
        '{}'.format(_format_exponent(bsd_plus, bsd_mean)),
        '{BSD_WEIGHT}':
        '{:.3e}'.format(bsd_mean_weight),
        '{BSD_WEIGHT_ERR_MINUS}':
        '{}'.format(_format_exponent(bsd_minus_weight, bsd_mean_weight)),
        '{BSD_WEIGHT_ERR_PLUS}':
        '{}'.format(_format_exponent(bsd_plus_weight, bsd_mean_weight)),
        '{ER}':
        '{:.3e}'.format(Er_mean),
        '{ER_ERR_MINUS}':
        '{}'.format(_format_exponent(Er_minus, Er_mean)),
        '{ER_ERR_PLUS}':
        '{}'.format(_format_exponent(Er_plus, Er_mean)),
        '{CONF_FILE_BNAME}':
        config_file,
        '{CONF_FILE}':
        config_file,
        '{OUT_FILE_BNAME}':
        out_file,
        '{OUT_FILE}':
        out_file,
        '{LOG_FILE_BNAME}':
        log_file,
        '{LOG_FILE}':
        log_file,
        '{MAP_MAG}':
        map_mag,
        '{MAP_FC}':
        map_fc,
        '{TRACES_PLOTS}':
        traces_plots,
        '{SPECTRA_PLOTS}':
        spectra_plots,
        '{BOX_PLOTS}':
        box_plots,
        '{STATION_TABLE_ROWS}':
        station_table_rows,
    }

    # Misfit plots (when using grid search)
    if os.path.exists(os.path.join(config.options.outdir, 'misfit')):
        misfit_plot_comment_begin = ''
        misfit_plot_comment_end = ''
        _misfit_page(config)
    else:
        misfit_plot_comment_begin = '<!--'
        misfit_plot_comment_end = '-->'
    replacements.update({
        '{MISFIT_PLOT_COMMENT_BEGIN}': misfit_plot_comment_begin,
        '{MISFIT_PLOT_COMMENT_END}': misfit_plot_comment_end
    })

    # QuakeML file (if produced)
    if os.path.exists(os.path.join(config.options.outdir, quakeml_file)):
        quakeml_file_link = open(quakeml_file_link_html).read()
        quakeml_file_link = quakeml_file_link\
            .replace('{QUAKEML_FILE}', quakeml_file)\
            .replace('{QUAKEML_FILE_BNAME}', quakeml_file)
    else:
        quakeml_file_link = ''
    replacements.update({'{QUAKEML_FILE_LINK}': quakeml_file_link})

    index = open(index_html).read()
    index = _multireplace(index, replacements)
    with open(index_html_out, 'w') as fp:
        fp.write(index)
    logger.info('HTML report written to file: ' + index_html_out)
Exemplo n.º 8
0
def write_qml(config, sourcepar):
    if not config.options.qml_file:
        return
    qml_file = config.options.qml_file
    cat = read_events(qml_file)
    evid = config.hypo.evid
    try:
        ev = [e for e in cat if evid in str(e.resource_id)][0]
    except Exception:
        logging.warning('Unable to find evid "{}" in QuakeML file. '
                        'QuakeML output will not be written.'.format(evid))

    origin = ev.preferred_origin()
    if origin is None:
        origin = ev.origins[0]
    origin_id = origin.resource_id
    origin_id_strip = origin_id.id.split('/')[-1]
    origin_id_strip = origin_id_strip.replace(config.smi_strip_from_origin_id,
                                              '')

    # Common parameters
    ssp_version = get_versions()['version']
    method_id = config.smi_base + '/sourcespec/' + ssp_version
    cr_info = CreationInfo()
    cr_info.agency_id = config.agency_id
    if config.author is None:
        author = '{}@{}'.format(getuser(), gethostname())
    else:
        author = config.author
    cr_info.author = author
    cr_info.creation_time = UTCDateTime()

    means = sourcepar.means_weight
    errors = sourcepar.errors_weight
    stationpar = sourcepar.station_parameters

    # Magnitude
    mag = Magnitude()
    _id = config.smi_magnitude_template.replace('$SMI_BASE', config.smi_base)
    _id = _id.replace('$ORIGIN_ID', origin_id_strip)
    mag.resource_id = ResourceIdentifier(id=_id)
    mag.method_id = ResourceIdentifier(id=method_id)
    mag.origin_id = origin_id
    mag.magnitude_type = 'Mw'
    mag.mag = means['Mw']
    mag_err = QuantityError()
    mag_err.uncertainty = errors['Mw']
    mag_err.confidence_level = 68.2
    mag.mag_errors = mag_err
    mag.station_count = len([_s for _s in stationpar.keys()])
    mag.evaluation_mode = 'automatic'
    mag.creation_info = cr_info

    # Seismic moment -- It has to be stored in a MomentTensor object
    # which, in turn, is part of a FocalMechanism object
    mt = MomentTensor()
    _id = config.smi_moment_tensor_template.replace('$SMI_BASE',
                                                    config.smi_base)
    _id = _id.replace('$ORIGIN_ID', origin_id_strip)
    mt.resource_id = ResourceIdentifier(id=_id)
    mt.derived_origin_id = origin_id
    mt.moment_magnitude_id = mag.resource_id
    mt.scalar_moment = means['Mo']
    mt_err = QuantityError()
    mt_err.lower_uncertainty = errors['Mo'][0]
    mt_err.upper_uncertainty = errors['Mo'][1]
    mt_err.confidence_level = 68.2
    mt.scalar_moment_errors = mt_err
    mt.method_id = method_id
    mt.creation_info = cr_info
    # And here is the FocalMechanism object
    fm = FocalMechanism()
    _id = config.smi_focal_mechanism_template.replace('$SMI_BASE',
                                                      config.smi_base)
    _id = _id.replace('$ORIGIN_ID', origin_id_strip)
    fm.resource_id = ResourceIdentifier(id=_id)
    fm.triggering_origin_id = origin_id
    fm.method_id = ResourceIdentifier(id=method_id)
    fm.moment_tensor = mt
    fm.creation_info = cr_info
    ev.focal_mechanisms.append(fm)

    # Station magnitudes
    for statId in sorted(stationpar.keys()):
        par = stationpar[statId]
        st_mag = StationMagnitude()
        seed_id = statId.split()[0]
        _id = config.smi_station_magnitude_template.replace(
            '$SMI_MAGNITUDE_TEMPLATE', config.smi_magnitude_template)
        _id = _id.replace('$ORIGIN_ID', origin_id_strip)
        _id = _id.replace('$SMI_BASE', config.smi_base)
        _id = _id.replace('$WAVEFORM_ID', seed_id)
        st_mag.resource_id = ResourceIdentifier(id=_id)
        st_mag.origin_id = origin_id
        st_mag.mag = par['Mw']
        st_mag.station_magnitude_type = 'Mw'
        st_mag.method_id = mag.method_id
        st_mag.creation_info = cr_info
        st_mag.waveform_id = WaveformStreamID(seed_string=seed_id)
        st_mag.extra = SSPExtra()
        st_mag.extra.moment = SSPTag(par['Mo'])
        st_mag.extra.corner_frequency = SSPTag(par['fc'])
        st_mag.extra.t_star = SSPTag(par['t_star'])
        ev.station_magnitudes.append(st_mag)
        st_mag_contrib = StationMagnitudeContribution()
        st_mag_contrib.station_magnitude_id = st_mag.resource_id
        mag.station_magnitude_contributions.append(st_mag_contrib)
    ev.magnitudes.append(mag)

    # Write other average parameters as custom tags
    ev.extra = SSPExtra()
    ev.extra.corner_frequency = SSPContainerTag()
    ev.extra.corner_frequency.value.value = SSPTag(means['fc'])
    ev.extra.corner_frequency.value.lower_uncertainty =\
        SSPTag(errors['fc'][0])
    ev.extra.corner_frequency.value.upper_uncertainty =\
        SSPTag(errors['fc'][1])
    ev.extra.corner_frequency.value.confidence_level = SSPTag(68.2)
    ev.extra.t_star = SSPContainerTag()
    ev.extra.t_star.value.value = SSPTag(means['t_star'])
    ev.extra.t_star.value.uncertainty = SSPTag(errors['t_star'])
    ev.extra.t_star.value.confidence_level = SSPTag(68.2)
    ev.extra.source_radius = SSPContainerTag()
    ev.extra.source_radius.value.value = SSPTag(means['ra'])
    ev.extra.source_radius.value.lower_uncertainty =\
        SSPTag(errors['ra'][0])
    ev.extra.source_radius.value.upper_uncertainty =\
        SSPTag(errors['ra'][1])
    ev.extra.source_radius.value.confidence_level = SSPTag(68.2)
    ev.extra.stress_drop = SSPContainerTag()
    ev.extra.stress_drop.value.value = SSPTag(means['bsd'])
    ev.extra.stress_drop.value.lower_uncertainty =\
        SSPTag(errors['bsd'][0])
    ev.extra.stress_drop.value.upper_uncertainty =\
        SSPTag(errors['bsd'][1])
    ev.extra.stress_drop.value.confidence_level = SSPTag(68.2)

    if config.set_preferred_magnitude:
        ev.preferred_magnitude_id = mag.resource_id.id

    qml_file_out = os.path.join(config.options.outdir, evid + '.xml')
    ev.write(qml_file_out, format='QUAKEML')
    logging.info('QuakeML file written to: ' + qml_file_out)