Exemplo n.º 1
0
def marginalise(fisher_matrix, names):
    """
    This function marginalises a Fisher matrix over all parameters but the ones in names. 
    The new Fisher matrix will have the parameters specified in names, in the order specified by names.
    The calculation is performed in the numerically stable way.
        
    :param fisher_matrix: input Fisher matrix
    :type fisher_matrix: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param names: list of names of the parameters of the output Fisher matrix,
        in the order that will appear in the output Fisher matrix. All other parameters 
        will be marginalized over.
    :type names: :class:`list` of :class:`string`        
    :returns: A Fisher matrix with the marginalized parameters
    :rtype: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`    
    
    """
    # check validity of the input:
    if (not isinstance(fisher_matrix, fm.fisher_matrix)):
        raise ValueError('Error, input fisher_matrix is not a fisher_matrix')
    # check wether the names required are inside the Fisher matrix:
    for i in names:
        if not fisher_matrix.param_names_dict.has_key(i):
            raise ValueError('Error, parameter ' + str(i) +
                             ' is not in a parameter of fisher_matrix')
    # get the new latex names and fiducial:
    new_param_names_latex = []
    new_param_fiducial = []
    for i in names:
        ind = fisher_matrix.param_names_dict[i] - 1
        new_param_names_latex.append(fisher_matrix.param_names_latex[ind])
        new_param_fiducial.append(fisher_matrix.param_fiducial[ind])
    # initialize an empty matrix:
    num_param_new = len(names)
    new_matrix = np.zeros([num_param_new, num_param_new])
    # fill the new inverse matrix:
    for i in xrange(num_param_new):
        for j in xrange(num_param_new):
            # get the name:
            x = names[i]
            y = names[j]
            # get the parameter name:
            x1 = fisher_matrix.param_names_dict[x] - 1
            y1 = fisher_matrix.param_names_dict[y] - 1
            # get the entrance of the new matrix:
            new_matrix[i, j] = fisher_matrix.get_fisher_inverse()[x1, y1]

    fisher_temp = np.linalg.inv(new_matrix)
    # create the new Fisher matrix:
    fisher_new = fm.fisher_matrix(fisher_matrix=fisher_temp,
                                  param_names=names,
                                  param_names_latex=new_param_names_latex,
                                  fiducial=new_param_fiducial)
    fisher_new.name = fisher_matrix.name + '_marginal'
    fisher_new.path = fisher_matrix.path
    fisher_new.indir = fisher_matrix.indir

    return fisher_new
Exemplo n.º 2
0
def reshuffle(fisher_matrix, names):
    """
    This function reshuffles a Fisher matrix. The new Fisher matrix will have the 
    parameters specified in names, in the order specified by names.
    Can be used to delete parameters, change their order or extract the Fisher 
    for some parameters without marginalizing over the others.
        
    :param fisher_matrix: input Fisher matrix
    :type fisher_matrix: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param names: list of names of the parameters that are desired in the output Fisher 
        matrix, in the desired order.
    :type names: :class:`list` of :class:`string`        
    :returns: A Fisher matrix with the new parameters
    :rtype: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    
    """
    # check validity of the input:
    if (not isinstance(fisher_matrix, fm.fisher_matrix)):
        raise ValueError('Error, input fisher_matrix is not a fisher_matrix')
    # check wether the names required are inside the Fisher matrix:
    for i in names:
        if not fisher_matrix.param_names_dict.has_key(i):
            raise ValueError('Error, parameter ' + str(i) +
                             ' is not in a parameter of fisher_matrix')
    # get the new latex names and fiducial:
    new_param_names_latex = []
    new_param_fiducial = []
    for i in names:
        ind = fisher_matrix.param_names_dict[i] - 1
        new_param_names_latex.append(fisher_matrix.param_names_latex[ind])
        new_param_fiducial.append(fisher_matrix.param_fiducial[ind])
    # initialize an empty matrix:
    num_param_new = len(names)
    new_matrix = np.zeros([num_param_new, num_param_new])
    # fill the new matrix:
    for i in xrange(num_param_new):
        for j in xrange(num_param_new):
            # get the name:
            x = names[i]
            y = names[j]
            # get the parameter name:
            x1 = fisher_matrix.param_names_dict[x] - 1
            y1 = fisher_matrix.param_names_dict[y] - 1
            # get the entrance of the new matrix:
            new_matrix[i, j] = fisher_matrix.fisher_matrix[x1, y1]
    # create the new Fisher matrix:
    fisher_new = fm.fisher_matrix(fisher_matrix=new_matrix,
                                  param_names=names,
                                  param_names_latex=new_param_names_latex,
                                  fiducial=new_param_fiducial)
    fisher_new.name = fisher_matrix.name + '_reshuffled'
    fisher_new.path = fisher_matrix.path
    fisher_new.indir = fisher_matrix.indir

    return fisher_new
