Example #1
0
 def work(self, search=True, forward=True, run_id='current'):
     self.pre_work(search or forward)
     seis = self.seismosizer
     conf = self.in_config.get_config()
     mm_conf = self.in_config.get_config(keys=Step.outer_misfit_method_params)
     
     sourcetype = self.sourcetype
     base_source = source_model.Source( sourcetype )
     
     for p in source_model.param_names(sourcetype):
         if d2u(p) in conf:
             base_source[p] = float(conf[d2u(p)])
             
     if 'plane' in conf and conf['plane'] == 2: 
         strike, dip, slip_rake = float(conf['strike']), float(conf['dip']), float(conf['slip_rake'])
         strike, dip, slip_rake = moment_tensor.other_plane( strike, dip, slip_rake )
         base_source['strike'] = strike
         base_source['dip'] = dip
         base_source['slip-rake'] = slip_rake
         
     if 'plane' in conf:
         for param in 'strike', 'dip', 'slip-rake':
             self.out_config.__dict__['active_'+d2u(param)] = base_source[param]
             
     grid_def = []
     for param in self.params:
         oldval = base_source[u2d(param)]
         descr = conf[param+'_range']            
         grid_def.append(grid_defi(u2d(param),oldval,descr))
         
     if search or forward: self.setup_inner_misfit_method()
     if search:
         if self.ref_source_from is not None:
             step, ident = self.ref_source_from
             ref_source = step.get_snapshot_source(ident)
         else:
             ref_source = None
         
         self.setup_inner_misfit_method()
         finder = gridsearch.MisfitGrid( base_source, param_values=grid_def, ref_source=ref_source)
         finder.compute(seis)
     else:
         finder = self.load(self.stepname, run_id=run_id)
         
     finder.postprocess(**mm_conf)
     self.dump(finder, self.stepname)
     
     stats = finder.stats
     for param in self.params:
         str_result = stats[u2d(param)].str_best_and_confidence()
         logging.info(str_result)
         self.result(str_result, param )
         base_source[u2d(param)] = stats[u2d(param)].best
         self.out_config.__dict__[param] = stats[u2d(param)].best
         self.out_config.__dict__[param+'_stats'] = stats[u2d(param)]
     
     self.out_config.min_misfit = finder.get_best_misfit()
     self.out_config.nstations_total  = finder.nreceivers
     self.out_config.nstations_used  = finder.nreceivers_enabled
     
     logging.info('Misfit = %f, Source = %s' % (finder.get_best_misfit(), str(base_source)))
     mt = base_source.moment_tensor()
     logging.info(str(mt))
     
     self.result(str(mt), 'moment_tensor')
     
     misfit_median = finder.get_median_of_misfits_by_r()
     if self.xblacklist_level is not None:
         ir = 0
         
         if 'xblacklist' in conf:
             xblacklist = set(conf['xblacklist'])
         else:
             xblacklist = set()
             
         for r, mm in zip(seis.receivers, finder.misfits_by_r):
             if mm/misfit_median > self.xblacklist_level:
                 xblacklist.add(ir) 
                 logging.info('Blacklisting:  %i, %s, %g' % (ir+1, r.name, mm/misfit_median))
                 
             ir += 1
         self.out_config.xblacklist = sorted(list(xblacklist))
                 
     if forward:
         self.snapshot( base_source, 'best', mm_conf )
         
     self.post_work(search or forward)
