Beispiel #1
0
def find_alt_hierarchy_fit(asimov_data_set, template_maker,hypo_params,hypo_normal,
                           minimizer_settings,only_atm_params=True,check_octant=False):
    """
    For the hypothesis of the mass hierarchy being NMH
    ('normal_hierarchy'=True) or IMH ('normal_hierarchy'=False), finds the
    best fit for the free params in 'param_values' for the alternative
    (opposite) hierarchy that maximizes the LLH of the Asimov data set.

    \params:
      * asimov_data_set - asimov data set to find best fit llh
      * template_maker - instance of class pisa.analysis.TemplateMaker, used to
        generate the asimov data set.
      * hypo_params - parameters for template generation
      * hypo_normal - boolean for NMH (True) or IMH (False)
      * minimizer_settings - settings for bfgs minimization
      * only_atm_params - boolean to denote whether the fit will be over the
        atmospheric oscillation parameters only or over all the free params
        in params
    """

    # Find best fit of the alternative hierarchy to the
    # hypothesized asimov data set.
    #hypo_types = [('hypo_IMH',False)] if data_normal else  [('hypo_NMH',True)]
    hypo_params = select_hierarchy(hypo_params,normal_hierarchy=hypo_normal)

    with Timer() as t:
        llh_data = find_max_llh_bfgs(
            asimov_data_set,template_maker,hypo_params,minimizer_settings,
            normal_hierarchy=hypo_normal,check_octant=check_octant)
    profile.info("==> elapsed time for optimizer: %s sec"%t.secs)

    return llh_data
Beispiel #2
0
def get_gradients(data_tag, param,template_maker,fiducial_params,grid_settings,store_dir):
  """
  Use the template maker to create all the templates needed to obtain the gradients.
  """
  logging.info("Working on parameter %s."%param)

  steps = get_steps(param, grid_settings, fiducial_params)

  pmaps = {}

  # Generate one template for each value of the parameter in question and store in pmaps
  for param_value in steps:

      # Make the template corresponding to the current value of the parameter
      with Timer() as t:
          maps = template_maker.get_template(
              get_values(dict(fiducial_params,**{param:dict(fiducial_params[param],
                                                            **{'value': param_value})})))
      profile.info("==> elapsed time for template: %s sec"%t.secs)

      pmaps[param_value] = maps

  # Store the maps used to calculate partial derivatives
  if store_dir != tempfile.gettempdir():
  	logging.info("Writing maps for parameter %s to %s"%(param,store_dir))

  to_json(pmaps, os.path.join(store_dir,param+"_"+data_tag+".json"))

  gradient_map = get_derivative_map(pmaps,fiducial_params[param],degree=2)

  return gradient_map
Beispiel #3
0
def find_alt_hierarchy_fit(asimov_data_set,
                           template_maker,
                           hypo_params,
                           hypo_normal,
                           minimizer_settings,
                           only_atm_params=True,
                           check_octant=False):
    """
    For the hypothesis of the mass hierarchy being NMH
    ('normal_hierarchy'=True) or IMH ('normal_hierarchy'=False), finds the
    best fit for the free params in 'param_values' for the alternative
    (opposite) hierarchy that maximizes the LLH of the Asimov data set.

    \params:
      * asimov_data_set - asimov data set to find best fit llh
      * template_maker - instance of class pisa.analysis.TemplateMaker, used to
        generate the asimov data set.
      * hypo_params - parameters for template generation
      * hypo_normal - boolean for NMH (True) or IMH (False)
      * minimizer_settings - settings for bfgs minimization
      * only_atm_params - boolean to denote whether the fit will be over the
        atmospheric oscillation parameters only or over all the free params
        in params
    """

    # Find best fit of the alternative hierarchy to the
    # hypothesized asimov data set.
    #hypo_types = [('hypo_IMH',False)] if data_normal else  [('hypo_NMH',True)]
    hypo_params = select_hierarchy(hypo_params, normal_hierarchy=hypo_normal)

    with Timer() as t:
        llh_data = find_max_llh_bfgs(asimov_data_set,
                                     template_maker,
                                     hypo_params,
                                     minimizer_settings,
                                     normal_hierarchy=hypo_normal,
                                     check_octant=check_octant)
    profile.info("==> elapsed time for optimizer: %s sec" % t.secs)

    return llh_data
    def get_osc_prob_maps(self, **kwargs):
        """
        Returns an oscillation probability map dictionary calculated
        at the values of the input parameters:
          deltam21,deltam31,theta12,theta13,theta23,deltacp
        for flavor_from to flavor_to, with the binning of ebins,czbins.
        The dictionary is formatted as:
          'nue_maps': {'nue':map,'numu':map,'nutau':map},
          'numu_maps': {...}
          'nue_bar_maps': {...}
          'numu_bar_maps': {...}
        NOTES: * expects all angles in [rad]
               * this method doesn't calculate the oscillation probabi-
                 lities itself, but calls get_osc_probLT_dict internally
        """
        #Get the finely binned maps as implemented in the derived class
        logging.info('Retrieving finely binned maps')
        fine_maps = self.get_osc_probLT_dict(**kwargs)

        logging.info("Smoothing fine maps...")
        profile.info("start smoothing maps")
        smoothed_maps = {}
        smoothed_maps['ebins'] = self.ebins
        smoothed_maps['czbins'] = self.czbins

        for from_nu, tomap_dict in fine_maps.items():
            if 'bins' in from_nu: continue
            new_tomaps = {}
            for to_nu, tomap in tomap_dict.items():
                logging.debug("Getting smoothed map %s/%s"%(from_nu,to_nu))
                new_tomaps[to_nu] = get_smoothed_map(tomap,
                                         fine_maps['ebins'],
                                         fine_maps['czbins'],
                                         self.ebins, self.czbins)
            smoothed_maps[from_nu] = new_tomaps

        profile.info("stop smoothing maps")

        return smoothed_maps