Exemplo n.º 3
0
def information_gain( fisher_1, fisher_2, fisher_prior, units=math.log(2.0), stat=True ):
    """
    This function computes the Fisher approximation of Kullback-Leibler information gain.
    For the details of the formula we refer to the CosmicFish notes.
        
    :param fisher_1: first input Fisher matrix
    :type fisher_1: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param fisher_2: second input Fisher matrix
    :type fisher_2: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param fisher_prior: input Fisher matrix with the prior information.
    :type fisher_prior: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param units: Units of information gain. Optional by default in Bits.
    :type units: :class:`float`   
    :param stat: wether to output the expected value and variance
    :type stat: :class:`logical`   
    :returns: a :class:`float` with the information gain.
    :rtype: :class:`float`   
    """
    info_gain = 0.0
    # first computations:
    F1p = fisher_1 + fisher_prior
    F2p = fisher_2 + fisher_prior
    # get common parameter names:
    param_names = [ name for name in F1p.get_param_names() if name in F2p.get_param_names() ]
    # reshuffle the second matrix:
    F1p = reshuffle( F1p, param_names )
    F2p = reshuffle( F2p, param_names )
    # define a dummy Fisher matrix with empty entrances and with the same parameters as the others:
    fisher_temp = fm.fisher_matrix( fisher_matrix=0.0*F2p.get_fisher_matrix(),
                                    param_names=F2p.get_param_names(),
                                    param_names_latex=F2p.get_param_names_latex(),
                                    fiducial=F2p.get_param_fiducial() )
    fisher_temp = fisher_2 + fisher_temp
    # the first term:
    info_gain = info_gain -math.log( F1p.determinant()/F2p.determinant() ) 
    info_gain = info_gain -F1p.get_fisher_matrix().shape[0]
    # the second trace term:
    info_gain = info_gain + np.trace( np.dot( F2p.get_fisher_inverse() , F1p.get_fisher_matrix() ) )
    # add additional term if statistical average over data is wanted
    if stat:
        # we break down the third term into two pieces:
        temp = np.dot( np.dot( np.dot( fisher_temp.get_fisher_matrix(), F2p.get_fisher_inverse() ),F1p.get_fisher_matrix() ), F2p.get_fisher_inverse() )
        temp = temp + np.dot( np.dot( temp,fisher_temp.get_fisher_matrix() ), F1p.get_fisher_inverse() )
        info_gain = info_gain + np.trace( temp )
        # compute variance:
        temp          = np.dot( temp, temp )
        info_variance = np.trace( temp )
    # output
    info_gain     = info_gain/2.0/units
    return info_gain

# ***************************************************************************************
    
Exemplo n.º 4
0
def marginalise( fisher_matrix, names ):
    """
    This function marginalises a Fisher matrix over all parameters but the ones in names. 
    The new Fisher matrix will have the parameters specified in names, in the order specified by names.
    The calculation is performed in the numerically stable way.
        
    :param fisher_matrix: input Fisher matrix
    :type fisher_matrix: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param names: list of names of the parameters of the output Fisher matrix,
        in the order that will appear in the output Fisher matrix. All other parameters 
        will be marginalized over.
    :type names: :class:`list` of :class:`string`        
    :returns: A Fisher matrix with the marginalized parameters
    :rtype: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`    
    
    """
    # check validity of the input:
    if ( not isinstance(fisher_matrix, fm.fisher_matrix) ):
            raise ValueError('Error, input fisher_matrix is not a fisher_matrix')
    # check wether the names required are inside the Fisher matrix:
    for i in names:
        if not fisher_matrix.param_names_dict.has_key(i):
            raise ValueError('Error, parameter '+str(i)+' is not in a parameter of fisher_matrix')
    # get the new latex names and fiducial:
    new_param_names_latex = []
    new_param_fiducial    = []
    for i in names:
        ind = fisher_matrix.param_names_dict[i] -1 
        new_param_names_latex.append(fisher_matrix.param_names_latex[ind])
        new_param_fiducial.append(fisher_matrix.param_fiducial[ind])
    # initialize an empty matrix:
    num_param_new = len(names)
    new_matrix = np.zeros([num_param_new,num_param_new])    
    # fill the new inverse matrix:
    for i in xrange(num_param_new):
        for j in xrange(num_param_new):
            # get the name:
            x = names[i]
            y = names[j]
            # get the parameter name:
            x1 = fisher_matrix.param_names_dict[x]-1
            y1 = fisher_matrix.param_names_dict[y]-1
            # get the entrance of the new matrix:
            new_matrix[i,j] = fisher_matrix.get_fisher_inverse()[x1,y1]
    
    fisher_temp = np.linalg.inv( new_matrix )
    # create the new Fisher matrix:
    fisher_new = fm.fisher_matrix(fisher_matrix=fisher_temp, param_names=names, param_names_latex=new_param_names_latex, fiducial=new_param_fiducial)        
    fisher_new.name  = fisher_matrix.name + '_marginal'
    fisher_new.path  = fisher_matrix.path
    fisher_new.indir = fisher_matrix.indir        
    
    return fisher_new     
