示例#1
0
    def perform(self, node, inputs, output):
        """
        Perform method of the Operator to calculate synthetic displacements.

        Parameters
        ----------
        inputs : list
            of :class:`numpy.ndarray`
        output : list
            1) of synthetic waveforms of :class:`numpy.ndarray`
               (n x nsamples)
            2) of start times of the first waveform samples
               :class:`numpy.ndarray` (n x 1)
        """
        synths = output[0]

        point = {vname: i for vname, i in zip(self.varnames, inputs)}

        mpoint = utility.adjust_point_units(point)

        source_points = utility.split_point(mpoint)

        for i, source in enumerate(self.sources):
            utility.update_source(source, **source_points[i])
            # reset source time may result in store error otherwise
            source.time = 0.

        synths[0] = heart.geo_synthetics(
            engine=self.engine,
            targets=self.targets,
            sources=self.sources,
            outmode='stacked_array')
示例#2
0
    def perform(self, node, inputs, output):
        """
        Perform method of the Operator to calculate synthetic displacements.

        Parameters
        ----------
        inputs : list
            of :class:`numpy.ndarray`
        output : list
            of synthetic displacements of :class:`numpy.ndarray` (n x 1)
        """
        z = output[0]

        point = {vname: i for vname, i in zip(self.varnames, inputs)}

        point = utility.adjust_point_units(point)

        source_points = utility.split_point(point)

        for i, source in enumerate(self.sources):
            source.update(**source_points[i])

        z[0] = heart.geo_layer_synthetics_pscmp(
            store_superdir=self.store_superdir,
            crust_ind=self.crust_ind,
            lons=self.lons,
            lats=self.lats,
            sources=self.sources)
示例#3
0
    def perform(self, node, inputs, output):
        """
        Perform method of the Operator to calculate synthetic displacements.

        Parameters
        ----------
        inputs : list
            of :class:`numpy.ndarray`
        output : list
            of synthetic displacements of :class:`numpy.ndarray` (n x 3)
        """
        z = output[0]

        point = {vname: i for vname, i in zip(self.varnames, inputs)}
        point.update(self.fixed_values)

        point = utility.adjust_point_units(point)
        spoint, bpoint = interseismic.seperate_point(point)

        source_points = utility.split_point(spoint)

        for i, source_point in enumerate(source_points):
            self.sources[i].update(**source_point)

        z[0] = interseismic.geo_backslip_synthetics(
            engine=self.engine,
            targets=self.targets,
            sources=self.sources,
            lons=num.array(self.lons),
            lats=num.array(self.lats),
            reference=self.reference,
            **bpoint)

        def infer_shape(self, node, input_shapes):
            return [(len(self.lats), 3)]
示例#4
0
    def perform(self, node, inputs, output):
        """
        Perform method of the Operator to calculate synthetic displacements.

        Parameters
        ----------
        inputs : list
            of :class:`numpy.ndarray`
        output : list
            1) of synthetic waveforms of :class:`numpy.ndarray`
               (n x nsamples)
            2) of start times of the first waveform samples
               :class:`numpy.ndarray` (n x 1)
        """
        synths = output[0]
        tmins = output[1]

        point = {vname: i for vname, i in zip(self.varnames, inputs)}

        mpoint = utility.adjust_point_units(point)

        source_points = utility.split_point(mpoint)

        for i, source in enumerate(self.sources):
            utility.update_source(source, **source_points[i])
            source.time += self.event.time

        synths[0], tmins[0] = heart.seis_synthetics(
            engine=self.engine,
            sources=self.sources,
            targets=self.targets,
            arrival_taper=self.arrival_taper,
            wavename=self.wavename,
            filterer=self.filterer,
            pre_stack_cut=self.pre_stack_cut)
示例#5
0
    def point2sources(self, point):
        """
        Updates the composite source(s) (in place) with the point values.
        """
        tpoint = copy.deepcopy(point)
        tpoint = utility.adjust_point_units(tpoint)

        # remove hyperparameters from point
        hps = self.config.get_hypernames()

        for hyper in hps:
            if hyper in tpoint:
                tpoint.pop(hyper)

        source_params = self.sources[0].keys()

        for param in tpoint.keys():
            if param not in source_params:
                tpoint.pop(param)

        source_points = utility.split_point(tpoint)

        for i, source in enumerate(self.sources):
            utility.update_source(source, **source_points[i])
            # reset source time may result in store error otherwise
            source.time = 0.