Beispiel #5
0
def get_gradients(data_tag, param, template_maker, fiducial_params,
                  grid_settings, store_dir):
    """
  Use the template maker to create all the templates needed to obtain the gradients.
  """
    logging.info("Working on parameter %s." % param)

    steps = get_steps(param, grid_settings, fiducial_params)

    pmaps = {}

    # Generate one template for each value of the parameter in question and store in pmaps
    for param_value in steps:

        # Make the template corresponding to the current value of the parameter
        with Timer() as t:
            maps = template_maker.get_template(
                get_values(
                    dict(
                        fiducial_params, **{
                            param:
                            dict(fiducial_params[param],
                                 **{'value': param_value})
                        })))
        profile.info("==> elapsed time for template: %s sec" % t.secs)

        pmaps[param_value] = maps

    # Store the maps used to calculate partial derivatives
    if store_dir != tempfile.gettempdir():
        logging.info("Writing maps for parameter %s to %s" %
                     (param, store_dir))

    to_json(pmaps, os.path.join(store_dir, param + "_" + data_tag + ".json"))

    gradient_map = get_derivative_map(pmaps, fiducial_params[param], degree=2)

    return gradient_map
Beispiel #6
0
    def fill_osc_prob(self, osc_prob_dict, ecen, czcen,
                      theta12=None, theta13=None, theta23=None,
                      deltam21=None, deltam31=None, deltacp=None,
                      energy_scale=None,**kwargs):
        '''
        Loops over ecen,czcen and fills the osc_prob_dict maps, with
        probabilities calculated according to prob3
        '''

        neutrinos = ['nue','numu','nutau']
        anti_neutrinos = ['nue_bar','numu_bar','nutau_bar']
        mID = ['','_bar']

        nu_barger = {'nue':1,'numu':2,'nutau':3,
                     'nue_bar':1,'numu_bar':2,'nutau_bar':3}

        logging.info("Defining osc_prob_dict from BargerPropagator...")
        profile.info("start oscillation calculation")
        # Set to false, since we are using sin^2(2 theta) variables
        kSquared = False
        sin2th12Sq = np.sin(2.0*theta12)**2
        sin2th13Sq = np.sin(2.0*theta13)**2
        sin2th23Sq = np.sin(2.0*theta23)**2

        total_bins = int(len(ecen)*len(czcen))
        mod = total_bins/50
        ibin = 0
        loglevel = logging.root.getEffectiveLevel()
        for icz, coszen in enumerate(czcen):

            for ie,energy in enumerate(ecen):
                if energy_scale is not None: energy*=energy_scale
                ibin+=1
                if loglevel <= logging.INFO:
                    if (ibin%mod) == 0:
                        sys.stdout.write(".")
                        sys.stdout.flush()

                # In BargerPropagator code, it takes the "atmospheric
                # mass difference"-the nearest two mass differences, so
                # that it takes as input deltam31 for IMH and deltam32
                # for NMH
                mAtm = deltam31 if deltam31 < 0.0 else (deltam31 - deltam21)

                ########### FIRST FOR NEUTRINOS ##########
                kNuBar = 1 # +1 for nu -1 for nubar
                self.barger_prop.SetMNS(sin2th12Sq,sin2th13Sq,sin2th23Sq,deltam21,mAtm,
                                        deltacp,energy,kSquared,kNuBar)
                self.barger_prop.DefinePath(coszen, self.prop_height)
                self.barger_prop.propagate(kNuBar)

                for nu in ['nue','numu']:
                    nu_i = nu_barger[nu]
                    nu = nu+'_maps'
                    for to_nu in neutrinos:
                        nu_f = nu_barger[to_nu]
                        osc_prob_dict[nu][to_nu][ie][icz]=self.barger_prop.GetProb(nu_i,nu_f)

                ########### SECOND FOR ANTINEUTRINOS ##########
                kNuBar = -1
                self.barger_prop.SetMNS(sin2th12Sq,sin2th13Sq,sin2th23Sq,deltam21,
                                        mAtm,deltacp,energy,kSquared,kNuBar)
                self.barger_prop.DefinePath(coszen, self.prop_height)
                self.barger_prop.propagate(kNuBar)

                for nu in ['nue_bar','numu_bar']:
                    nu_i = nu_barger[nu]
                    nu+='_maps'
                    for to_nu in anti_neutrinos:
                        nu_f = nu_barger[to_nu]
                        osc_prob_dict[nu][to_nu][ie][icz] = self.barger_prop.GetProb(nu_i,nu_f)

        if loglevel <= logging.INFO:
            sys.stdout.write("\n")

        profile.info("stop oscillation calculation")

        return
Beispiel #7
0
def llh_bfgs(opt_vals, *args):
    """
    Function that the bfgs algorithm tries to minimize. Essentially,
    it is a wrapper function around get_template() and
    get_binwise_llh().

    This fuction is set up this way, because the fmin_l_bfgs_b
    algorithm must take a function with two inputs: params & *args,
    where 'params' are the actual VALUES to be varied, and must
    correspond to the limits in 'bounds', and 'args' are arguments
    which are not varied and optimized, but needed by the
    get_template() function here. Thus, we pass the arguments to this
    function as follows:

    --opt_vals: [param1,param2,...,paramN] - systematics varied in the optimization.
    --args: [names,scales,fmap,fixed_params,template_maker,opt_steps_dict,priors]
      where
        names: are the dict keys corresponding to param1, param2,...
        scales: the scales to be applied before passing to get_template
          [IMPORTANT! In the optimizer, all parameters must be ~ the same order.
          Here, we keep them between 0.1,1 so the "epsilon" step size will vary
          the parameters in roughly the same precision.]
        fmap: pseudo data flattened map
        fixed_params: dictionary of other paramters needed by the get_template()
          function
        template_maker: template maker object
        opt_steps_dict: dictionary recording information regarding the steps taken
          for each trial of the optimization process.
        priors: gaussian priors corresponding to opt_vals list.
          Format: [(prior1,best1),(prior2,best2),...,(priorN,bestN)]
    """

    names, scales, fmap, fixed_params, template_maker, opt_steps_dict, priors = args

    # free parameters being "optimized" by minimizer re-scaled to their true values.
    unscaled_opt_vals = [
        opt_vals[i] / scales[i] for i in xrange(len(opt_vals))
    ]

    unscaled_free_params = {
        names[i]: val
        for i, val in enumerate(unscaled_opt_vals)
    }
    template_params = dict(unscaled_free_params.items() +
                           get_values(fixed_params).items())

    # Now get true template, and compute LLH
    with Timer() as t:
        if template_params['theta23'] == 0.0:
            logging.info(
                "Zero theta23, so generating no oscillations template...")
            true_template = template_maker.get_template_no_osc(template_params)
        else:
            true_template = template_maker.get_template(template_params)
    profile.info("==> elapsed time for template maker: %s sec" % t.secs)
    true_fmap = flatten_map(true_template, chan=template_params['channel'])

    # NOTE: The minus sign is present on both of these next two lines
    # to reflect the fact that the optimizer finds a minimum rather
    # than maximum.
    llh = -get_binwise_llh(fmap, true_fmap)
    llh -= sum([
        get_prior_llh(opt_val, sigma, value)
        for (opt_val, (sigma, value)) in zip(unscaled_opt_vals, priors)
    ])

    # Save all optimizer-tested values to opt_steps_dict, to see
    # optimizer history later
    for key in names:
        opt_steps_dict[key].append(template_params[key])
    opt_steps_dict['llh'].append(llh)

    physics.debug("LLH is %.2f at: " % llh)
    for name, val in zip(names, opt_vals):
        physics.debug(" %20s = %6.4f" % (name, val))

    return llh