Exemplo n.º 5
0
def reshuffle( fisher_matrix, names ):
    """
    This function reshuffles a Fisher matrix. The new Fisher matrix will have the 
    parameters specified in names, in the order specified by names.
    Can be used to delete parameters, change their order or extract the Fisher 
    for some parameters without marginalizing over the others.
        
    :param fisher_matrix: input Fisher matrix
    :type fisher_matrix: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param names: list of names of the parameters that are desired in the output Fisher 
        matrix, in the desired order.
    :type names: :class:`list` of :class:`string`        
    :returns: A Fisher matrix with the new parameters
    :rtype: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    
    """
    # check validity of the input:
    if ( not isinstance(fisher_matrix, fm.fisher_matrix) ):
            raise ValueError('Error, input fisher_matrix is not a fisher_matrix')
    # check wether the names required are inside the Fisher matrix:
    for i in names:
        if not fisher_matrix.param_names_dict.has_key(i):
            raise ValueError('Error, parameter '+str(i)+' is not in a parameter of fisher_matrix')
    # get the new latex names and fiducial:
    new_param_names_latex = []
    new_param_fiducial    = []
    for i in names:
        ind = fisher_matrix.param_names_dict[i] -1 
        new_param_names_latex.append(fisher_matrix.param_names_latex[ind])
        new_param_fiducial.append(fisher_matrix.param_fiducial[ind])
    # initialize an empty matrix:
    num_param_new = len(names)
    new_matrix = np.zeros([num_param_new,num_param_new])    
    # fill the new matrix:
    for i in xrange(num_param_new):
        for j in xrange(num_param_new):
            # get the name:
            x = names[i]
            y = names[j]
            # get the parameter name:
            x1 = fisher_matrix.param_names_dict[x]-1
            y1 = fisher_matrix.param_names_dict[y]-1
            # get the entrance of the new matrix:
            new_matrix[i,j] = fisher_matrix.fisher_matrix[x1,y1]
    # create the new Fisher matrix:
    fisher_new = fm.fisher_matrix(fisher_matrix=new_matrix, param_names=names, param_names_latex=new_param_names_latex, fiducial=new_param_fiducial)        
    fisher_new.name  = fisher_matrix.name + '_reshuffled'
    fisher_new.path  = fisher_matrix.path
    fisher_new.indir = fisher_matrix.indir        
    
    return fisher_new    
Exemplo n.º 6
0
def eliminate_columns_rows(fisher_matrix, indexes):
    """
    This function eliminates the row and columns corresponding to the given indexes
    from the Fisher matrix. It also deletes all the other informations like the names
    of the parameters. Notice that the index corresponding to the first parameter
    is zero.

    :param fisher_matrix: input Fisher matrix
    :type fisher_matrix: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param indexes: list of integers with the indexes to delete from the Fisher matrix
    :type indexes: :class:`list` of :class:`int`        
    :returns: A Fisher matrix with the columns and rows deleted
    :rtype: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    
    """
    # check validity of the input:
    if (not isinstance(fisher_matrix, fm.fisher_matrix)):
        raise ValueError('Error, input fisher_matrix is not a fisher_matrix')
    # write the param names:
    new_param_names = []
    new_param_names_latex = []
    new_param_fiducial = []
    for i in xrange(fisher_matrix.num_params):
        if i not in indexes:
            new_param_names.append(fisher_matrix.param_names[i])
            new_param_names_latex.append(fisher_matrix.param_names_latex[i])
            new_param_fiducial.append(fisher_matrix.param_fiducial[i])
    # write the Fisher matrix:
    fisher_temp = np.delete(np.delete(fisher_matrix.fisher_matrix, indexes, 0),
                            indexes, 1)
    # initialize the new Fisher matrix:
    fisher_new = fm.fisher_matrix(fisher_matrix=fisher_temp,
                                  param_names=new_param_names,
                                  param_names_latex=new_param_names_latex,
                                  fiducial=new_param_fiducial)
    fisher_new.name = fisher_matrix.name + '_reduced'
    fisher_new.path = fisher_matrix.path
    fisher_new.indir = fisher_matrix.indir

    return fisher_new