示例#6
0
文件: seismic.py 项目: braunfuss/beat
    def point2sources(self, point):
        """
        Updates the composite source(s) (in place) with the point values.
        """
        tpoint = copy.deepcopy(point)
        tpoint = utility.adjust_point_units(tpoint)

        # remove hyperparameters from point
        hps = self.config.get_hypernames()

        for hyper in hps:
            if hyper in tpoint:
                tpoint.pop(hyper)

        source = self.sources[0]
        source_params = source.keys() + source.stf.keys()

        for param in tpoint.keys():
            if param not in source_params:
                tpoint.pop(param)

        tpoint['time'] += self.event.time

        source_points = utility.split_point(tpoint)

        for i, source in enumerate(self.sources):
            utility.update_source(source, **source_points[i])
示例#7
0
    def perform(self, node, inputs, output):

        z = output[0]

        lons = inputs.pop(0)
        lats = inputs.pop(0)

        point = {var: inp for var, inp in zip(config.geo_vars_magma, inputs)}

        point = utility.adjust_point_units(point)

        source_points = utility.split_point(point)

        for i, source in enumerate(self.sources):
            source.update(**source_points[i])
            heart.adjust_fault_reference(source, input_depth='top')

        z[0] = heart.geo_layer_synthetics(self.store_superdir, self.crust_ind,
                                          lons, lats, self.sources)
示例#8
0
    def perform(self, node, inputs, output):

        synths = output[0]
        tmins = output[1]

        point = {
            var: inp
            for var, inp in zip(config.joint_vars_geometry, inputs)
        }

        mpoint = utility.adjust_point_units(point)

        source_points = utility.split_point(mpoint)

        for i, source in enumerate(self.sources):
            utility.update_source(source, **source_points[i])
            source.time += self.event.time
            heart.adjust_fault_reference(source, input_depth='top')

        synths[0], tmins[0] = heart.seis_synthetics(self.engine, self.sources,
                                                    self.targets,
                                                    self.arrival_taper,
                                                    self.filterer)
示例#9
0
    def point2sources(self, point):
        """
        Updates the composite source(s) (in place) with the point values.

        Parameters
        ----------
        point : dict
            with random variables from solution space
        """
        tpoint = copy.deepcopy(point)
        tpoint = utility.adjust_point_units(tpoint)

        # remove hyperparameters from point
        hps = self.config.get_hypernames()

        for hyper in hps:
            if hyper in tpoint:
                tpoint.pop(hyper)

        source = self.sources[0]
        source_params = list(source.keys()) + list(source.stf.keys())

        for param in list(tpoint.keys()):
            if param not in source_params:
                tpoint.pop(param)

        # update source times
        if self.nevents == 1:
            tpoint['time'] += self.event.time  # single event
        else:
            for i, event in enumerate(self.events):  # multi event
                tpoint['time'][i] += event.time

        source_points = utility.split_point(tpoint)

        for i, source in enumerate(self.sources):
            utility.update_source(source, **source_points[i])
示例#10
0
    def point2sources(self, point, input_depth='top'):
        """
        Updates the composite source(s) (in place) with the point values.

        Parameters
        ----------
        point : dict
            with random variables from solution space
        input_depth : string
            may be either 'top'- input coordinates are transformed to center
            'center' - input coordinates are not transformed
        """
        tpoint = copy.deepcopy(point)
        tpoint = utility.adjust_point_units(tpoint)

        # remove hyperparameters from point
        hps = self.config.get_hypernames()

        for hyper in hps:
            if hyper in tpoint:
                tpoint.pop(hyper)

        source = self.sources[0]
        source_params = list(source.keys()) + list(source.stf.keys())

        for param in list(tpoint.keys()):
            if param not in source_params:
                tpoint.pop(param)

        tpoint['time'] += self.event.time

        source_points = utility.split_point(tpoint)

        for i, source in enumerate(self.sources):
            utility.update_source(source,
                                  input_depth=input_depth,
                                  **source_points[i])