Beispiel #8
0
if scipy.__version__ < '0.12.0':
    logging.warn('Detected scipy version %s < 0.12.0'%scipy.__version__)
    if 'maxiter' in minimizer_settings:
      logging.warn('Optimizer settings for \"maxiter\" will be ignored')
      minimizer_settings.pop('maxiter')

#Get the parameters
params = template_settings['params']

#store results from all the trials
trials = []

template_maker = TemplateMaker(get_values(params),**template_settings['binning'])

for itrial in xrange(1,args.ntrials+1):
    profile.info("start trial %d"%itrial)
    logging.info(">"*10 + "Running trial: %05d"%itrial + "<"*10)


    # //////////////////////////////////////////////////////////////////////
    # For each trial, generate two pseudo-data experiemnts (one for each
    # hierarchy), and for each find the best matching template in each of the
    # hierarchy hypothesis.
    # //////////////////////////////////////////////////////////////////////
    results = {}
    for data_tag, data_normal in [('data_NMH',True),('data_IMH',False)]:

        results[data_tag] = {}
        # 0) get a random seed and store with the data
        results[data_tag]['seed'] = get_seed()
        # 1) get a pseudo data fmap from fiducial model (best fit vals of params).
Beispiel #9
0
                               **template_settings['binning'])
if args.pseudo_data_settings:
    pseudo_data_template_maker = TemplateMaker(
        get_values(pseudo_data_settings['params']),
        **pseudo_data_settings['binning'])
else:
    pseudo_data_template_maker = template_maker

# Put in try/except block?

#store results from all the trials
trials = []

try:
    for itrial in xrange(1, args.ntrials + 1):
        profile.info("start trial %d" % itrial)
        logging.info(">" * 10 + "Running trial: %05d" % itrial + "<" * 10)

        # //////////////////////////////////////////////////////////////////////
        # For each trial, generate two pseudo-data experiemnts (one for each
        # hierarchy), and for each find the best matching template in each of the
        # hierarchy hypotheses.
        # //////////////////////////////////////////////////////////////////////
        results = {}
        for data_tag, data_normal in [('data_NMH', True), ('data_IMH', False)]:

            results[data_tag] = {}
            # 0) get a random seed and store with the data
            results[data_tag]['seed'] = get_seed()
            logging.info("  RNG seed: %ld" % results[data_tag]['seed'])
            # 1) get a pseudo data fmap from fiducial model (best fit vals of params).
Beispiel #10
0
                               **template_settings['binning'])
if args.pseudo_data_settings:
    pseudo_data_template_maker = TemplateMaker(get_values(pseudo_data_settings['params']),
                                               **pseudo_data_settings['binning'])
else:
    pseudo_data_template_maker = template_maker


# Put in try/except block?

#store results from all the trials
trials = []

try:
    for itrial in xrange(1,args.ntrials+1):
        profile.info("start trial %d"%itrial)
        logging.info(">"*10 + "Running trial: %05d"%itrial + "<"*10)

        # //////////////////////////////////////////////////////////////////////
        # For each trial, generate two pseudo-data experiemnts (one for each
        # hierarchy), and for each find the best matching template in each of the
        # hierarchy hypotheses.
        # //////////////////////////////////////////////////////////////////////
        results = {}
        for data_tag, data_normal in [('data_NMH',True),('data_IMH',False)]:

            results[data_tag] = {}
            # 0) get a random seed and store with the data
            results[data_tag]['seed'] = get_seed()
            logging.info("  RNG seed: %ld"%results[data_tag]['seed'])
            # 1) get a pseudo data fmap from fiducial model (best fit vals of params).
Beispiel #11
0
def find_max_grid(fmap,
                  template_maker,
                  params,
                  grid_settings,
                  save_steps=True,
                  normal_hierarchy=True):
    '''
    Finds the template (and free systematic params) that maximize
    likelihood that the data came from the chosen template of true
    params, using a brute force grid scan over the whole parameter space.

    returns a dictionary of llh data and best fit params, in the format:
      {'llh': [...],
       'param1': [...],
       'param2': [...],
       ...}
    where 'param1', 'param2', ... are the free params that are varied in the
    scan. If save_steps is False, all lists only contain the best-fit parameters
    and llh values.
    '''

    #print "NOW INSIDE find_max_grid:"
    #print "After fixing to their true values, params dict is now: "
    #for key in params.keys():
    #    try: print "  >>param: %s value: %s"%(key,str(params[key]['best']))
    #    except: continue

    # Get params dict which will be optimized (free_params) and which
    # won't be (fixed_params) but are still needed for get_template()
    fixed_params = get_fixed_params(select_hierarchy(params, normal_hierarchy))
    free_params = get_free_params(select_hierarchy(params, normal_hierarchy))

    #Obtain just the priors
    priors = get_param_priors(free_params)

    #Calculate steps for all free parameters
    calc_steps(free_params, grid_settings['steps'])

    #Build a list from all parameters that holds a list of (name, step) tuples
    steplist = [[(name, step) for step in param['steps']]
                for name, param in sorted(free_params.items())]

    #Prepare to store all the steps
    steps = {key: [] for key in free_params.keys()}
    steps['llh'] = []

    #Iterate over the cartesian product
    for pos in product(*steplist):

        #Get a dict with all parameter values at this position
        #including the fixed parameters
        template_params = dict(list(pos) + get_values(fixed_params).items())

        #print "   >> NOW IN LOOP: "
        #for key in template_params.keys():
        #    try: print "  >>param: %s value: %s"%(key,str(template_params[key]['value']))
        #    except: continue

        # Now get true template
        profile.info('start template calculation')
        true_template = template_maker.get_template(template_params)
        profile.info('stop template calculation')
        true_fmap = flatten_map(true_template)

        #and calculate the likelihood
        llh = -get_binwise_llh(fmap, true_fmap)

        #get sorted vals to match with priors
        vals = [v for k, v in sorted(pos)]
        llh -= sum([
            get_prior_llh(vals, sigma, value)
            for (vals, (sigma, value)) in zip(vals, priors)
        ])

        # Save all values to steps and report
        steps['llh'].append(llh)
        physics.debug("LLH is %.2f at: " % llh)
        for key, val in pos:
            steps[key].append(val)
            physics.debug(" %20s = %6.4f" % (key, val))

    #Find best fit value
    maxllh = min(steps['llh'])
    maxpos = steps['llh'].index(maxllh)

    #Report best fit
    physics.info('Found best LLH = %.2f in %d calls at:' %
                 (maxllh, len(steps['llh'])))
    for name, vals in steps.items():
        physics.info('  %20s = %6.4f' % (name, vals[maxpos]))

        #only save this maximum if asked for
        if not save_steps:
            steps[name] = vals[maxpos]

    return steps
