예제 #1
0
 def test_create3(self):
     """
     Create edges from profiles 3
     """
     # sampling: profile, edge
     # MN: 'msh' assigned but never used
     msh = create_from_profiles(self.profiles2, 50, 50, False)
예제 #2
0
 def setUp(self):
     path = os.path.join(BASE_DATA_PATH, '../data/slab/cs04/*.csv')
     profiles2 = []
     for filename in sorted(glob.glob(path)):
         profiles2.append(_read_profile(filename))
     #
     # building the mesh
     self.msh = create_from_profiles(profiles2, 50, 50, False)
예제 #3
0
 def setUp(self):
     path = os.path.join(BASE_DATA_PATH, 'profiles06')
     self.profiles, _ = _read_profiles(path)
     self.h_sampl = 4
     self.v_sampl = 4
     idl = False
     alg = False
     self.smsh = create_from_profiles(self.profiles, self.h_sampl,
                                      self.v_sampl, idl, alg)
예제 #4
0
 def test_mesh_creation_with_alignment(self):
     """ Test construction of the mesh """
     h_sampl = 4
     v_sampl = 4
     idl = False
     alg = True
     smsh = create_from_profiles(self.profiles, h_sampl, v_sampl, idl, alg)
     # ppp(self.profiles, smsh)
     idx = numpy.isfinite(smsh[:, :, 0])
예제 #5
0
 def test_mesh_creation(self):
     """ Test construction of the mesh """
     h_sampl = 5
     v_sampl = 5
     idl = False
     alg = False
     smsh = create_from_profiles(self.profiles, h_sampl, v_sampl, idl, alg)
     # ppp(self.profiles, smsh)
     # plotter(self.profiles, smsh)
     idx = numpy.isfinite(smsh[:, :, 0])
예제 #6
0
 def test_mesh_creation(self):
     """ Create mesh from profiles for SA """
     sampling = 40
     idl = False
     alg = False
     smsh = create_from_profiles(self.profiles, sampling, sampling, idl,
                                 alg)
     # ppp(self.profiles, smsh)
     # plotter(self.profiles, smsh)
     idx = numpy.isfinite(smsh[:, :, 0])
     self.assertEqual(numpy.sum(numpy.sum(idx)), 202)
예제 #7
0
    def test_mesh_creation(self):
        """ Create the mesh: two parallel profiles - no top alignment """
        h_sampl = 4
        v_sampl = 4
        idl = False
        alg = False
        smsh = create_from_profiles(self.profiles, h_sampl, v_sampl, idl, alg)

        # plotter(self.profiles, smsh)

        #
        # Check the horizontal mesh spacing
        computed = []
        for i in range(0, smsh.shape[0]):
            tmp = []
            for j in range(0, smsh.shape[1] - 1):
                k = j + 1
                dst = distance(smsh[i, j, 0], smsh[i, j, 1], smsh[i, j, 2],
                               smsh[i, k, 0], smsh[i, k, 1], smsh[i, k, 2])
                tmp.append(dst)
            computed.append(dst)
        computed = numpy.array(computed)
        self.assertTrue(numpy.all(abs(computed - h_sampl) / h_sampl < 0.05))
        #
        # Check the vertical mesh spacing
        computed = []
        for i in range(0, smsh.shape[0] - 1):
            tmp = []
            k = i + 1
            for j in range(0, smsh.shape[1]):
                dst = distance(smsh[i, j, 0], smsh[i, j, 1], smsh[i, j, 2],
                               smsh[k, j, 0], smsh[k, j, 1], smsh[k, j, 2])
                tmp.append(dst)
            computed.append(dst)
        computed = numpy.array(computed)
        print(numpy.amax(abs(computed - v_sampl) / v_sampl))
        self.assertTrue(numpy.all(abs(computed - v_sampl) / v_sampl < 0.05))
예제 #8
0
 def _test_create4(self):
     """
     Create edges from profiles 3
     """
     msh = create_from_profiles(self.profiles3, 5, 5, False)
     assert not np.any(np.isnan(msh))