Exemplo n.º 7
0
def eliminate_columns_rows( fisher_matrix, indexes ):
    """
    This function eliminates the row and columns corresponding to the given indexes
    from the Fisher matrix. It also deletes all the other informations like the names
    of the parameters. Notice that the index corresponding to the first parameter
    is zero.

    :param fisher_matrix: input Fisher matrix
    :type fisher_matrix: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param indexes: list of integers with the indexes to delete from the Fisher matrix
    :type indexes: :class:`list` of :class:`int`        
    :returns: A Fisher matrix with the columns and rows deleted
    :rtype: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    
    """
    # check validity of the input:
    if ( not isinstance(fisher_matrix, fm.fisher_matrix) ):
            raise ValueError('Error, input fisher_matrix is not a fisher_matrix')
    # write the param names:
    new_param_names       = []
    new_param_names_latex = []
    new_param_fiducial    = []
    for i in xrange( fisher_matrix.num_params ):
        if i not in indexes:
            new_param_names.append( fisher_matrix.param_names[i] )
            new_param_names_latex.append( fisher_matrix.param_names_latex[i] )
            new_param_fiducial.append( fisher_matrix.param_fiducial[i] )
    # write the Fisher matrix:
    fisher_temp = np.delete ( np.delete( fisher_matrix.fisher_matrix, indexes , 0 ), indexes , 1 )
    # initialize the new Fisher matrix:
    fisher_new = fm.fisher_matrix(fisher_matrix=fisher_temp, param_names=new_param_names, param_names_latex=new_param_names_latex, fiducial=new_param_fiducial )        
    fisher_new.name  = fisher_matrix.name + '_reduced'
    fisher_new.path  = fisher_matrix.path
    fisher_new.indir = fisher_matrix.indir

    return fisher_new
Exemplo n.º 8
0
    def search_fisher_path(self, fisher_path, search_fisher_guess=False, with_derived=True ):
        """
        Searches a path for fisher matrices. 
        Will detect wether fisher_path contains directly the paths to the Fisher files or folder.
        If a list of folders is passed all the folders will be searched, first for Fisher matrices
        then for derived Fisher matrices.

        :param fisher_path: path or list of paths to search for Fisher matrices. If this contains Fisher matrices files those are imported as well.
        :type fisher_path: :class:`string` or :class:`list` of :class:`string`
        :param search_fisher_guess: wether to guess the Fisher matrix name or not. 
            Guessing assumes that the Fisher matrices have 'fisher_matrix' and '.dat' in the name as happens
            with Fisher matrices produced with CosmicFish.
        :type search_fisher_guess: :class:`bool`
        :param with_derived: wether to search for derived Fisher matrices to add to the base Fisher that are found.
        :type with_derived: :class:`bool`
        
        """
        fisher_path = copy.deepcopy( fu.make_list(fisher_path) )
        # explore all paths:
        fisher_files = []
        derived_fisher_files = []
        for path in fisher_path:
            if os.path.isfile(path):
                fisher_files.append(path)
                derived_fisher_files.append(path)
                continue
            if search_fisher_guess:
                # search for all files with fisher_matrix in the name and fisher_matrix_derived in the name
                # this is the standard cosmicfish output and should be safe if you are using cosmicfish.
                # get the file list:
                files = [ os.path.join(path, f) for f in os.listdir(path) if os.path.isfile( os.path.join(path, f) )]
                # filter the list by guessing the names to get Fisher matrices:
                for f in files:
                    f_temp = os.path.basename(f)
                    if 'fisher_matrix' in f_temp and '.dat' in f_temp and '_derived' not in f_temp:
                        fisher_files.append( f )
                # filter the list by guessing the names to get derived Fisher matrices:
                for f in files:
                    f_temp = os.path.basename(f)
                    if 'fisher_matrix' in f_temp and '_derived' in f_temp and '.dat' in f_temp:
                        derived_fisher_files.append( f )  
            else:
                # search for all the files and try to import them as fisher matrices then as derived fishers
                # get the file list:
                files = [ os.path.join(path, f) for f in os.listdir(path) if os.path.isfile( os.path.join(path, f) )]
                for f in files:
                    fisher_files.append( f )
                    derived_fisher_files.append( f ) 
                    
        # import fisher matrices:
        for file in fisher_files:
            if CosmicFishPyLib.__feedback__ > 1: print 'Trying to import: '+file+' as a Fisher matrix: ',
            try:    
                self.fisher_list.append( fm.fisher_matrix( file_name = file ))
                self.fisher_name_list.append( self.fisher_list[-1].name )
                if CosmicFishPyLib.__feedback__ > 1: print 'SUCCESS'
                if CosmicFishPyLib.__feedback__ == 1: print 'Imported as a Fisher matrix: '+file
                # remove from the derived fishers if necessary:
                derived_fisher_files.remove(file)
            except:
                if CosmicFishPyLib.__feedback__ > 1: print 'FAIL'
        # import derived fisher matrices:
        if with_derived:
            for file in derived_fisher_files:
                # get the derived matrix:
                if CosmicFishPyLib.__feedback__ > 1: print 'Trying to import: '+file+' as a derived Fisher matrix: ',
                try:    
                    fisher_derived = fd.fisher_derived( file_name = file )
                    if CosmicFishPyLib.__feedback__ > 1: print 'SUCCESS'
                except: 
                    fisher_derived = None
                    if CosmicFishPyLib.__feedback__ > 1: print 'FAIL'
                # add derived to the fisher matrix when possible:
                if fisher_derived is not None:
                    for i in xrange( len( self.fisher_name_list) ):
                        if CosmicFishPyLib.__feedback__ > 1: print 'Trying to add derived from: '+fisher_derived.name+' to the Fisher matrix: '+self.fisher_list[i].name,
                        try: 
                            self.fisher_list[i] = fisher_derived.add_derived( fisher_matrix=self.fisher_list[i], preserve_input=True )
                            self.fisher_name_list[i] = self.fisher_list[i].name 
                            if CosmicFishPyLib.__feedback__ > 1: print 'SUCCESS'
                            if CosmicFishPyLib.__feedback__ == 1: print 'Added derived parameters from: '+fisher_derived.name+' to Fisher matrix: '+self.fisher_list[i].name
                        except:
                            if CosmicFishPyLib.__feedback__ > 1: print 'FAIL'