Beispiel #12
0
if args.gpu_id is not None:
    template_settings['params']['gpu_id'] = {}
    template_settings['params']['gpu_id']['value'] = args.gpu_id
    template_settings['params']['gpu_id']['fixed'] = True

#Get the parameters
params = template_settings['params']

# Make sure that atmospheric parameters are fixed:
logging.warn("Ensuring that atmospheric parameters are fixed for this analysis")
params = fix_atm_params(params)
#print "params: ",params.items()

with Timer() as t:
    template_maker = TemplateMaker(get_values(params),**template_settings['binning'])
profile.info("==> elapsed time to initialize templates: %s sec"%t.secs)

#data_types = [('data_NMH',True),('data_IMH',False)]
data_types = [('data_NMH',True)]

results = {}
# Store for future checking:
results['template_settings'] = template_settings
results['minimizer_settings'] = minimizer_settings
results['grid_settings'] = grid_settings

try:
    for data_tag, data_normal in data_types:
        results[data_tag] = {}

        data_params = select_hierarchy(params,normal_hierarchy=data_normal)
Beispiel #13
0
#Read in the settings
template_settings = from_json(args.template_settings)
grid_settings = from_json(args.grid_settings)

#Get the parameters
params = template_settings['params']

#store results from all the trials
trials = []

template_maker = TemplateMaker(get_values(params),
                               **template_settings['binning'])

for itrial in xrange(1, args.ntrials + 1):
    profile.info("start trial %d" % itrial)
    logging.info(">" * 10 + "Running trial: %05d" % itrial + "<" * 10)

    # //////////////////////////////////////////////////////////////////////
    # For each trial, generate two pseudo-data experiemnts (one for each
    # hierarchy), and for each find the best matching template in each of the
    # hierarchy hypothesis.
    # //////////////////////////////////////////////////////////////////////
    results = {}
    for data_tag, data_normal in [('data_NMH', True), ('data_IMH', False)]:

        results[data_tag] = {}
        # 1) get a pseudo data fmap from fiducial model (best fit vals of params).
        fmap = get_pseudo_data_fmap(
            template_maker,
            get_values(select_hierarchy(params, normal_hierarchy=data_normal)))
Beispiel #14
0
def get_fisher_matrices(template_settings,
                        grid_settings,
                        IMH=True,
                        NMH=False,
                        dump_all_stages=False,
                        save_templates=False,
                        outdir=None):
    '''
  Main function that runs the Fisher analysis for the chosen hierarchy(ies) (inverted by default).

  Returns a dictionary of Fisher matrices, in the format:
  {'IMH': {'cscd': [...],
          'trck': [...],
          'comb': [...],
          },
  'NMH': {'cscd': [...],
          'trck': [...],
          'comb': [...],
         }
  }

  If save_templates=True and no hierarchy is given, only fiducial templates will be written out;
  if one is given, then the templates used to obtain the gradients will be written out in
  addition.
  '''
    if outdir is None and (save_templates or dump_all_stages):
        logging.info(
            "No output directory specified. Will save templates to current working directory."
        )
        outdir = os.getcwd()

    profile.info("start initializing")

    # Get the parameters
    params = template_settings['params']
    bins = template_settings['binning']

    # Artifically add the hierarchy parameter to the list of parameters
    # The method get_hierarchy_gradients below will know how to deal with it
    params['hierarchy_nh'] = {
        "value": 1.,
        "range": [0., 1.],
        "fixed": False,
        "prior": None
    }
    params['hierarchy_ih'] = {
        "value": 0.,
        "range": [0., 1.],
        "fixed": False,
        "prior": None
    }

    chosen_data = []
    if IMH:
        chosen_data.append(('IMH', False))
        logging.info("Fisher matrix will be built for IMH.")
    if NMH:
        chosen_data.append(('NMH', True))
        logging.info("Fisher matrix will be built for NMH.")
    if chosen_data == []:
        # In this case, only the fiducial maps (for both hierarchies) will be written
        logging.info("No Fisher matrices will be built.")

    # There is no sense in performing any of the following steps if no Fisher matrices are to be built
    # and no templates are to be saved.
    if chosen_data != [] or dump_all_stages or save_templates:

        # Initialise return dict to hold Fisher matrices
        fisher = {
            data_tag: {
                'cscd': [],
                'trck': [],
                'comb': []
            }
            for data_tag, data_normal in chosen_data
        }

        # Get a template maker with the settings used to initialize
        template_maker = TemplateMaker(get_values(params), **bins)

        profile.info("stop initializing\n")

        # Generate fiducial templates for both hierarchies (needed for partial derivatives
        # w.r.t. hierarchy parameter)
        fiducial_maps = {}
        for hierarchy in ['NMH', 'IMH']:

            logging.info("Generating fiducial templates for %s." % hierarchy)

            # Get the fiducial parameter values corresponding to this hierarchy
            fiducial_params = select_hierarchy(
                params, normal_hierarchy=(hierarchy == 'NMH'))

            # Generate fiducial maps, either all of them or only the ultimate one
            profile.info("start template calculation")
            with Timer() as t:
                fid_maps = template_maker.get_template(
                    get_values(fiducial_params), return_stages=dump_all_stages)
            profile.info("==> elapsed time for template: %s sec" % t.secs)

            fiducial_maps[
                hierarchy] = fid_maps[4] if dump_all_stages else fid_maps

            # save fiducial map(s)
            # all stages
            if dump_all_stages:
                stage_names = ("0_unoscillated_flux", "1_oscillated_flux",
                               "2_oscillated_counts", "3_reco", "4_pid")
                stage_maps = {}
                for stage in xrange(0, len(fid_maps)):
                    stage_maps[stage_names[stage]] = fid_maps[stage]
                logging.info(
                    "Writing fiducial maps (all stages) for %s to %s." %
                    (hierarchy, outdir))
                to_json(stage_maps,
                        os.path.join(outdir, "fid_map_" + hierarchy + ".json"))
            # only the final stage
            elif save_templates:
                logging.info(
                    "Writing fiducial map (final stage) for %s to %s." %
                    (hierarchy, outdir))
                to_json(fiducial_maps[hierarchy],
                        os.path.join(outdir, "fid_map_" + hierarchy + ".json"))

        # Get_gradients and get_hierarchy_gradients will both (temporarily)
        # store the templates used to generate the gradient maps
        store_dir = outdir if save_templates else tempfile.gettempdir()

        # Calculate Fisher matrices for the user-defined cases (NHM true and/or IMH true)
        for data_tag, data_normal in chosen_data:

            logging.info("Running Fisher analysis for %s." % (data_tag))

            # The fiducial params are selected from the hierarchy case that does NOT match
            # the data, as we are varying from this model to find the 'best fit'
            fiducial_params = select_hierarchy(params, not data_normal)

            # Get the free parameters (i.e. those for which the gradients should be calculated)
            free_params = select_hierarchy(get_free_params(params),
                                           not data_normal)
            gradient_maps = {}
            for param in free_params.keys():
                # Special treatment for the hierarchy parameter
                if param == 'hierarchy':
                    gradient_maps[param] = get_hierarchy_gradients(
                        data_tag,
                        fiducial_maps,
                        fiducial_params,
                        grid_settings,
                        store_dir,
                    )
                else:
                    gradient_maps[param] = get_gradients(
                        data_tag, param, template_maker, fiducial_params,
                        grid_settings, store_dir)

            logging.info("Building Fisher matrix for %s." % (data_tag))

            # Build Fisher matrices for the given hierarchy
            fisher[data_tag] = build_fisher_matrix(
                gradient_maps,
                fiducial_maps['IMH'] if data_normal else fiducial_maps['NMH'],
                fiducial_params)

            # If Fisher matrices exist for both channels, add the matrices to obtain the combined one.
            if len(fisher[data_tag].keys()) > 1:
                fisher[data_tag]['comb'] = FisherMatrix(
                    matrix=np.array([
                        f.matrix for f in fisher[data_tag].itervalues()
                    ]).sum(axis=0),
                    parameters=gradient_maps.keys(),  #order is important here!
                    best_fits=[
                        fiducial_params[par]['value']
                        for par in gradient_maps.keys()
                    ],
                    priors=[
                        fiducial_params[par]['prior']
                        for par in gradient_maps.keys()
                    ],
                )
        return fisher

    else:
        logging.info("Nothing to be done.")
        return {}