예제 #9
0
def calculate_ruptures(ini_fname, only_plt=False, ref_fdr=None):
    """
    :param str ini_fname:
        The name of a .ini file
    :param ref_fdr:
        The path to the reference folder used to set the paths in the .ini
        file. If not provided directly, we use the one set in the .ini file.
    """
    #
    # read config file
    config = configparser.ConfigParser()
    config.readfp(open(ini_fname))
    #
    # logging settings
    logging.basicConfig(format='rupture:%(levelname)s:%(message)s')
    #
    # reference folder
    if ref_fdr is None:
        ref_fdr = config.get('main', 'reference_folder')
    #
    # set parameters
    profile_sd_topsl = config.getfloat('main', 'profile_sd_topsl')
    edge_sd_topsl = config.getfloat('main', 'edge_sd_topsl')
    # this sampling distance is used to
    sampling = config.getfloat('main', 'sampling')
    float_strike = config.getfloat('main', 'float_strike')
    float_dip = config.getfloat('main', 'float_dip')
    slab_thickness = config.getfloat('main', 'slab_thickness')
    label = config.get('main', 'label')
    hspa = config.getfloat('main', 'hspa')
    vspa = config.getfloat('main', 'vspa')
    uniform_fraction = config.getfloat('main', 'uniform_fraction')
    #
    # MFD params
    agr = config.getfloat('main', 'agr')
    bgr = config.getfloat('main', 'bgr')
    mmax = config.getfloat('main', 'mmax')
    mmin = config.getfloat('main', 'mmin')
    #
    # IDL
    if config.has_option('main', 'idl'):
        idl = config.get('main', 'idl')
    else:
        idl = False
    #
    # IDL
    align = False
    if config.has_option('main', 'profile_alignment'):
        tmps = config.get('main', 'profile_alignment')
        if re.search('true', tmps.lower()):
            align = True
    #
    # set profile folder
    path = config.get('main', 'profile_folder')
    path = os.path.abspath(os.path.join(ref_fdr, path))
    #
    # catalogue
    cat_pickle_fname = config.get('main', 'catalogue_pickle_fname')
    cat_pickle_fname = os.path.abspath(os.path.join(ref_fdr, cat_pickle_fname))
    #
    # output
    hdf5_filename = config.get('main', 'out_hdf5_fname')
    hdf5_filename = os.path.abspath(os.path.join(ref_fdr, hdf5_filename))
    #
    # smoothing output
    out_hdf5_smoothing_fname = config.get('main', 'out_hdf5_smoothing_fname')
    tmps = os.path.join(ref_fdr, out_hdf5_smoothing_fname)
    out_hdf5_smoothing_fname = os.path.abspath(tmps)
    #
    # tectonic regionalisation
    treg_filename = config.get('main', 'treg_fname')
    if not re.search('[a-z]', treg_filename):
        treg_filename = None
    else:
        treg_filename = os.path.abspath(os.path.join(ref_fdr, treg_filename))
    #
    #
    dips = list_of_floats_from_string(config.get('main', 'dips'))
    asprsstr = config.get('main', 'aspect_ratios')
    asprs = dict_of_floats_from_string(asprsstr)
    #
    # magnitude-scaling relationship
    msrstr = config.get('main', 'mag_scaling_relation')
    msrd = get_available_scalerel()
    if msrstr not in msrd.keys():
        raise ValueError('')
    msr = msrd[msrstr]()
    #
    # ------------------------------------------------------------------------
    logging.info('Reading profiles from: {:s}'.format(path))
    profiles, pro_fnames = _read_profiles(path)
    assert len(profiles) > 0
    #
    """
    if logging.getLogger().isEnabledFor(logging.DEBUG):
        import matplotlib.pyplot as plt
        from mpl_toolkits.mplot3d import Axes3D
        fig = plt.figure(figsize=(10, 8))
        ax = fig.add_subplot(111, projection='3d')
        for ipro, (pro, fnme) in enumerate(zip(profiles, pro_fnames)):
            tmp = [[p.longitude, p.latitude, p.depth] for p in pro.points]
            tmp = np.array(tmp)
            ax.plot(tmp[:, 0], tmp[:, 1], tmp[:, 2], 'x--b', markersize=2)
            tmps = '{:d}-{:s}'.format(ipro, os.path.basename(fnme))
            ax.text(tmp[0, 0], tmp[0, 1], tmp[0, 2], tmps)
        ax.invert_zaxis()
        ax.view_init(50, 55)
        plt.show()
    """
    #
    # create mesh from profiles
    msh = create_from_profiles(profiles, profile_sd_topsl, edge_sd_topsl, idl)
    #
    # Create inslab mesh. The one created here describes the top of the slab.
    # The output (i.e ohs) is a dictionary with the values of dip as keys. The
    # values in the dictionary are :class:`openquake.hazardlib.geo.line.Line`
    # instances
    ohs = create_inslab_meshes(msh, dips, slab_thickness, sampling)

    if only_plt:
        pass
    """
        azim = 10.
        elev = 20.
        dist = 20.

        f = mlab.figure(bgcolor=(1, 1, 1), size=(900, 600))
        vsc = -0.01
        #
        # profiles
        for ipro, (pro, fnme) in enumerate(zip(profiles, pro_fnames)):
            tmp = [[p.longitude, p.latitude, p.depth] for p in pro.points]
            tmp = np.array(tmp)
            tmp[tmp[:, 0] < 0, 0] = tmp[tmp[:, 0] < 0, 0] + 360
            mlab.plot3d(tmp[:, 0], tmp[:, 1], tmp[:, 2]*vsc, color=(1, 0, 0))
        #
        # top of the slab mesh
        plot_mesh_mayavi(msh, vsc, color=(0, 1, 0))
        #
        for key in ohs:
            for iii in range(len(ohs[key])):
                for line in ohs[key][iii]:
                    pnt = np.array([[p.longitude, p.latitude, p.depth]
                                    for p in line.points])
                    pnt[pnt[:, 0] < 0, 0] = pnt[pnt[:, 0] < 0, 0] + 360
                    mlab.plot3d(pnt[:, 0], pnt[:, 1], pnt[:, 2]*vsc,
                                color=(0, 0, 1))

        f.scene.camera.azimuth(azim)
        f.scene.camera.elevation(elev)
        mlab.view(distance=dist)
        mlab.show()
        mlab.show()

        exit(0)
    """

    if 1:
        vsc = 0.01
        import matplotlib.pyplot as plt
        # MN: 'Axes3D' imported but never used
        from mpl_toolkits.mplot3d import Axes3D
        fig = plt.figure(figsize=(10, 8))
        ax = fig.add_subplot(111, projection='3d')
        #
        # profiles
        for ipro, (pro, fnme) in enumerate(zip(profiles, pro_fnames)):
            tmp = [[p.longitude, p.latitude, p.depth] for p in pro.points]
            tmp = np.array(tmp)
            tmp[tmp[:, 0] < 0, 0] = tmp[tmp[:, 0] < 0, 0] + 360
            ax.plot(tmp[:, 0],
                    tmp[:, 1],
                    tmp[:, 2] * vsc,
                    'x--b',
                    markersize=2)
            tmps = '{:d}-{:s}'.format(ipro, os.path.basename(fnme))
            ax.text(tmp[0, 0], tmp[0, 1], tmp[0, 2] * vsc, tmps)
        #
        # top of the slab mesh
        # plot_mesh(ax, msh, vsc)
        #
        for key in ohs:
            for iii in range(len(ohs[key])):
                for line in ohs[key][iii]:
                    pnt = np.array([[p.longitude, p.latitude, p.depth]
                                    for p in line.points])
                    pnt[pnt[:, 0] < 0, 0] = pnt[pnt[:, 0] < 0, 0] + 360
                    ax.plot(pnt[:, 0], pnt[:, 1], pnt[:, 2] * vsc, '-r')
        ax.invert_zaxis()
        ax.view_init(50, 55)
        plt.show()

    #
    # The one created here describes the bottom of the slab
    lmsh = create_lower_surface_mesh(msh, slab_thickness)
    #
    # get min and max values
    milo, mila, mide, malo, mala, made = get_min_max(msh, lmsh)
    #
    # discretizing the slab
    # omsh = Mesh(msh[:, :, 0], msh[:, :, 1], msh[:, :, 2])
    # olmsh = Mesh(lmsh[:, :, 0], lmsh[:, :, 1], lmsh[:, :, 2])
    #
    # this `dlt` value [in degrees] is used to create a buffer around the mesh
    dlt = 5.0
    msh3d = Grid3d(milo - dlt, mila - dlt, mide, malo + dlt, mala + dlt, made,
                   hspa, vspa)
    # mlo, mla, mde = msh3d.select_nodes_within_two_meshesa(omsh, olmsh)
    mlo, mla, mde = msh3d.get_coordinates_vectors()
    #
    # save data on hdf5 file
    if os.path.exists(hdf5_filename):
        os.remove(hdf5_filename)
    logging.info('Creating {:s}'.format(hdf5_filename))
    fh5 = h5py.File(hdf5_filename, 'w')
    grp_slab = fh5.create_group('slab')
    dset = grp_slab.create_dataset('top', data=msh)
    dset.attrs['spacing'] = sampling
    grp_slab.create_dataset('bot', data=lmsh)
    fh5.close()
    #
    # get catalogue
    catalogue = get_catalogue(cat_pickle_fname, treg_filename, label)
    #
    # smoothing
    values, smooth = smoothing(mlo, mla, mde, catalogue, hspa, vspa,
                               out_hdf5_smoothing_fname)
    #
    # spatial index
    # r = spatial_index(mlo, mla, mde, catalogue, hspa, vspa)
    r, proj = spatial_index(smooth)
    #
    # magnitude-frequency distribution
    mfd = TruncatedGRMFD(min_mag=mmin,
                         max_mag=mmax,
                         bin_width=0.1,
                         a_val=agr,
                         b_val=bgr)
    #
    # create all the ruptures - the probability of occurrence is for one year
    # in this case
    # MN: 'Axes3D' assigned but never used
    allrup = create_ruptures(mfd, dips, sampling, msr, asprs, float_strike,
                             float_dip, r, values, ohs, 1., hdf5_filename,
                             uniform_fraction, proj, idl, align, True)
