def read_info(path): try: info = guts.load(filename=path) except OSError: raise GrondError('Cannot read Grond run info file: %s' % path) if not isinstance(info, RunInfo): raise GrondError('Invalid Grond run info in file "%s".' % path) return info
def read_config(path): try: config = guts.load(filename=path) except OSError: raise GrondError( 'cannot read Grond clustering configuration file: %s' % path) if not isinstance(config, Clustering): raise GrondError( 'invalid Grond clustering configuration in file "%s"' % path) return config
def read_config(path): try: config = guts.load(filename=path) except OSError: raise GrondError('cannot read Grond report configuration file: %s' % path) if not isinstance(config, ReportConfig): raise GrondError('invalid Grond report configuration in file "%s"' % path) config.set_basepath(op.dirname(path) or '.') return config
def load_misfit_result_collection(path): try: obj = load(filename=path) except OSError as e: raise GrondError( 'Failed to read ensemble misfit results from file "%s" (%s)' % (path, e)) if not isinstance(obj, MisfitResultCollection): raise GrondError( 'File "%s" does not contain any misfit result collection.' % path) return obj
def read_config(path): get_all_plot_classes() # make sure all plot modules are imported try: config = guts.load(filename=path) except OSError: raise GrondError('Cannot read Grond report configuration file: %s' % path) if not isinstance(config, ReportConfig): raise GrondError('Invalid Grond report configuration in file "%s".' % path) config.set_basepath(op.dirname(path) or '.') return config
def load(cls, path): collection = load(filename=path) if not isinstance(collection, PlotConfigCollection): raise GrondError( 'invalid plot collection configuration in file "%s"' % path) return collection
def write_info(info, path): try: guts.dump(info, filename=path, header='Grond run info file, version %s' % __version__) except OSError: raise GrondError('Cannot write Grond run info file: %s' % path)
def load(cls, path): from grond.plot import get_all_plot_classes get_all_plot_classes() # make sure all plot classes are loaded collection = load(filename=path) if not isinstance(collection, PlotConfigCollection): raise GrondError( 'invalid plot collection configuration in file "%s"' % path) return collection
def random_uniform(self, xbounds, rstate, fixed_magnitude=None): if fixed_magnitude is not None: raise GrondError( 'Setting fixed magnitude in random model generation not ' 'supported for this type of problem.') x = rstate.uniform(0., 1., self.nparameters) x *= (xbounds[:, 1] - xbounds[:, 0]) x += xbounds[:, 0] return x
def write_config(config, path): try: guts.dump(config, filename=path, header='Grond clustering configuration file, version %s' % __version__) except OSError: raise GrondError('cannot write Grond report configuration file: %s' % path)
def random_uniform(self, xbounds, rstate, fixed_magnitude=None): if fixed_magnitude is not None: raise GrondError( 'Setting fixed magnitude in random model generation not ' 'supported for this type of problem.') x = num.zeros(self.nparameters) for i in range(self.nparameters): x[i] = rstate.uniform(xbounds[i, 0], xbounds[i, 1]) return x
def get_random_model(self, ntries_limit=100): xbounds = self.get_parameter_bounds() for _ in range(ntries_limit): x = self.random_uniform(xbounds, rstate=g_rstate) try: return self.preconstrain(x) except Forbidden: pass raise GrondError( 'Could not find any suitable candidate sample within %i tries' % (ntries_limit))
def get_sample(self, problem, iiter, chains): assert 0 <= iiter < self.niterations ntries_preconstrain = 0 for ntries_preconstrain in range(self.ntries_preconstrain_limit): try: return problem.preconstrain( self.get_raw_sample(problem, iiter, chains)) except Forbidden: pass raise GrondError( 'could not find any suitable candidate sample within %i tries' % (self.ntries_preconstrain_limit))
def write_config(config, path): try: basepath = config.get_basepath() dirname = op.dirname(path) or '.' config.change_basepath(dirname) guts.dump(config, filename=path, header='Grond report configuration file, version %s' % __version__) config.change_basepath(basepath) except OSError: raise GrondError('cannot write Grond report configuration file: %s' % path)
def analyse(self, problem, ds): if self.niter == 0: return wtargets = [] if not problem.has_waveforms: return for target in problem.waveform_targets: wtarget = copy.copy(target) wtarget.flip_norm = True wtarget.weight = 1.0 wtargets.append(wtarget) wproblem = problem.copy() wproblem.targets = wtargets xbounds = wproblem.get_parameter_bounds() misfits = num.zeros((self.niter, wproblem.ntargets, 2)) rstate = num.random.RandomState(123) isbad_mask = None self._tlog_last = 0 for iiter in range(self.niter): self.log_progress(problem, iiter, self.niter) while True: if self.use_reference_magnitude: try: fixed_magnitude = wproblem.base_source.get_magnitude() except gf.DerivedMagnitudeError: raise GrondError( 'Cannot use use_reference_magnitude for this type ' 'of source model.') else: fixed_magnitude = None x = wproblem.random_uniform(xbounds, rstate, fixed_magnitude=fixed_magnitude) try: x = wproblem.preconstrain(x) break except Forbidden: pass if isbad_mask is not None and num.any(isbad_mask): isok_mask = num.logical_not(isbad_mask) else: isok_mask = None misfits[iiter, :, :] = wproblem.misfits(x, mask=isok_mask) isbad_mask = num.isnan(misfits[iiter, :, 1]) mean_ms = num.mean(misfits[:, :, 0], axis=0) mean_ps = num.mean(misfits[:, :, 1], axis=0) weights = 1. / mean_ps families, nfamilies = wproblem.get_family_mask() for ifamily in range(nfamilies): weights[families == ifamily] /= ( num.nansum(weights[families == ifamily]) / num.nansum(num.isfinite(weights[families == ifamily]))) if self.cutoff is not None: weights[mean_ms / mean_ps > self.cutoff] = 0.0 for weight, target in zip(weights, problem.waveform_targets): target.analyser_results['target_balancing'] = \ TargetBalancingAnalyserResult(weight=float(weight)) for itarget, target in enumerate(problem.waveform_targets): logger.info( ('Balancing analysis for target "%s":\n' ' m/p: %g\n' ' weight: %g\n') % (target.string_id(), mean_ms[itarget] / mean_ps[itarget], weights[itarget]))
def raise_invalid_norm_exponent(self): raise GrondError('Invalid norm exponent: %f' % self.norm_exponent)
def get_gf_store(self, target): if self.get_engine() is None: raise GrondError('Cannot get GF Store, modelling is not set up!') return self.get_engine().get_store(target.store_id)
def combine_misfits(self, misfits, extra_weights=None, extra_residuals=None, extra_correlated_weights=dict(), get_contributions=False): ''' Combine misfit contributions (residuals) to global or bootstrap misfits :param misfits: 3D array ``misfits[imodel, iresidual, 0]`` are the misfit contributions (residuals) ``misfits[imodel, iresidual, 1]`` are the normalisation contributions. It is also possible to give the misfit and normalisation contributions for a single model as ``misfits[iresidual, 0]`` and misfits[iresidual, 1]`` in which case, the first dimension (imodel) of the result will be stipped off. :param extra_weights: if given, 2D array of extra weights to be applied to the contributions, indexed as ``extra_weights[ibootstrap, iresidual]``. :param extra_residuals: if given, 2D array of perturbations to be added to the residuals, indexed as ``extra_residuals[ibootstrap, iresidual]``. :param extra_correlated_weights: if a dictionary of ``imisfit: correlated weight matrix`` is passed a correlated weight matrix is applied to the misfit and normalisation values. `imisfit` is the starting index in the misfits vector the correlated weight matrix applies to. :param get_contributions: get the weighted and perturbed contributions (don't do the sum). :returns: if no *extra_weights* or *extra_residuals* are given, a 1D array indexed as ``misfits[imodel]`` containing the global misfit for each model is returned, otherwise a 2D array ``misfits[imodel, ibootstrap]`` with the misfit for every model and weighting/residual set is returned. ''' if misfits.ndim == 2: misfits = misfits[num.newaxis, :, :] return self.combine_misfits(misfits, extra_weights, extra_residuals, extra_correlated_weights, get_contributions)[0, ...] if extra_weights is None and extra_residuals is None: return self.combine_misfits(misfits, False, False, extra_correlated_weights, get_contributions)[:, 0] assert misfits.ndim == 3 assert not num.any(extra_weights) or extra_weights.ndim == 2 assert not num.any(extra_residuals) or extra_residuals.ndim == 2 if self.norm_exponent != 2 and extra_correlated_weights: raise GrondError('Correlated weights can only be used ' ' with norm_exponent=2') exp, root = self.get_norm_functions() nmodels = misfits.shape[0] nmisfits = misfits.shape[1] # noqa mf = misfits[:, num.newaxis, :, :].copy() if num.any(extra_residuals): mf = mf + extra_residuals[num.newaxis, :, :, num.newaxis] res = mf[..., 0] norms = mf[..., 1] for imisfit, corr_weight_mat in extra_correlated_weights.items(): jmisfit = imisfit + corr_weight_mat.shape[0] for imodel in range(nmodels): corr_res = res[imodel, :, imisfit:jmisfit] corr_norms = norms[imodel, :, imisfit:jmisfit] res[imodel, :, imisfit:jmisfit] = \ correlated_weights(corr_res, corr_weight_mat) norms[imodel, :, imisfit:jmisfit] = \ correlated_weights(corr_norms, corr_weight_mat) # Apply normalization family weights (these weights depend on # on just calculated correlated norms!) weights_fam = \ self.inter_family_weights2(norms[:, 0, :])[:, num.newaxis, :] weights_fam = exp(weights_fam) res = exp(res) norms = exp(norms) res *= weights_fam norms *= weights_fam weights_tar = self.get_target_weights()[num.newaxis, num.newaxis, :] if num.any(extra_weights): weights_tar = weights_tar * extra_weights[num.newaxis, :, :] weights_tar = exp(weights_tar) res = res * weights_tar norms = norms * weights_tar if get_contributions: return res / num.nansum(norms, axis=2)[:, :, num.newaxis] result = root(num.nansum(res, axis=2) / num.nansum(norms, axis=2)) assert result[result < 0].size == 0 return result
def post_process(self, engine, source, tr_syn): tr_syn = tr_syn.pyrocko_trace() nslc = self.codes config = self.misfit_config tmin_fit, tmax_fit, tfade, tfade_taper = \ self.get_taper_params(engine, source) ds = self.get_dataset() tobs, tsyn = self.get_pick_shift(engine, source) if None not in (tobs, tsyn): tobs_shift = tobs - tsyn else: tobs_shift = 0.0 tr_syn.extend(tmin_fit - tfade * 2.0, tmax_fit + tfade * 2.0, fillmethod='repeat') freqlimits = self.get_freqlimits() if config.quantity == 'displacement': syn_resp = None elif config.quantity == 'velocity': syn_resp = trace.DifferentiationResponse(1) elif config.quantity == 'acceleration': syn_resp = trace.DifferentiationResponse(2) else: GrondError('Unsupported quantity: %s' % config.quantity) tr_syn = tr_syn.transfer(freqlimits=freqlimits, tfade=tfade, transfer_function=syn_resp) tr_syn.chop(tmin_fit - 2 * tfade, tmax_fit + 2 * tfade) tmin_obs, tmax_obs = self.get_cutout_timespan(tmin_fit + tobs_shift, tmax_fit + tobs_shift, tfade) try: tr_obs = ds.get_waveform( nslc, quantity=config.quantity, tinc_cache=1.0 / (config.fmin or 0.1 * config.fmax), tmin=tmin_fit + tobs_shift - tfade, tmax=tmax_fit + tobs_shift + tfade, tfade=tfade, freqlimits=freqlimits, deltat=tr_syn.deltat, cache=True, backazimuth=self.get_backazimuth_for_waveform()) if tobs_shift != 0.0: tr_obs = tr_obs.copy() tr_obs.shift(-tobs_shift) mr = misfit(tr_obs, tr_syn, taper=trace.CosTaper(tmin_fit - tfade_taper, tmin_fit, tmax_fit, tmax_fit + tfade_taper), domain=config.domain, exponent=config.norm_exponent, flip=self.flip_norm, result_mode=self._result_mode, tautoshift_max=config.tautoshift_max, autoshift_penalty_max=config.autoshift_penalty_max, subtargets=self._piggyback_subtargets) self._piggyback_subtargets = [] mr.tobs_shift = float(tobs_shift) mr.tsyn_pick = float_or_none(tsyn) return mr except NotFound as e: logger.debug(str(e)) raise gf.SeismosizerError('No waveform data: %s' % str(e))