Beispiel #15
0
    def fill_osc_prob(self,
                      osc_prob_dict,
                      ecen,
                      czcen,
                      theta12=None,
                      theta13=None,
                      theta23=None,
                      deltam21=None,
                      deltam31=None,
                      deltacp=None,
                      energy_scale=None,
                      YeI=None,
                      YeO=None,
                      YeM=None,
                      **kwargs):
        '''
        Loops over ecen,czcen and fills the osc_prob_dict maps, with
        probabilities calculated according to prob3
        '''

        neutrinos = ['nue', 'numu', 'nutau']
        anti_neutrinos = ['nue_bar', 'numu_bar', 'nutau_bar']
        mID = ['', '_bar']

        nu_barger = {
            'nue': 1,
            'numu': 2,
            'nutau': 3,
            'nue_bar': 1,
            'numu_bar': 2,
            'nutau_bar': 3
        }

        logging.info("Defining osc_prob_dict from BargerPropagator...")
        profile.info("start oscillation calculation")
        # Set to true, since we are using sin^2(theta) variables
        kSquared = True
        sin2th12Sq = np.sin(theta12)**2
        sin2th13Sq = np.sin(theta13)**2
        sin2th23Sq = np.sin(theta23)**2
        evals = []
        czvals = []
        total_bins = int(len(ecen) * len(czcen))
        mod = total_bins / 20
        loglevel = logging.root.getEffectiveLevel()
        for ie, energy in enumerate(ecen):
            for icz, coszen in enumerate(czcen):
                evals.append(energy)
                czvals.append(coszen)
                scaled_energy = energy * energy_scale

                if loglevel <= logging.INFO:
                    if ((ie + 1) * (icz + 1) % mod == 0):
                        sys.stdout.write(".")
                        sys.stdout.flush()

                # In BargerPropagator code, it takes the "atmospheric
                # mass difference"-the nearest two mass differences, so
                # that it takes as input deltam31 for IMH and deltam32
                # for NMH
                mAtm = deltam31 if deltam31 < 0.0 else (deltam31 - deltam21)

                ########### FIRST FOR NEUTRINOS ##########
                kNuBar = 1  # +1 for nu -1 for nubar
                self.barger_prop.SetMNS(sin2th12Sq, sin2th13Sq, sin2th23Sq,
                                        deltam21, mAtm, deltacp, scaled_energy,
                                        kSquared, kNuBar)

                self.barger_prop.DefinePath(coszen, self.prop_height, YeI, YeO,
                                            YeM)
                self.barger_prop.propagate(kNuBar)

                for nu in ['nue', 'numu']:
                    nu_i = nu_barger[nu]
                    nu = nu + '_maps'
                    for to_nu in neutrinos:
                        nu_f = nu_barger[to_nu]
                        osc_prob_dict[nu][to_nu].append(
                            self.barger_prop.GetProb(nu_i, nu_f))

                ########### SECOND FOR ANTINEUTRINOS ##########
                kNuBar = -1
                self.barger_prop.SetMNS(sin2th12Sq, sin2th13Sq, sin2th23Sq,
                                        deltam21, mAtm, deltacp, scaled_energy,
                                        kSquared, kNuBar)
                self.barger_prop.DefinePath(coszen, self.prop_height, YeI, YeO,
                                            YeM)
                self.barger_prop.propagate(kNuBar)

                for nu in ['nue_bar', 'numu_bar']:
                    nu_i = nu_barger[nu]
                    nu += '_maps'
                    for to_nu in anti_neutrinos:
                        nu_f = nu_barger[to_nu]
                        osc_prob_dict[nu][to_nu].append(
                            self.barger_prop.GetProb(nu_i, nu_f))

        if loglevel <= logging.INFO: sys.stdout.write("\n")

        profile.info("stop oscillation calculation")

        return evals, czvals