Example #2
0
    def work(self, search=True, forward=True, run_id='current'):
        self.pre_work(search or forward)
        seis = self.seismosizer
        conf = self.in_config.get_config()
        mm_conf = self.in_config.get_config(keys=Step.outer_misfit_method_params)
        
        sourcetype = self.sourcetype
        base_source = source_model.Source( sourcetype )
        
        for p in source_model.param_names(sourcetype):
            if d2u(p) in conf:
                base_source[p] = float(conf[d2u(p)])
                
        if 'plane' in conf and conf['plane'] == 2: 
            strike, dip, slip_rake = float(conf['strike']), float(conf['dip']), float(conf['slip_rake'])
            strike, dip, slip_rake = moment_tensor.other_plane( strike, dip, slip_rake )
            base_source['strike'] = strike
            base_source['dip'] = dip
            base_source['slip-rake'] = slip_rake
            
        if 'plane' in conf:
            for param in 'strike', 'dip', 'slip-rake':
                self.out_config.__dict__['active_'+d2u(param)] = base_source[param]
        
        # setup grid of starting points for gradient se
        starter_grid_def = []
        for param in self.params:
            if param+'_start_range' in conf:
                oldval = base_source[u2d(param)]
                descr = conf[param+'_start_range']
                starter_grid_def.append( grid_defi(u2d(param),oldval,descr) )
        
        if starter_grid_def:
            starter_sources = base_source.grid( starter_grid_def )
        else:
            starter_sources = [ base_source ]
        
        grid_def = []
        for param in self.params:
            oldval = base_source[u2d(param)]
            descr = conf[param+'_range']
            grid_def.append(grid_defi(u2d(param),oldval,descr))
        
        dparams = [ u2d(param) for param in self.params ]
        self.nminfunccalls = 0

        norms = [ num.min(vals[1:]-vals[:-1]) for (param, vals) in grid_def ]
        bounds = [ (num.min(vals)/norm,num.max(vals)/norm) for  ((param, vals),norm) in zip(grid_def, norms) ]

        if search or forward: self.setup_inner_misfit_method()
        
        def x_to_source(x):
            source = copy.deepcopy(base_source)
            for i,param in enumerate(self.params):
                source[u2d(param)] = x[i]*norms[i]
            return source
        
        def source_to_x(source):
            x = []
            for param, norm in zip(self.params, norms):
                x.append(source[u2d(param)]/norm)
            return x
        
        
        def minfunc(x):
            self.nminfunccalls += 1
            source = x_to_source(x)
            try:
                logging.debug('Evaluating source: %s', source.pretty_str(dparams) )
                best, misfit = seis.best_source([source], **mm_conf)
                logging.debug('Misfit: %g' % misfit)
            except NoValidSources:
                logging.warn('Gradient search aborted at invalid source:' )
                for str_param in current_base.pretty_str(dparams).splitlines():
                    logging.warn( str_param )
                raise
            return misfit
            
        if search:
            self.setup_inner_misfit_method()
                        
            # fix depth range by trying out different depths
            for iparam, (param, vals) in enumerate(grid_def):
                if param == 'depth':
                    depth_sources = base_source.grid( [ (param,vals) ] )
                    dummy_source, dummy_misfit, failings = seis.best_source(depth_sources, return_failings=True, **mm_conf)
                    ok = []
                    for isource, source in enumerate(depth_sources):
                        if isource not in failings:
                            ok.append(source['depth'])
                    miok = min(ok)
                    maok = max(ok)
                    bounds[iparam] = ((miok+gridsearch.step_at(ok,miok)*0.3)/norms[iparam],
                                      (maok-gridsearch.step_at(ok,maok)*0.3)/norms[iparam])
            
            # grid search over gradient searches
            min_misfit = None
            very_best_source = None
            ngood = 0
            ntotal = 0
            for starter_source in starter_sources:
                ntotal += 1
                # look if starting source is valid
                current_base = copy.deepcopy(starter_source)
                try:
                    current_base, misfit = seis.best_source([current_base], **mm_conf)
                except NoValidSources:
                    logging.warn('Skipping invalid starting source:')
                    for str_param in current_base.pretty_str(dparams).splitlines():
                        logging.warn( str_param )
                    continue
                if min_misfit == None:
                    min_misfit = misfit
                    very_best_source = current_base
                
                x0 = source_to_x(current_base)
                try:
                    x, misfit, d = fmin_l_bfgs_b(minfunc, x0, approx_grad=True, bounds=bounds, epsilon=0.2, factr=1e10)
                except NoValidSources:
                    continue
                current = x_to_source(x)
                if d['warnflag'] != 0: continue
                
                # restart gradient search at current minimum
                
                x0 = source_to_x(current)
                try:
                    x, misfit, d = fmin_l_bfgs_b(minfunc, x0, approx_grad=True, bounds=bounds, epsilon=0.05, factr=1e7)
                except NoValidSources:
                    continue
                current = x_to_source(x)
                if d['warnflag'] != 0: continue

                
                minkind = ''
                if misfit < min_misfit:
                    logging.info('Found possible minimum: Misfit = %f' % misfit)
                    for str_param in current.pretty_str(dparams).splitlines():
                        logging.info( str_param )
                    if 'strike' in self.params:
                        mt = moment_tensor.MomentTensor(strike=current['strike'], dip=current['dip'], rake=current['slip-rake'])
                        fps1, fps2 = mt.str_fault_planes().strip().splitlines()
                        logging.info(fps1)
                        logging.info(fps2)
                    min_misfit = misfit
                    very_best_source = current
                
                ngood += 1
                
            if min_misfit is None:
                raise Exception('No valid starting points found')
        else:
            logging.error('Fixme: inversion.py')
        
        very_best_source_normalform = copy.deepcopy(very_best_source)
        if 'strike' in base_source.keys():
            very_best_source_normalform.disambigue_sdr()
        
        for param, coords in grid_def:
            val = very_best_source[param]
            remark = ''
            if snap(val,coords)[0] in (0,len(coords)-1): remark = ' (?: at end of range)'
            str_result = '%s = %g%s' % (param.title(), val, remark)
            logging.info(str_result)
            self.result(str_result, d2u(param))
            base_source[param] = very_best_source_normalform[param]
            self.out_config.__dict__[d2u(param)] = very_best_source_normalform[param]
            
        str_result = 'Misfit = %g' % min_misfit
        logging.info(str_result)
        self.result(str_result, 'Misfit')
        self.out_config.__dict__['min_misfit'] = min_misfit
        
        logging.info('Total number iterations in gradient searches: %i' % self.nminfunccalls)
        logging.info('Number of gradient searches tried: %i' % ntotal)
        logging.info('Number of successful gradient searches: %i' % ngood)
        self.out_config.__dict__['greeper_nminfunccalls'] = self.nminfunccalls
        self.out_config.__dict__['greeper_ntotal'] = ntotal
        self.out_config.__dict__['greeper_ngood'] = ngood
           
        if forward:
            self.snapshot( base_source, 'best', mm_conf )
            
        self.post_work(search or forward)