示例#11
0
def init_config(name,
                date=None,
                min_magnitude=6.0,
                main_path='./',
                datatypes=['geodetic'],
                mode='geometry',
                source_type='RectangularSource',
                n_sources=1,
                waveforms=['any_P'],
                sampler='SMC',
                hyper_sampler='Metropolis',
                use_custom=False,
                individual_gfs=False):
    """
    Initialise BEATconfig File and write it main_path/name .
    Fine parameters have to be edited in the config file .yaml manually.

    Parameters
    ----------
    name : str
        Name of the event
    date : str
        'YYYY-MM-DD', date of the event
    min_magnitude : scalar, float
        approximate minimum Mw of the event
    datatypes : List of strings
        data sets to include in the optimization: either 'geodetic' and/or
        'seismic'
    mode : str
        type of optimization problem: 'Geometry' / 'Static'/ 'Kinematic'
    n_sources : int
        number of sources to solve for / discretize depending on mode parameter
    waveforms : list
        of strings of waveforms to include into the misfit function and
        GF calculation
    sampler : str
        Optimization algorithm to use to sample the solution space
        Options: 'SMC', 'Metropolis'
    use_custom : boolean
        Flag to setup manually a custom velocity model.
    individual_gfs : boolean
        Flag to use individual Green's Functions for each specific station.
        If false a reference location will be initialised in the config file.
        If true the reference locations will be taken from the imported station
        objects.

    Returns
    -------
    :class:`BEATconfig`
    """

    c = BEATconfig(name=name, date=date)
    c.project_dir = os.path.join(os.path.abspath(main_path), name)

    if mode == 'geometry' or mode == 'interseismic':
        if date is not None and not mode == 'interseismic':
            c.event = utility.search_catalog(date=date,
                                             min_magnitude=min_magnitude)

        elif mode == 'interseismic':
            c.event = model.Event(lat=10., lon=10., depth=0.)
            c.date = 'dummy'
            logger.info('Interseismic mode! Using event as reference for the'
                        ' stable block! Please update coordinates!')
        else:
            logger.warn('No given date! Using dummy event!'
                        ' Updating reference coordinates (spatial & temporal)'
                        ' necessary!')
            c.event = model.Event(duration=1.)
            c.date = 'dummy'

        if 'geodetic' in datatypes:
            c.geodetic_config = GeodeticConfig()
            if use_custom:
                logger.info('use_custom flag set! The velocity model in the'
                            ' geodetic GF configuration has to be updated!')
                c.geodetic_config.gf_config.custom_velocity_model = \
                    load_model().extract(depth_max=100. * km)
                c.geodetic_config.gf_config.use_crust2 = False
                c.geodetic_config.gf_config.replace_water = False
        else:
            c.geodetic_config = None

        if 'seismic' in datatypes:
            c.seismic_config = SeismicConfig()
            c.seismic_config.init_waveforms(waveforms)

            if not individual_gfs:
                c.seismic_config.gf_config.reference_location = \
                    ReferenceLocation(lat=10.0, lon=10.0)
            else:
                c.seismic_config.gf_config.reference_location = None

            if use_custom:
                logger.info('use_custom flag set! The velocity model in the'
                            ' seismic GF configuration has to be updated!')
                c.seismic_config.gf_config.custom_velocity_model = \
                    load_model().extract(depth_max=100. * km)
                c.seismic_config.gf_config.use_crust2 = False
                c.seismic_config.gf_config.replace_water = False
        else:
            c.seismic_config = None

    elif mode == 'ffi':

        if source_type != 'RectangularSource':
            raise TypeError('Static distributed slip is so far only supported'
                            ' for RectangularSource(s)')

        gmc = load_config(c.project_dir, 'geometry')

        if gmc is not None:
            logger.info('Taking information from geometry_config ...')
            if source_type != gmc.problem_config.source_type:
                raise ValueError(
                    'Specified reference source: "%s" differs from the'
                    ' source that has been used previously in'
                    ' "geometry" mode: "%s"!' %
                    (source_type, gmc.problem_config.source_type))

            n_sources = gmc.problem_config.n_sources
            point = {
                k: v.testvalue
                for k, v in gmc.problem_config.priors.iteritems()
            }
            point = utility.adjust_point_units(point)
            source_points = utility.split_point(point)

            reference_sources = init_reference_sources(
                source_points, n_sources, gmc.problem_config.source_type,
                gmc.problem_config.stf_type)

            c.date = gmc.date
            c.event = gmc.event

            if 'geodetic' in datatypes:
                gc = gmc.geodetic_config
                if gc is None:
                    logger.warning(
                        'Asked for "geodetic" datatype but geometry config '
                        'has no such datatype! Initialising default "geodetic"'
                        ' linear config!')
                    gc = GeodeticConfig()
                    lgf_config = GeodeticLinearGFConfig()
                else:
                    lgf_config = GeodeticLinearGFConfig(
                        earth_model_name=gc.gf_config.earth_model_name,
                        store_superdir=gc.gf_config.store_superdir,
                        n_variations=gc.gf_config.n_variations,
                        reference_sources=reference_sources,
                        sample_rate=gc.gf_config.sample_rate)

                c.geodetic_config = gc
                c.geodetic_config.gf_config = lgf_config

            elif 'seismic' in datatypes:
                sc = gmc.seismic_config
                if sc is None:
                    logger.warning(
                        'Asked for "seismic" datatype but geometry config '
                        'has no such datatype! Initialising default "seismic"'
                        ' linear config!')
                    sc = SeismicConfig()
                    lgf_config = SeismicLinearGFConfig()
                else:
                    lgf_config = SeismicLinearGFConfig(
                        earth_model_name=sc.gf_config.earth_model_name,
                        sample_rate=sc.gf_config.sample_rate,
                        reference_location=sc.gf_config.reference_location,
                        store_superdir=sc.gf_config.store_superdir,
                        n_variations=sc.gf_config.n_variations,
                        reference_sources=reference_sources)
                c.seismic_config = sc
                c.seismic_config.gf_config = lgf_config
        else:
            logger.warning('Found no geometry setup, ...')
            raise ImportError(
                'No geometry configuration file existing! Please initialise'
                ' a "geometry" configuration ("beat init command"), update'
                ' the Greens Function information and create GreensFunction'
                ' stores for the non-linear problem.')

    c.problem_config = ProblemConfig(n_sources=n_sources,
                                     datatypes=datatypes,
                                     mode=mode,
                                     source_type=source_type)
    c.problem_config.init_vars()
    c.problem_config.set_decimation_factor()

    c.sampler_config = SamplerConfig(name=sampler)
    c.sampler_config.set_parameters(update_covariances=False)

    c.hyper_sampler_config = SamplerConfig(name=hyper_sampler)
    c.hyper_sampler_config.set_parameters(update_covariances=None)

    c.update_hypers()
    c.problem_config.validate_priors()

    c.regularize()
    c.validate()

    logger.info('Project_directory: %s \n' % c.project_dir)
    util.ensuredir(c.project_dir)

    dump_config(c)
    return c