Beispiel #16
0
    parser.add_argument('-o', '--outfile', dest='outfile', metavar='FILE',
                        type=str, action='store',default="template.json",
                        help='file to store the output')
    args = parser.parse_args()

    set_verbosity(args.verbose)

    with Timer() as t:
        #Load all the settings
        model_settings = from_json(args.template_settings)

        #Select a hierarchy
        logging.info('Selected %s hierarchy'%
                     ('normal' if args.normal else 'inverted'))
        params =  select_hierarchy(model_settings['params'],
                                   normal_hierarchy=args.normal)

        #Intialize template maker
        template_maker = TemplateMaker(get_values(params),
                                       **model_settings['binning'])
    profile.info("  ==> elapsed time to initialize templates: %s sec"%t.secs)

    #Now get the actual template
    with Timer(verbose=False) as t:
        template_maps = template_maker.get_template(get_values(params),
                                                    return_stages=args.save_all)
    profile.info("==> elapsed time to get template: %s sec"%t.secs)

    logging.info("Saving file to %s"%args.outfile)
    to_json(template_maps, args.outfile)
Beispiel #17
0
                        default="",
                        help="Directory to save the output figures.")
    parser.add_argument('-v',
                        '--verbose',
                        action='count',
                        default=0,
                        help='set verbosity level')
    args = parser.parse_args()
    set_verbosity(args.verbose)

    template_settings = from_json(args.template_settings)

    with Timer() as t:
        template_maker = TemplateMaker(get_values(template_settings['params']),
                                       **template_settings['binning'])
    profile.info("==> elapsed time to initialize templates: %s sec" % t.secs)

    # Make nmh template:
    nmh_params = select_hierarchy(template_settings['params'],
                                  normal_hierarchy=True)
    imh_params = select_hierarchy(template_settings['params'],
                                  normal_hierarchy=False)
    with Timer(verbose=False) as t:
        nmh = template_maker.get_template(get_values(nmh_params),
                                          return_stages=args.all)
    profile.info("==> elapsed time to get NMH template: %s sec" % t.secs)
    with Timer(verbose=False) as t:
        imh = template_maker.get_template(get_values(imh_params),
                                          return_stages=args.all)
    profile.info("==> elapsed time to get IMH template: %s sec" % t.secs)
Beispiel #18
0
    logging.warn('Detected scipy version %s < 0.12.0'%scipy.__version__)
    if 'maxiter' in minimizer_settings:
        logging.warn('Optimizer settings for \"maxiter\" will be ignored')
        minimizer_settings.pop('maxiter')

#Get the parameters
params = template_settings['params']

# Make sure that atmospheric parameters are fixed:
logging.warn("Ensuring that atmospheric parameters are fixed for this analysis")
params = fix_atm_params(params)
#print "params: ",params.items()

with Timer() as t:
    template_maker = TemplateMaker(get_values(params),**template_settings['binning'])
profile.info("==> elapsed time to initialize templates: %s sec"%t.secs)

#data_types = [('data_NMH',True),('data_IMH',False)]
data_types = [('data_NMH',True)]

results = {}
# Store for future checking:
results['template_settings'] = template_settings
results['minimizer_settings'] = minimizer_settings
results['grid_settings'] = grid_settings

try:
    for data_tag, data_normal in data_types:
        results[data_tag] = {}

        data_params = select_hierarchy(params,normal_hierarchy=data_normal)
Beispiel #19
0
set_verbosity(args.verbose)

# Read in the settings
template_settings = from_json(args.template_settings)
grid_settings = from_json(args.grid_settings)

# Get the parameters
params = template_settings["params"]

# store results from all the trials
trials = []

template_maker = TemplateMaker(get_values(params), **template_settings["binning"])

for itrial in xrange(1, args.ntrials + 1):
    profile.info("start trial %d" % itrial)
    logging.info(">" * 10 + "Running trial: %05d" % itrial + "<" * 10)

    # //////////////////////////////////////////////////////////////////////
    # For each trial, generate two pseudo-data experiemnts (one for each
    # hierarchy), and for each find the best matching template in each of the
    # hierarchy hypothesis.
    # //////////////////////////////////////////////////////////////////////
    results = {}
    for data_tag, data_normal in [("data_NMH", True), ("data_IMH", False)]:

        results[data_tag] = {}
        # 1) get a pseudo data fmap from fiducial model (best fit vals of params).
        fmap = get_pseudo_data_fmap(template_maker, get_values(select_hierarchy(params, normal_hierarchy=data_normal)))

        # 2) find max llh (and best fit free params) from matching pseudo data
Beispiel #20
0
                        help='''settings for the template generation''')
    hselect = parser.add_mutually_exclusive_group(required=False)
    hselect.add_argument('--normal', dest='normal', default=True,
                        action='store_true', help="select the normal hierarchy")
    hselect.add_argument('--inverted', dest='normal', default = False,
                        action='store_false', help="select the inverted hierarchy")
    parser.add_argument('-v','--verbose',action='count',default=None,
                        help='set verbosity level.')
    parser.add_argument('-o', '--outfile', dest='outfile', metavar='FILE', type=str,
                        action='store',default="template.json",
                        help='file to store the output')
    args = parser.parse_args()

    set_verbosity(args.verbose)

    profile.info("start initializing")

    #Load all the settings
    model_settings = from_json(args.template_settings)

    #Select a hierarchy
    logging.info('Selected %s hierarchy'%
            ('normal' if args.normal else 'inverted'))
    params =  select_hierarchy(model_settings['params'],normal_hierarchy=args.normal)

    #Intialize template maker
    template_maker = TemplateMaker(get_values(params),**model_settings['binning'])

    profile.info("stop initializing")

    #Now get the actual template