예제 #10
0
def create_ruptures(mfd,
                    dips,
                    sampling,
                    msr,
                    asprs,
                    float_strike,
                    float_dip,
                    r,
                    values,
                    oms,
                    tspan,
                    hdf5_filename,
                    uniform_fraction,
                    proj,
                    idl,
                    align=False,
                    inslab=False):
    """
    Create inslab ruptures using an MFD, a time span. The dictionary 'oms'
    contains lists of profiles for various values of dip. The ruptures are
    floated on each virtual fault created from a set of profiles.

    :param mfd:
        A magnitude frequency distribution
    :param dips:
        A set of dip values
    :param sampling:
        The distance in km used to
    :param msr:
        A magnitude scaling relationship instance
    :param asprs:
        A set of aspect ratios
    :param float_strike:
        Along strike floating parameter
    :param float_dip:
        Along dip floating parameter
    :param r:
        Spatial index
    :param values:
        Smothing results
    :param oms:
        A dictionary. Values of dip are used as keys while values of the
        dictionary are list of lists. Every list contains one or several
        :class:`openquake.hazardlib.geo.line.Line` instances each one
        corresponding to a 3D profile.
    :param tspan:
        Time span [in yr]
    :param hdf5_filename:
        Name of the hdf5 file where to store the ruptures
    :param uniform_fraction:
        Fraction of the overall rate for a given magnitude bin to be
        distributed uniformly to all the ruptures for the same mag bin.
    :param align:
        Profile alignment flag
    """
    #
    # hdf5 file
    fh5 = h5py.File(hdf5_filename, 'a')
    grp_inslab = fh5.create_group('inslab')
    #
    allrup = {}
    iscnt = 0
    for dip in dips:
        for mi, lines in enumerate(oms[dip]):
            #
            # filter out small surfaces i.e. surfaces defined by less than
            # three profiles
            if len(lines) < 3:
                continue
            #
            # checking initial profiles
            for l in lines:
                ps = np.array([[p.longitude, p.latitude, p.depth]
                               for p in l.points])
                assert not np.any(np.isnan(ps))
            #
            # create in-slab virtual fault - `lines` is the list of profiles
            # to be used for the construction of the virtual fault surface
            smsh = create_from_profiles(lines, sampling, sampling, idl, align)
            #
            # Create mesh
            omsh = Mesh(smsh[:, :, 0], smsh[:, :, 1], smsh[:, :, 2])
            #
            # Store data in the hdf5 file
            grp_inslab.create_dataset('{:09d}'.format(iscnt), data=smsh)
            #
            # get centroids for a given virtual fault surface
            ccc = get_centroids(smsh[:, :, 0], smsh[:, :, 1], smsh[:, :, 2])
            #
            # Get weights - this assigns to each cell centroid the weight of
            # the closest node in the values array
            weights = get_weights(ccc, r, values, proj)
            #
            # loop over magnitudes
            for mag, _ in mfd.get_annual_occurrence_rates():
                #
                # TODO this is assigns arbitrarly a rake of 90 degrees. It
                # should be a configuration parameter
                area = msr.get_median_area(mag=mag, rake=90)
                rups = []
                for aspr in asprs:
                    #
                    # IMPORTANT: the sampling here must be consistent with
                    # what we use for the construction of the mesh
                    lng, wdt = get_discrete_dimensions(area, sampling, aspr)
                    #
                    # If one of the dimensions is equal to 0 it means that
                    # this aspect ratio cannot be represented with the value of
                    # sampling
                    if (lng is None or wdt is None or lng < 1e-10
                            or wdt < 1e-10):
                        msg = 'Ruptures for magnitude {:.2f} and ar {:.2f}'
                        msg = msg.format(mag, aspr)
                        msg = '{:s} will not be defined'.format(msg)
                        logging.warning(msg)
                        continue
                    #
                    # rupture lenght and rupture width as multiples of the
                    # mesh sampling distance
                    rup_len = int(lng / sampling) + 1
                    rup_wid = int(wdt / sampling) + 1
                    #
                    # skipping small ruptures
                    if rup_len < 2 or rup_wid < 2:
                        msg = 'Found an incompatible discrete rupture size'
                        logging.warning(msg)
                        continue
                    #
                    # get_ruptures
                    counter = 0
                    for rup, rl, cl in get_ruptures(omsh,
                                                    rup_len,
                                                    rup_wid,
                                                    f_strike=float_strike,
                                                    f_dip=float_dip):
                        #
                        # getting weights from the smoothing
                        w = weights[cl:rup_len - 1, rl:rup_wid - 1]
                        i = np.isfinite(w)
                        #
                        # fix the longitudes outside the standard [-180, 180]
                        # range
                        ij = np.isfinite(rup[0])
                        iw = rup[0] > 180.
                        ik = np.logical_and(ij, iw)
                        rup[0][ik] -= 360
                        """
                        iw = np.nonzero(rup[0][ij] > 180.)
                        if len(iw):
                            print(type(rup), rup[0])
                            print(ij[iw])
                            rup[0][ij[iw]] -= 360.
                        """

                        #if np.any(rup[0][j] > 180):
                        #    rup[0][rup[0] > 180.] = rup[0][rup[0] > 180.] - 360.
                        assert np.all(rup[0][ij] <= 180)
                        assert np.all(rup[0][ij] >= -180)

                        rx = rup[0][ij].flatten()
                        ry = rup[1][ij].flatten()
                        rz = rup[2][ij].flatten()

                        #
                        # normalize the weight using the aspect ratio weight
                        wsum = sum(w[i]) / asprs[aspr]
                        #
                        # create the gridded surface. We need at least four
                        # vertexes
                        if len(rx) > 3:
                            #if rup[0].size > 3:
                            srfc = GriddedSurface(
                                Mesh.from_coords(zip(rx, ry, rz), sort=False))
                            #srfc = GriddedSurface(Mesh.from_coords(zip(rup[0],
                            #                                           rup[1],
                            #                                           rup[2]),
                            #                                       sort=False))
                            #
                            # update the list with the ruptures - the last
                            # element in the list is the container for the
                            # probability of occurrence. For the time being
                            # this is not defined
                            rups.append([srfc, wsum, dip, aspr, []])
                            counter += 1
                #
                # update the list of ruptures
                lab = '{:.2f}'.format(mag)
                if lab in allrup:
                    allrup[lab] += rups
                else:
                    allrup[lab] = rups
            #
            # update counter
            iscnt += 1
    #
    # closing the hdf5 file
    fh5.close()
    #
    # logging info
    for lab in sorted(allrup.keys()):
        tmps = 'Number of ruptures for m={:s}: {:d}'
        logging.info(tmps.format(lab, len(allrup[lab])))
    #
    # Compute the normalizing factor for every rupture. This is used only in
    # the case when smoothing is used a reference for distributing occurrence
    twei = {}
    for mag, occr in mfd.get_annual_occurrence_rates():
        smm = 0.
        lab = '{:.2f}'.format(mag)
        for _, wei, _, _, _ in allrup[lab]:
            if np.isfinite(wei):
                smm += wei
        twei[lab] = smm
        tmps = 'Total weight {:s}: {:f}'
        logging.info(tmps.format(lab, twei[lab]))
    #
    # generate and store the final set of ruptures
    fh5 = h5py.File(hdf5_filename, 'a')
    grp_rup = fh5.create_group('ruptures')
    #
    for mag, occr in mfd.get_annual_occurrence_rates():
        #
        # set label
        lab = '{:.2f}'.format(mag)
        #
        # warning
        if twei[lab] < 1e-50 and uniform_fraction < 0.99:
            tmps = 'Weight for magnitude {:s} equal to 0'
            tmps = tmps.format(lab)
            logging.warning(tmps)
        #
        #
        rups = []
        grp = grp_rup.create_group(lab)
        cnt = 0
        numrup = len(allrup[lab])
        for srfc, wei, _, _, _ in allrup[lab]:
            #
            # Adjust the weight. Every rupture will have a weight that is
            # a combination between a flat rate and a variable rate
            if twei[lab] > 1e-10:
                wei = wei / twei[lab]
                ocr = (wei * occr * (1. - uniform_fraction) +
                       occr / numrup * uniform_fraction)
            else:
                ocr = occr / numrup * uniform_fraction
            #
            # compute the probabilities
            p0 = np.exp(-ocr * tspan)
            p1 = 1. - p0
            #
            #
            rups.append([srfc, wei, dip, aspr, [p0, p1]])
            #
            #
            a = np.zeros(1,
                         dtype=[
                             ('lons', 'f4', srfc.mesh.lons.shape),
                             ('lats', 'f4', srfc.mesh.lons.shape),
                             ('deps', 'f4', srfc.mesh.lons.shape),
                             ('w', 'float32'),
                             ('dip', 'f4'),
                             ('aspr', 'f4'),
                             ('prbs', 'float32', (2)),
                         ])
            a['lons'] = srfc.mesh.lons
            a['lats'] = srfc.mesh.lats
            a['deps'] = srfc.mesh.depths
            a['w'] = wei
            a['dip'] = dip
            a['aspr'] = aspr
            a['prbs'] = np.array([p0, p1], dtype='float32')
            grp.create_dataset('{:08d}'.format(cnt), data=a)
            cnt += 1
        allrup[lab] = rups
    fh5.close()

    return allrup