Exemplo n.º 9
0
    def add_derived(self, fisher_matrix, preserve_input=False):
        """
        This function computes the derived fisher_matrix given an input Fisher matrix based on the Jacobian
        contained in derived_matrix.

        :param fisher_matrix: input Fisher matrix that will be used as a base for the derived Fisher matrix.
        :type fisher_matrix: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
        :param preserve_input: wether to preserve input parameters in the output Fisher. 
                Default to false because it might lead to strage results if not used properly.
        :type preserve_input: :class:`bool`        
        :return: output Fisher matrix with derived parameters. 
        :rtype: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`

        """
        # check the type of the input Fisher matrix:
        if (not isinstance(fisher_matrix, fm.fisher_matrix)):
            raise ValueError(
                'Error, input fisher_matrix is not a fisher_matrix')
        # check if the fisher matrix is compatible with the fisher_derived matrix:
        if (fisher_matrix.param_names != self.param_names):
            raise ValueError(
                'Error, paramnames of derived matrix and fisher matrix do not match'
            )
        # check wether the two fiducials are the same:
        if not np.allclose(self.param_fiducial, fisher_matrix.param_fiducial):
            raise ValueError(
                'Error, fiducial of derived matrix and fisher matrix do not match'
            )
        # create the new parameter names:
        if preserve_input:
            temp_param_names = fisher_matrix.param_names + self.derived_param_names
            temp_param_names_latex = fisher_matrix.param_names_latex + self.derived_param_names_latex
            temp_param_fiducial = np.append(fisher_matrix.param_fiducial,
                                            self.derived_param_fiducial)
        else:
            temp_param_names = self.derived_param_names
            temp_param_names_latex = self.derived_param_names_latex
            temp_param_fiducial = self.derived_param_fiducial
        # prepare the derived matrix to preserve the original prameters:
        if preserve_input:
            temp_derived_matrix = np.hstack(
                (np.identity(self.num_params), self.derived_matrix))
        else:
            temp_derived_matrix = self.derived_matrix
        # compute the derived inverse Fisher matrix:
        A = temp_derived_matrix
        AT = np.transpose(temp_derived_matrix)
        original_fisher = fisher_matrix.get_fisher_inverse()
        fisher_new_inverse = np.dot(
            np.dot(AT, fisher_matrix.get_fisher_inverse()), A)
        # get initial PCA and spectral cutoff:
        (w, v) = fisher_matrix.PCA()
        initial_cutoff = fisher_matrix.fisher_cutoff
        constrained_eigen = [i for i in w if i > 1.1 * initial_cutoff]
        initial_best_mode = 1.0 / np.amax(constrained_eigen)
        initial_worse_mode = 1.0 / np.amin(constrained_eigen)
        # get the new matrix spectrum:
        (w_new, v_new) = np.linalg.eigh(fisher_new_inverse)
        # establish the cutoff. This is chosen to leave unaltered the original eigenvalues of the Fisher matrix as much as we can.
        spectral_width = (
            np.log10(fisher_matrix.fisher_spectrum) -
            (np.log10(initial_worse_mode) - np.log10(initial_best_mode))) / 2.0
        upper_cutoff = 10.0**(np.log10(initial_worse_mode) + spectral_width)
        lower_cutoff = 10.0**(np.log10(initial_best_mode) - spectral_width)
        # check the cutoff:
        if np.amin(np.abs(w_new)) < lower_cutoff or np.amax(
                np.abs(w_new)) > upper_cutoff:
            print 'WARNING: in add_derived name:', self.name, ' fisher:', fisher_matrix.name
            print '** derived parameters are strongly degenerate and might alter the quality of the original Fisher matrix.'
            print '** Try removing degenerate parameters from the Fisher matrix and the derived matrix to get rid of this warning.'
        # apply the cutoff:
        if preserve_input:
            temp = np.zeros((self.num_params + self.num_derived,
                             self.num_params + self.num_derived), float)
        else:
            temp = np.zeros((self.num_derived, self.num_derived), float)
        for i, el in enumerate(temp):
            if w_new[i] < lower_cutoff:
                temp[i, i] = 1.0 / (lower_cutoff)
            elif np.abs(w_new[i]) > upper_cutoff:
                temp[i, i] = 1.0 / (upper_cutoff)
            else:
                temp[i, i] = 1.0 / w_new[i]
        # rebuild the Fisher matrix:
        fisher_new_inverse = np.dot(v_new, np.dot(temp, np.transpose(v_new)))
        # return the new Fisher matrix:
        fisher_matrix_new = fm.fisher_matrix(
            fisher_matrix=fisher_new_inverse,
            param_names=temp_param_names,
            param_names_latex=temp_param_names_latex,
            fiducial=temp_param_fiducial)
        fisher_matrix_new.path = fisher_matrix.path
        if preserve_input:
            fisher_matrix_new.name = fisher_matrix.name
        else:
            fisher_matrix_new.name = fisher_matrix.name + '_derived'
        fisher_matrix_new.indir = fisher_matrix.indir
        # return the new Fisher matrix with the derived parameters
        return fisher_matrix_new