Beispiel #21
0
def llh_bfgs(opt_vals,*args):
    """
    Function that the bfgs algorithm tries to minimize. Essentially,
    it is a wrapper function around get_template() and
    get_binwise_llh().

    This fuction is set up this way, because the fmin_l_bfgs_b
    algorithm must take a function with two inputs: params & *args,
    where 'params' are the actual VALUES to be varied, and must
    correspond to the limits in 'bounds', and 'args' are arguments
    which are not varied and optimized, but needed by the
    get_template() function here. Thus, we pass the arguments to this
    function as follows:

    --opt_vals: [param1,param2,...,paramN] - systematics varied in the optimization.
    --args: [names,scales,fmap,fixed_params,template_maker,opt_steps_dict,priors]
      where
        names: are the dict keys corresponding to param1, param2,...
        scales: the scales to be applied before passing to get_template
          [IMPORTANT! In the optimizer, all parameters must be ~ the same order.
          Here, we keep them between 0.1,1 so the "epsilon" step size will vary
          the parameters in roughly the same precision.]
        fmap: pseudo data flattened map
        fixed_params: dictionary of other paramters needed by the get_template()
          function
        template_maker: template maker object
        opt_steps_dict: dictionary recording information regarding the steps taken
          for each trial of the optimization process.
        priors: gaussian priors corresponding to opt_vals list.
          Format: [(prior1,best1),(prior2,best2),...,(priorN,bestN)]
    """


    names,scales,fmap,fixed_params,template_maker,opt_steps_dict,priors = args

    # free parameters being "optimized" by minimizer re-scaled to their true values.
    unscaled_opt_vals = [opt_vals[i]/scales[i] for i in xrange(len(opt_vals))]

    unscaled_free_params = { names[i]: val for i,val in enumerate(unscaled_opt_vals) }
    template_params = dict(unscaled_free_params.items() + get_values(fixed_params).items())

    # Now get true template, and compute LLH
    with Timer() as t:
        if template_params['theta23'] == 0.0:
            logging.info("Zero theta23, so generating no oscillations template...")
            true_template = template_maker.get_template_no_osc(template_params)
        else:
            true_template = template_maker.get_template(template_params)
    profile.info("==> elapsed time for template maker: %s sec"%t.secs)
    true_fmap = flatten_map(true_template,chan=template_params['channel'])

    # NOTE: The minus sign is present on both of these next two lines
    # to reflect the fact that the optimizer finds a minimum rather
    # than maximum.
    llh = -get_binwise_llh(fmap,true_fmap)
    llh -= sum([ get_prior_llh(opt_val,sigma,value)
                 for (opt_val,(sigma,value)) in zip(unscaled_opt_vals,priors)])

    # Save all optimizer-tested values to opt_steps_dict, to see
    # optimizer history later
    for key in names:
        opt_steps_dict[key].append(template_params[key])
    opt_steps_dict['llh'].append(llh)

    physics.debug("LLH is %.2f at: "%llh)
    for name, val in zip(names, opt_vals):
        physics.debug(" %20s = %6.4f" %(name,val))

    return llh
Beispiel #22
0
def find_max_grid(fmap,template_maker,params,grid_settings,save_steps=True,
                                                     normal_hierarchy=True):
    '''
    Finds the template (and free systematic params) that maximize
    likelihood that the data came from the chosen template of true
    params, using a brute force grid scan over the whole parameter space.

    returns a dictionary of llh data and best fit params, in the format:
      {'llh': [...],
       'param1': [...],
       'param2': [...],
       ...}
    where 'param1', 'param2', ... are the free params that are varied in the
    scan. If save_steps is False, all lists only contain the best-fit parameters
    and llh values.
    '''

    #print "NOW INSIDE find_max_grid:"
    #print "After fixing to their true values, params dict is now: "
    #for key in params.keys():
    #    try: print "  >>param: %s value: %s"%(key,str(params[key]['best']))
    #    except: continue


    # Get params dict which will be optimized (free_params) and which
    # won't be (fixed_params) but are still needed for get_template()
    fixed_params = get_fixed_params(select_hierarchy(params,normal_hierarchy))
    free_params = get_free_params(select_hierarchy(params,normal_hierarchy))

    #Obtain just the priors
    priors = get_param_priors(free_params)

    #Calculate steps for all free parameters
    calc_steps(free_params, grid_settings['steps'])

    #Build a list from all parameters that holds a list of (name, step) tuples
    steplist = [ [(name,step) for step in param['steps']] for name, param in sorted(free_params.items())]

    #Prepare to store all the steps
    steps = {key:[] for key in free_params.keys()}
    steps['llh'] = []

    #Iterate over the cartesian product
    for pos in product(*steplist):

        #Get a dict with all parameter values at this position
        #including the fixed parameters
        template_params = dict(list(pos) + get_values(fixed_params).items())

        #print "   >> NOW IN LOOP: "
        #for key in template_params.keys():
        #    try: print "  >>param: %s value: %s"%(key,str(template_params[key]['value']))
        #    except: continue

        # Now get true template
        profile.info('start template calculation')
        true_template = template_maker.get_template(template_params)
        profile.info('stop template calculation')
        true_fmap = flatten_map(true_template)

        #and calculate the likelihood
        llh = -get_binwise_llh(fmap,true_fmap)

        #get sorted vals to match with priors
        vals = [ v for k,v in sorted(pos) ]
        llh -= sum([ get_prior_llh(vals,sigma,value) for (vals,(sigma,value)) in zip(vals,priors)])

        # Save all values to steps and report
        steps['llh'].append(llh)
        physics.debug("LLH is %.2f at: "%llh)
        for key, val in pos:
            steps[key].append(val)
            physics.debug(" %20s = %6.4f" %(key, val))

    #Find best fit value
    maxllh = min(steps['llh'])
    maxpos = steps['llh'].index(maxllh)

    #Report best fit
    physics.info('Found best LLH = %.2f in %d calls at:'
                 %(maxllh,len(steps['llh'])))
    for name, vals in steps.items():
        physics.info('  %20s = %6.4f'%(name,vals[maxpos]))

        #only save this maximum if asked for
        if not save_steps:
            steps[name]=vals[maxpos]

    return steps