示例#12
0
def init_config(name,
                date=None,
                min_magnitude=6.0,
                main_path='./',
                datatypes=['geodetic'],
                mode='geometry',
                source_type='RectangularSource',
                n_sources=1,
                waveforms=['any_P'],
                sampler='SMC',
                hyper_sampler='Metropolis',
                use_custom=False,
                individual_gfs=False):
    """
    Initialise BEATconfig File and write it main_path/name .
    Fine parameters have to be edited in the config file .yaml manually.

    Parameters
    ----------
    name : str
        Name of the event
    date : str
        'YYYY-MM-DD', date of the event
    min_magnitude : scalar, float
        approximate minimum Mw of the event
    datatypes : List of strings
        data sets to include in the optimization: either 'geodetic' and/or
        'seismic'
    mode : str
        type of optimization problem: 'Geometry' / 'Static'/ 'Kinematic'
    n_sources : int
        number of sources to solve for / discretize depending on mode parameter
    waveforms : list
        of strings of waveforms to include into the misfit function and
        GF calculation
    sampler : str
        Optimization algorithm to use to sample the solution space
        Options: 'SMC', 'Metropolis'
    use_custom : boolean
        Flag to setup manually a custom velocity model.
    individual_gfs : boolean
        Flag to use individual Green's Functions for each specific station.
        If false a reference location will be initialised in the config file.
        If true the reference locations will be taken from the imported station
        objects.

    Returns
    -------
    :class:`BEATconfig`
    """

    c = BEATconfig(name=name, date=date)
    c.project_dir = os.path.join(os.path.abspath(main_path), name)

    if mode == 'geometry' or mode == 'interseismic':
        if date is not None and not mode == 'interseismic':
            c.event = utility.search_catalog(date=date,
                                             min_magnitude=min_magnitude)

        elif mode == 'interseismic':
            c.event = model.Event(lat=10., lon=10., depth=0.)
            c.date = 'dummy'
            logger.info('Interseismic mode! Using event as reference for the'
                        ' stable block! Please update coordinates!')
        else:
            logger.warn('No given date! Using dummy event!'
                        ' Updating reference coordinates (spatial & temporal)'
                        ' necessary!')
            c.event = model.Event(duration=1.)
            c.date = 'dummy'

        if 'geodetic' in datatypes:
            c.geodetic_config = GeodeticConfig()
            if use_custom:
                logger.info('use_custom flag set! The velocity model in the'
                            ' geodetic GF configuration has to be updated!')
                c.geodetic_config.gf_config.custom_velocity_model = \
                    load_model().extract(depth_max=100. * km)
                c.geodetic_config.gf_config.use_crust2 = False
                c.geodetic_config.gf_config.replace_water = False
        else:
            c.geodetic_config = None

        if 'seismic' in datatypes:
            c.seismic_config = SeismicConfig()
            c.seismic_config.init_waveforms(waveforms)

            if not individual_gfs:
                c.seismic_config.gf_config.reference_location = \
                    ReferenceLocation(lat=10.0, lon=10.0)
            else:
                c.seismic_config.gf_config.reference_location = None

            if use_custom:
                logger.info('use_custom flag set! The velocity model in the'
                            ' seismic GF configuration has to be updated!')
                c.seismic_config.gf_config.custom_velocity_model = \
                    load_model().extract(depth_max=100. * km)
                c.seismic_config.gf_config.use_crust2 = False
                c.seismic_config.gf_config.replace_water = False
        else:
            c.seismic_config = None

    elif mode == 'static':

        if source_type != 'RectangularSource':
            raise TypeError('Static distributed slip is so far only supported'
                            ' for RectangularSource(s)')

        gc = load_config(c.project_dir, 'geometry')

        if gc is not None:
            logger.info('Taking information from geometry_config ...')
            n_sources = gc.problem_config.n_sources
            point = {
                k: v.testvalue
                for k, v in gc.problem_config.priors.iteritems()
            }
            source_points = utility.split_point(point)
            reference_sources = [
                RectangularSource(**source_points[i]) for i in range(n_sources)
            ]

            c.date = gc.date
            c.event = gc.event
            c.geodetic_config = gc.geodetic_config
            c.geodetic_config.gf_config = LinearGFConfig(
                store_superdir=gc.geodetic_config.gf_config.store_superdir,
                n_variations=gc.geodetic_config.gf_config.n_variations,
                reference_sources=reference_sources)
        else:
            logger.info('Found no geometry setup, init blank ...')
            c.geodetic_config = GeodeticConfig(gf_config=LinearGFConfig())
            c.date = 'dummy'
        logger.info(
            'Problem config has to be updated. After deciding on the patch'
            ' dimensions and extension factors please run: import')

    c.problem_config = ProblemConfig(n_sources=n_sources,
                                     datatypes=datatypes,
                                     mode=mode,
                                     source_type=source_type)
    c.problem_config.init_vars()
    c.problem_config.set_decimation_factor()

    c.sampler_config = SamplerConfig(name=sampler)
    c.sampler_config.set_parameters(update_covariances=False)

    c.hyper_sampler_config = SamplerConfig(name=hyper_sampler)
    c.hyper_sampler_config.set_parameters(update_covariances=None)

    c.update_hypers()
    c.problem_config.validate_priors()

    c.regularize()
    c.validate()

    logger.info('Project_directory: %s \n' % c.project_dir)
    util.ensuredir(c.project_dir)

    dump_config(c)
    return c