Exemplo n.º 10
0
    def add_derived( self, fisher_matrix, preserve_input=False ):
        """
        This function computes the derived fisher_matrix given an input Fisher matrix based on the Jacobian
        contained in derived_matrix.

        :param fisher_matrix: input Fisher matrix that will be used as a base for the derived Fisher matrix.
        :type fisher_matrix: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
        :param preserve_input: wether to preserve input parameters in the output Fisher. 
                Default to false because it might lead to strage results if not used properly.
        :type preserve_input: :class:`bool`        
        :return: output Fisher matrix with derived parameters. 
        :rtype: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`

        """
        # check the type of the input Fisher matrix:
        if ( not isinstance(fisher_matrix, fm.fisher_matrix) ):
            raise ValueError('Error, input fisher_matrix is not a fisher_matrix')
        # check if the fisher matrix is compatible with the fisher_derived matrix:
        if ( fisher_matrix.param_names != self.param_names):
            raise ValueError('Error, paramnames of derived matrix and fisher matrix do not match')
        # check wether the two fiducials are the same:
        if not np.allclose(self.param_fiducial, fisher_matrix.param_fiducial ):
            raise ValueError('Error, fiducial of derived matrix and fisher matrix do not match')
        # create the new parameter names:
        if preserve_input:
            temp_param_names = fisher_matrix.param_names + self.derived_param_names
            temp_param_names_latex = fisher_matrix.param_names_latex + self.derived_param_names_latex
            temp_param_fiducial = np.append(fisher_matrix.param_fiducial, self.derived_param_fiducial)
        else:
            temp_param_names = self.derived_param_names
            temp_param_names_latex = self.derived_param_names_latex
            temp_param_fiducial = self.derived_param_fiducial
        # prepare the derived matrix to preserve the original prameters:
        if preserve_input:
            temp_derived_matrix = np.hstack( (np.identity( self.num_params ), self.derived_matrix) )
        else:
            temp_derived_matrix = self.derived_matrix
        # compute the derived inverse Fisher matrix:
        A = temp_derived_matrix
        AT = np.transpose( temp_derived_matrix )
        original_fisher = fisher_matrix.get_fisher_inverse()
        fisher_new_inverse = np.dot( np.dot(AT, fisher_matrix.get_fisher_inverse() ), A )
        # get initial PCA and spectral cutoff:
        (w,v)              = fisher_matrix.PCA()
        initial_cutoff     = fisher_matrix.fisher_cutoff
        constrained_eigen  = [ i for i in w if i> 1.1*initial_cutoff ]
        initial_best_mode  = 1.0/np.amax(constrained_eigen)
        initial_worse_mode = 1.0/np.amin(constrained_eigen)
        # get the new matrix spectrum:
        (w_new, v_new) = np.linalg.eigh( fisher_new_inverse )
        # establish the cutoff. This is chosen to leave unaltered the original eigenvalues of the Fisher matrix as much as we can.
        spectral_width = ( np.log10( fisher_matrix.fisher_spectrum ) -(np.log10( initial_worse_mode) - np.log10( initial_best_mode )) ) /2.0
        upper_cutoff = 10.0**(np.log10(initial_worse_mode)+spectral_width)
        lower_cutoff = 10.0**(np.log10(initial_best_mode)-spectral_width)
        # check the cutoff:
        if np.amin(np.abs(w_new))<lower_cutoff or np.amax(np.abs(w_new))>upper_cutoff:
            print 'WARNING: in add_derived name:', self.name, ' fisher:', fisher_matrix.name
            print '** derived parameters are strongly degenerate and might alter the quality of the original Fisher matrix.'
            print '** Try removing degenerate parameters from the Fisher matrix and the derived matrix to get rid of this warning.'
        # apply the cutoff:
        if preserve_input:
            temp = np.zeros((self.num_params + self.num_derived, self.num_params + self.num_derived), float)
        else:
            temp = np.zeros(( self.num_derived, self.num_derived), float)
        for i, el in enumerate(temp):
            if w_new[i] < lower_cutoff:
                temp[i,i] = 1.0/( lower_cutoff )
            elif np.abs(w_new[i]) > upper_cutoff:
                temp[i,i] = 1.0/( upper_cutoff )
            else:
                temp[i,i] = 1.0/w_new[i]
        # rebuild the Fisher matrix:
        fisher_new_inverse =  np.dot( v_new, np.dot(temp, np.transpose(v_new) ))
        # return the new Fisher matrix:
        fisher_matrix_new = fm.fisher_matrix( fisher_matrix=fisher_new_inverse, param_names=temp_param_names, param_names_latex=temp_param_names_latex, fiducial=temp_param_fiducial )
        fisher_matrix_new.path  = fisher_matrix.path
        if preserve_input:
            fisher_matrix_new.name  = fisher_matrix.name
        else:
            fisher_matrix_new.name  = fisher_matrix.name+'_derived'
        fisher_matrix_new.indir = fisher_matrix.indir
        # return the new Fisher matrix with the derived parameters
        return fisher_matrix_new