Beispiel #23
0
def get_fisher_matrices(template_settings, grid_settings, IMH=True, NMH=False, dump_all_stages=False,
		        save_templates=False, outdir=None):
  '''
  Main function that runs the Fisher analysis for the chosen hierarchy(ies) (inverted by default).

  Returns a dictionary of Fisher matrices, in the format:
  {'IMH': {'cscd': [...],
          'trck': [...],
          'comb': [...],
          },
  'NMH': {'cscd': [...],
          'trck': [...],
          'comb': [...],
         }
  }

  If save_templates=True and no hierarchy is given, only fiducial templates will be written out;
  if one is given, then the templates used to obtain the gradients will be written out in
  addition.
  '''
  if outdir is None and (save_templates or dump_all_stages):
    logging.info("No output directory specified. Will save templates to current working directory.")
    outdir = os.getcwd()

  profile.info("start initializing")

  # Get the parameters
  params = template_settings['params']
  bins = template_settings['binning']

  # Artifically add the hierarchy parameter to the list of parameters
  # The method get_hierarchy_gradients below will know how to deal with it
  params['hierarchy_nh'] = { "value": 1., "range": [0.,1.],
                           "fixed": False, "prior": None}
  params['hierarchy_ih'] = { "value": 0., "range": [0.,1.],
                           "fixed": False, "prior": None}

  chosen_data = []
  if IMH:
    chosen_data.append(('IMH',False))
    logging.info("Fisher matrix will be built for IMH.")
  if NMH:
    chosen_data.append(('NMH',True))
    logging.info("Fisher matrix will be built for NMH.")
  if chosen_data == []:
    # In this case, only the fiducial maps (for both hierarchies) will be written
    logging.info("No Fisher matrices will be built.")

  # There is no sense in performing any of the following steps if no Fisher matrices are to be built
  # and no templates are to be saved.
  if chosen_data!=[] or dump_all_stages or save_templates:

    # Initialise return dict to hold Fisher matrices
    fisher = { data_tag:{'cscd':[],'trck':[],'comb':[]} for data_tag, data_normal in chosen_data }

    # Get a template maker with the settings used to initialize
    template_maker = TemplateMaker(get_values(params),**bins)

    profile.info("stop initializing\n")

    # Generate fiducial templates for both hierarchies (needed for partial derivatives
    # w.r.t. hierarchy parameter)
    fiducial_maps = {}
    for hierarchy in ['NMH','IMH']:

      logging.info("Generating fiducial templates for %s."%hierarchy)

      # Get the fiducial parameter values corresponding to this hierarchy
      fiducial_params = select_hierarchy(params,normal_hierarchy=(hierarchy=='NMH'))

      # Generate fiducial maps, either all of them or only the ultimate one
      profile.info("start template calculation")
      with Timer() as t:
        fid_maps = template_maker.get_template(get_values(fiducial_params),
                                               return_stages=dump_all_stages)
      profile.info("==> elapsed time for template: %s sec"%t.secs)

      fiducial_maps[hierarchy] = fid_maps[4] if dump_all_stages else fid_maps

      # save fiducial map(s)
      # all stages
      if dump_all_stages:
        stage_names = ("0_unoscillated_flux","1_oscillated_flux","2_oscillated_counts","3_reco","4_pid")
        stage_maps = {}
        for stage in xrange(0,len(fid_maps)):
          stage_maps[stage_names[stage]] = fid_maps[stage]
        logging.info("Writing fiducial maps (all stages) for %s to %s."%(hierarchy,outdir))
        to_json(stage_maps,os.path.join(outdir,"fid_map_"+hierarchy+".json"))
      # only the final stage
      elif save_templates:
        logging.info("Writing fiducial map (final stage) for %s to %s."%(hierarchy,outdir))
        to_json(fiducial_maps[hierarchy],os.path.join(outdir,"fid_map_"+hierarchy+".json"))

    # Get_gradients and get_hierarchy_gradients will both (temporarily)
    # store the templates used to generate the gradient maps
    store_dir = outdir if save_templates else tempfile.gettempdir()

    # Calculate Fisher matrices for the user-defined cases (NHM true and/or IMH true)
    for data_tag, data_normal in chosen_data:

      logging.info("Running Fisher analysis for %s."%(data_tag))

      # The fiducial params are selected from the hierarchy case that does NOT match
      # the data, as we are varying from this model to find the 'best fit'
      fiducial_params = select_hierarchy(params,not data_normal)

      # Get the free parameters (i.e. those for which the gradients should be calculated)
      free_params = select_hierarchy(get_free_params(params),not data_normal)
      gradient_maps = {}
      for param in free_params.keys():
        # Special treatment for the hierarchy parameter
        if param=='hierarchy':
          gradient_maps[param] = get_hierarchy_gradients(data_tag,
						     fiducial_maps,
						     fiducial_params,
						     grid_settings,
						     store_dir,
						     )
        else:
          gradient_maps[param] = get_gradients(data_tag,
					   param,
                                           template_maker,
                                           fiducial_params,
                                           grid_settings,
                                           store_dir
                                           )

      logging.info("Building Fisher matrix for %s."%(data_tag))

      # Build Fisher matrices for the given hierarchy
      fisher[data_tag] = build_fisher_matrix(gradient_maps,fiducial_maps['IMH'] if data_normal else fiducial_maps['NMH'],fiducial_params)

      # If Fisher matrices exist for both channels, add the matrices to obtain the combined one.
      if len(fisher[data_tag].keys()) > 1:
        fisher[data_tag]['comb'] = FisherMatrix(matrix=np.array([f.matrix for f in fisher[data_tag].itervalues()]).sum(axis=0),
                                              parameters=gradient_maps.keys(),  #order is important here!
                                              best_fits=[fiducial_params[par]['value'] for par in gradient_maps.keys()],
                                              priors=[fiducial_params[par]['prior'] for par in gradient_maps.keys()],
                                              )
    return fisher

  else:
    logging.info("Nothing to be done.")
    return {}
Beispiel #24
0
    results[data_tag] = {}
    # 1) get "Asimov" average fidicual template:
    asimov_fmap = get_asimov_fmap(pseudo_data_template_maker,
                                  get_values(
                                      select_hierarchy(
                                          pseudo_data_settings['params'],
                                          normal_hierarchy=data_normal)),
                                  chan=channel)

    # 2) find max llh (and best fit free params) from matching pseudo data
    #    to templates.
    for hypo_tag, hypo_normal in [('hypo_NMH', True), ('hypo_IMH', False)]:

        physics.info("Finding best fit for %s under %s assumption" %
                     (data_tag, hypo_tag))
        profile.info("start optimizer")
        llh_data = find_max_llh_bfgs(asimov_fmap,
                                     template_maker,
                                     template_settings['params'],
                                     minimizer_settings,
                                     args.save_steps,
                                     normal_hierarchy=hypo_normal)
        profile.info("stop optimizer")

        #Store the LLH data
        results[data_tag][hypo_tag] = llh_data

#Assemble output dict
output = {
    'results': results,
    'template_settings': template_settings,