示例#13
0
文件: models.py 项目: xiaolongma/beat
    def get_synthetics(self, point, **kwargs):
        """
        Get synthetics for given point in solution space.

        Parameters
        ----------
        point : :func:`pymc3.Point`
            Dictionary with model parameters
        kwargs especially to change output of seismic forward model
            outmode = 'traces'/ 'array' / 'data'

        Returns
        -------
        Dictionary with keys according to datasets containing the synthetics
        as lists.
        """
        tpoint = copy.deepcopy(point)

        tpoint = utility.adjust_point_units(tpoint)

        # remove hyperparameters from point
        hps = self.config.problem_config.hyperparameters

        if len(hps) > 0:
            for hyper in hps.keys():
                if hyper in tpoint:
                    tpoint.pop(hyper)
                else:
                    pass

        d = dict()

        if self._seismic_flag:
            tpoint['time'] += self.event.time

        source_points = utility.split_point(tpoint)

        for i, source in enumerate(self.sources):
            utility.update_source(source, **source_points[i])

        dsources = utility.transform_sources(
            self.sources, self.config.problem_config.datasets)

        # seismic
        if self._seismic_flag:
            sc = self.config.seismic_config
            seis_synths, _ = heart.seis_synthetics(
                engine=self.engine,
                sources=dsources['seismic'],
                targets=self.stargets,
                arrival_taper=sc.arrival_taper,
                filterer=sc.filterer, **kwargs)

            d['seismic'] = seis_synths

        # geodetic
        if self._geodetic_flag:
            gc = self.config.geodetic_config

            crust_inds = [0]

            geo_synths = []
            for crust_ind in crust_inds:
                for gtarget in self.gtargets:
                    disp = heart.geo_layer_synthetics(
                        gc.gf_config.store_superdir,
                        crust_ind,
                        lons=gtarget.lons,
                        lats=gtarget.lats,
                        sources=dsources['geodetic'])
                    geo_synths.append((
                        disp[:, 0] * gtarget.los_vector[:, 0] + \
                        disp[:, 1] * gtarget.los_vector[:, 1] + \
                        disp[:, 2] * gtarget.los_vector[:, 2]))

            d['geodetic'] = geo_synths

        return d