예제 #11
0
def create_ruptures(mfd,
                    dips,
                    sampling,
                    msr,
                    asprs,
                    float_strike,
                    float_dip,
                    r,
                    values,
                    oms,
                    tspan,
                    hdf5_filename,
                    uniform_fraction,
                    proj,
                    idl,
                    align=False,
                    inslab=False):
    """
    Create inslab ruptures using an MFD, a time span. The dictionary 'oms'
    contains lists of profiles for various values of dip. The ruptures are
    floated on each virtual fault created from a set of profiles.

    :param mfd:
        A magnitude frequency distribution
    :param dips:
        A set of dip values used to create the virtual faults withni the slab.
    :param sampling:
        The distance in km used to sample the profiles
    :param msr:
        A magnitude scaling relationship instance
    :param asprs:
        A dictionary of aspect ratios (key: aspect ratio, value: weight)
    :param float_strike:
        Along strike rupture floating parameter
    :param float_dip:
        Along dip rupture floating parameter
    :param r:
        Spatial index for the nodes of the grid over which we smoothed
        seismicity
    :param values:
        Smothing results
    :param oms:
        A dictionary. Values of dip are used as keys while values of the
        dictionary are list of lists. Every list contains one or several
        :class:`openquake.hazardlib.geo.line.Line` instances each one
        corresponding to a 3D profile.
    :param tspan:
        Time span [in yr]
    :param hdf5_filename:
        Name of the hdf5 file where to store the ruptures
    :param uniform_fraction:
        Fraction of the overall rate for a given magnitude bin to be
        distributed uniformly to all the ruptures for the same mag bin.
    :param align:
        Profile alignment flag
    """

    # Create the output hdf5 file
    fh5 = h5py.File(hdf5_filename, 'a')
    grp_inslab = fh5.create_group('inslab')

    # Loop over dip angles, top traces on the top the slab surface and
    # magnitudes. The traces are used to create the virtual faults and
    # float the ruptures.
    allrup = {}
    iscnt = 0
    trup = 0
    for dip in dips:
        for mi, lines in enumerate(oms[dip]):

            print('\nVirtual fault {:d} dip {:.2f}\n'.format(mi, dip))

            # Filter out small surfaces i.e. surfaces defined by less than
            # three profiles
            if len(lines) < 3:
                continue

            # Checking initial profiles
            for lne in lines:
                ps = np.array([[p.longitude, p.latitude, p.depth]
                               for p in lne.points])
                assert not np.any(np.isnan(ps))

            # Create in-slab virtual fault - `lines` is the list of profiles
            # to be used for the construction of the virtual fault surface
            smsh = create_from_profiles(lines, sampling, sampling, idl, align)

            # Create mesh
            omsh = Mesh(smsh[:, :, 0], smsh[:, :, 1], smsh[:, :, 2])

            # Store data in the hdf5 file
            grp_inslab.create_dataset('{:09d}'.format(iscnt), data=smsh)

            # Get centroids for a given virtual fault surface
            ccc = get_centroids(smsh[:, :, 0], smsh[:, :, 1], smsh[:, :, 2])

            # Get weights - this assigns to each centroid the weight of
            # the closest node in the values array
            weights = get_weights(ccc, r, values, proj)

            # Loop over magnitudes
            for mag, _ in mfd.get_annual_occurrence_rates():

                # TODO this is assigns arbitrarly a rake of 90 degrees. It
                # should be a configuration parameter
                area = msr.get_median_area(mag=mag, rake=90)
                rups = []
                for aspr in asprs:

                    # IMPORTANT: the sampling here must be consistent with
                    # what we use for the construction of the mesh
                    lng, wdt = get_discrete_dimensions(area, sampling, aspr)

                    # If one of the dimensions is equal to 0 it means that
                    # this aspect ratio cannot be represented with the value of
                    # sampling
                    if (lng is None or wdt is None or lng < 1e-10
                            or wdt < 1e-10):
                        msg = 'Ruptures for magnitude {:.2f} and ar {:.2f}'
                        msg = msg.format(mag, aspr)
                        msg = ' {:s} will not be defined'.format(msg)
                        logging.warning(msg)
                        continue

                    # Rupture lenght and rupture width as multiples of the
                    # mesh sampling distance
                    rup_len = int(lng / sampling) + 1
                    rup_wid = int(wdt / sampling) + 1

                    # Skip small ruptures
                    if rup_len < 2 or rup_wid < 2:
                        msg = 'Found a small rupture size'
                        logging.warning(msg)
                        continue

                    # Get Ruptures
                    counter = 0
                    for rup, rl, cl in get_ruptures(omsh,
                                                    rup_len,
                                                    rup_wid,
                                                    f_strike=float_strike,
                                                    f_dip=float_dip):

                        # Get weights
                        wsum = asprs[aspr]
                        wsum_smoo = np.nan
                        if uniform_fraction < 0.99:
                            w = weights[rl:rl + rup_wid - 1,
                                        cl:cl + rup_len - 1]
                            i = np.isfinite(w)
                            tmpw = sum(w[i])
                            wsum_smoo = tmpw * asprs[aspr]

                        # Fix the longitudes outside the standard [-180, 180]
                        # range
                        ij = np.isfinite(rup[0])
                        iw = rup[0] > 180.
                        ik = np.logical_and(ij, iw)
                        rup[0][ik] -= 360

                        # Get centroid
                        idx_r = np.floor(rup[0].shape[0] / 2).astype('i4')
                        idx_c = np.floor(rup[0].shape[1] / 2).astype('i4')
                        hypo = [
                            rup[0][idx_r, idx_c], rup[1][idx_r, idx_c],
                            rup[2][idx_r, idx_c]
                        ]

                        # Checking
                        assert np.all(rup[0][ij] <= 180)
                        assert np.all(rup[0][ij] >= -180)

                        # Get coordinates of the rupture surface
                        rx = rup[0][ij].flatten()
                        ry = rup[1][ij].flatten()
                        rz = rup[2][ij].flatten()

                        # Create the gridded surface. We need at least four
                        # vertexes
                        if len(rx) > 3:
                            srfc = GriddedSurface(
                                Mesh.from_coords(zip(rx, ry, rz), sort=False))
                            # Update the list with the ruptures - the last
                            # element in the list is the container for the
                            # probability of occurrence. For the time being
                            # this is not defined
                            rups.append(
                                [srfc, wsum, wsum_smoo, dip, aspr, [], hypo])
                            counter += 1
                            trup += 1

                # Update the list of ruptures
                lab = '{:.2f}'.format(mag)
                if lab in allrup:
                    allrup[lab] += rups
                else:
                    allrup[lab] = rups

            # Update counter
            iscnt += 1

    # Closing the hdf5 file
    fh5.close()

    # Logging info
    for lab in sorted(allrup.keys()):
        tmps = 'Number of ruptures for m={:s}: {:d}'
        logging.info(tmps.format(lab, len(allrup[lab])))

    # Compute the normalizing factor
    twei = {}
    tweis = {}
    for mag, occr in mfd.get_annual_occurrence_rates():
        smm = 0.
        smms = 0.
        lab = '{:.2f}'.format(mag)
        for _, wei, weis, _, _, _, _ in allrup[lab]:
            if np.isfinite(wei):
                smm += wei
            if np.isfinite(weis):
                smms += weis
        twei[lab] = smm
        tweis[lab] = smms
        tmps = 'Total weight {:s}: {:f}'
        logging.info(tmps.format(lab, twei[lab]))

    # Generate and store the final set of ruptures
    fh5 = h5py.File(hdf5_filename, 'a')
    grp_rup = fh5.create_group('ruptures')

    # Assign probability of occurrence
    for mag, occr in mfd.get_annual_occurrence_rates():

        # Create the label
        lab = '{:.2f}'.format(mag)

        # Check if weight is larger than 0
        if twei[lab] < 1e-50 and uniform_fraction < 0.99:
            tmps = 'Weight for magnitude {:s} equal to 0'
            tmps = tmps.format(lab)
            logging.warning(tmps)

        rups = []
        grp = grp_rup.create_group(lab)

        # Loop over the ruptures and compute the annual pocc
        cnt = 0
        chk = 0
        chks = 0
        for srfc, wei, weis, _, _, _, hypo in allrup[lab]:

            # Adjust the weight. Every rupture will have a weight that is
            # a combination between a flat rate and a spatially variable rate
            wei = wei / twei[lab]
            ocr = (occr * uniform_fraction) * wei
            chk += wei
            if uniform_fraction < 0.99:
                weis = weis / tweis[lab]
                ocr += (occr * (1. - uniform_fraction)) * weis
                chks += weis

            # Compute the probabilities
            p0 = np.exp(-ocr * tspan)
            p1 = 1. - p0

            # Append ruptures
            rups.append([srfc, [wei, weis], dip, aspr, [p0, p1]])

            # Preparing the data structure for storing information
            a = np.zeros(1,
                         dtype=[
                             ('lons', 'f4', srfc.mesh.lons.shape),
                             ('lats', 'f4', srfc.mesh.lons.shape),
                             ('deps', 'f4', srfc.mesh.lons.shape),
                             ('w', 'float32', (2)),
                             ('dip', 'f4'),
                             ('aspr', 'f4'),
                             ('prbs', 'float32', (2)),
                             ('hypo', 'float32', (3)),
                         ])

            a['lons'] = srfc.mesh.lons
            a['lats'] = srfc.mesh.lats
            a['deps'] = srfc.mesh.depths
            a['w'] = [wei, weis]
            a['dip'] = dip
            a['aspr'] = aspr
            a['prbs'] = np.array([p0, p1], dtype='float32')
            a['hypo'] = hypo
            grp.create_dataset('{:08d}'.format(cnt), data=a)
            cnt += 1

        allrup[lab] = rups

        if len(rups):
            if uniform_fraction < 0.99:
                fmt = 'Sum of weights for smoothing: '
                fmt = '{:.5f}. Should be close to 1'
                msg = fmt.format(chks)
                assert (1.0 - chks) < 1e-5, msg

            if uniform_fraction > 0.01:
                fmt = 'Sum of weights for uniform: '
                fmt = '{:.5f}. Should be close to 1'
                msg = fmt.format(chk)
                assert (1.0 - chk) < 1e-5, msg

    fh5.close()

    return allrup