Exemplo n.º 11
0
def information_gain(fisher_1,
                     fisher_2,
                     fisher_prior,
                     units=math.log(2.0),
                     stat=True):
    """
    This function computes the Fisher approximation of Kullback-Leibler information gain.
    For the details of the formula we refer to the CosmicFish notes.
        
    :param fisher_1: first input Fisher matrix
    :type fisher_1: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param fisher_2: second input Fisher matrix
    :type fisher_2: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param fisher_prior: input Fisher matrix with the prior information.
    :type fisher_prior: :class:`cosmicfish_pylib.fisher_matrix.fisher_matrix`
    :param units: Units of information gain. Optional by default in Bits.
    :type units: :class:`float`   
    :param stat: wether to output the expected value and variance
    :type stat: :class:`logical`   
    :returns: a :class:`float` with the information gain.
    :rtype: :class:`float`   
    """
    info_gain = 0.0
    # first computations:
    F1p = fisher_1 + fisher_prior
    F2p = fisher_2 + fisher_prior
    # get common parameter names:
    param_names = [
        name for name in F1p.get_param_names()
        if name in F2p.get_param_names()
    ]
    # reshuffle the second matrix:
    F1p = reshuffle(F1p, param_names)
    F2p = reshuffle(F2p, param_names)
    # define a dummy Fisher matrix with empty entrances and with the same parameters as the others:
    fisher_temp = fm.fisher_matrix(
        fisher_matrix=0.0 * F2p.get_fisher_matrix(),
        param_names=F2p.get_param_names(),
        param_names_latex=F2p.get_param_names_latex(),
        fiducial=F2p.get_param_fiducial())
    fisher_temp = fisher_2 + fisher_temp
    # the first term:
    info_gain = info_gain - math.log(F1p.determinant() / F2p.determinant())
    info_gain = info_gain - F1p.get_fisher_matrix().shape[0]
    # the second trace term:
    info_gain = info_gain + np.trace(
        np.dot(F2p.get_fisher_inverse(), F1p.get_fisher_matrix()))
    # add additional term if statistical average over data is wanted
    if stat:
        # we break down the third term into two pieces:
        temp = np.dot(
            np.dot(
                np.dot(fisher_temp.get_fisher_matrix(),
                       F2p.get_fisher_inverse()), F1p.get_fisher_matrix()),
            F2p.get_fisher_inverse())
        temp = temp + np.dot(np.dot(temp, fisher_temp.get_fisher_matrix()),
                             F1p.get_fisher_inverse())
        info_gain = info_gain + np.trace(temp)
        # compute variance:
        temp = np.dot(temp, temp)
        info_variance = np.trace(temp)
    # output
    info_gain = info_gain / 2.0 / units
    return info_gain