示例#14
0
文件: models.py 项目: xiaolongma/beat
    def update_weights(self, point, n_jobs=1, plot=False):
        """
        Calculate and update model prediction uncertainty covariances
        due to uncertainty in the velocity model with respect to one point
        in the solution space. Shared variables are updated.

        Parameters
        ----------
        point : :func:`pymc3.Point`
            Dictionary with model parameters, for which the covariance matrixes
            with respect to velocity model uncertainties are calculated
        n_jobs : int
            Number of processors to use for calculation of seismic covariances
        plot : boolean
            Flag for opening the seismic waveforms in the snuffler
        """
        tpoint = copy.deepcopy(point)

        # update sources
        tpoint = utility.adjust_point_units(tpoint)

        # remove hyperparameters from point
        hps = self.config.problem_config.hyperparameters

        if len(hps) > 0:
            for hyper in hps.keys():
                tpoint.pop(hyper)

        if self._seismic_flag:
            tpoint['time'] += self.event.time

        source_points = utility.split_point(tpoint)

        for i, source in enumerate(self.sources):
            utility.update_source(source, **source_points[i])

        dsources = utility.transform_sources(
            self.sources, self.config.problem_config.datasets)

        # seismic
        if self._seismic_flag:
            sc = self.config.seismic_config

            for j, channel in enumerate(sc.channels):
                for i, station in enumerate(self.stations):
                    logger.debug('Channel %s of Station %s ' % (
                        channel, station.station))
                    crust_targets = heart.init_targets(
                        stations=[station],
                        channels=channel,
                        sample_rate=sc.gf_config.sample_rate,
                        crust_inds=range(sc.gf_config.n_variations))

                    cov_pv = cov.get_seis_cov_velocity_models(
                        engine=self.engine,
                        sources=dsources['seismic'],
                        targets=crust_targets,
                        arrival_taper=sc.arrival_taper,
                        filterer=sc.filterer,
                        plot=plot, n_jobs=n_jobs)

                    cov_pv = utility.ensure_cov_psd(cov_pv)

                    self.engine.close_cashed_stores()

                    index = j * len(self.stations) + i

                    self.stargets[index].covariance.pred_v = cov_pv
                    icov = self.stargets[index].covariance.inverse
                    self.sweights[index].set_value(icov)

        # geodetic
        if self._geodetic_flag:
            gc = self.config.geodetic_config

            for i, gtarget in enumerate(self.gtargets):
                logger.debug('Track %s' % gtarget.track)
                cov_pv = cov.get_geo_cov_velocity_models(
                    store_superdir=gc.gf_config.store_superdir,
                    crust_inds=range(gc.gf_config.n_variations),
                    dataset=gtarget,
                    sources=dsources['geodetic'])

                cov_pv = utility.ensure_cov_psd(cov_pv)

                gtarget.covariance.pred_v = cov_pv
                icov = gtarget.covariance.inverse
                self.gweights[i].set_value(icov)