Exemplo n.º 12
0
    def search_fisher_path(self,
                           fisher_path,
                           search_fisher_guess=False,
                           with_derived=True):
        """
        Searches a path for fisher matrices. 
        Will detect wether fisher_path contains directly the paths to the Fisher files or folder.
        If a list of folders is passed all the folders will be searched, first for Fisher matrices
        then for derived Fisher matrices.

        :param fisher_path: path or list of paths to search for Fisher matrices. If this contains Fisher matrices files those are imported as well.
        :type fisher_path: :class:`string` or :class:`list` of :class:`string`
        :param search_fisher_guess: wether to guess the Fisher matrix name or not. 
            Guessing assumes that the Fisher matrices have 'fisher_matrix' and '.dat' in the name as happens
            with Fisher matrices produced with CosmicFish.
        :type search_fisher_guess: :class:`bool`
        :param with_derived: wether to search for derived Fisher matrices to add to the base Fisher that are found.
        :type with_derived: :class:`bool`
        
        """
        fisher_path = copy.deepcopy(fu.make_list(fisher_path))
        # explore all paths:
        fisher_files = []
        derived_fisher_files = []
        for path in fisher_path:
            if os.path.isfile(path):
                fisher_files.append(path)
                derived_fisher_files.append(path)
                continue
            if search_fisher_guess:
                # search for all files with fisher_matrix in the name and fisher_matrix_derived in the name
                # this is the standard cosmicfish output and should be safe if you are using cosmicfish.
                # get the file list:
                files = [
                    os.path.join(path, f) for f in os.listdir(path)
                    if os.path.isfile(os.path.join(path, f))
                ]
                # filter the list by guessing the names to get Fisher matrices:
                for f in files:
                    f_temp = os.path.basename(f)
                    if 'fisher_matrix' in f_temp and '.dat' in f_temp and '_derived' not in f_temp:
                        fisher_files.append(f)
                # filter the list by guessing the names to get derived Fisher matrices:
                for f in files:
                    f_temp = os.path.basename(f)
                    if 'fisher_matrix' in f_temp and '_derived' in f_temp and '.dat' in f_temp:
                        derived_fisher_files.append(f)
            else:
                # search for all the files and try to import them as fisher matrices then as derived fishers
                # get the file list:
                files = [
                    os.path.join(path, f) for f in os.listdir(path)
                    if os.path.isfile(os.path.join(path, f))
                ]
                for f in files:
                    fisher_files.append(f)
                    derived_fisher_files.append(f)

        # import fisher matrices:
        for file in fisher_files:
            if CosmicFishPyLib.__feedback__ > 1:
                print 'Trying to import: ' + file + ' as a Fisher matrix: ',
            try:
                self.fisher_list.append(fm.fisher_matrix(file_name=file))
                self.fisher_name_list.append(self.fisher_list[-1].name)
                if CosmicFishPyLib.__feedback__ > 1: print 'SUCCESS'
                if CosmicFishPyLib.__feedback__ == 1:
                    print 'Imported as a Fisher matrix: ' + file
                # remove from the derived fishers if necessary:
                derived_fisher_files.remove(file)
            except:
                if CosmicFishPyLib.__feedback__ > 1: print 'FAIL'
        # import derived fisher matrices:
        if with_derived:
            for file in derived_fisher_files:
                # get the derived matrix:
                if CosmicFishPyLib.__feedback__ > 1:
                    print 'Trying to import: ' + file + ' as a derived Fisher matrix: ',
                try:
                    fisher_derived = fd.fisher_derived(file_name=file)
                    if CosmicFishPyLib.__feedback__ > 1: print 'SUCCESS'
                except:
                    fisher_derived = None
                    if CosmicFishPyLib.__feedback__ > 1: print 'FAIL'
                # add derived to the fisher matrix when possible:
                if fisher_derived is not None:
                    for i in xrange(len(self.fisher_name_list)):
                        if CosmicFishPyLib.__feedback__ > 1:
                            print 'Trying to add derived from: ' + fisher_derived.name + ' to the Fisher matrix: ' + self.fisher_list[
                                i].name,
                        try:
                            self.fisher_list[i] = fisher_derived.add_derived(
                                fisher_matrix=self.fisher_list[i],
                                preserve_input=True)
                            self.fisher_name_list[i] = self.fisher_list[i].name
                            if CosmicFishPyLib.__feedback__ > 1:
                                print 'SUCCESS'
                            if CosmicFishPyLib.__feedback__ == 1:
                                print 'Added derived parameters from: ' + fisher_derived.name + ' to Fisher matrix: ' + self.fisher_list[
                                    i].name
                        except:
                            if CosmicFishPyLib.__feedback__ > 1: print 'FAIL'