Source code for pygeostat.statistics.postsim

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
A postsim style utility
"""
#-----------------------------------------------------------------------------
# Boilerplate
#-----------------------------------------------------------------------------

#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
import pandas as pd
import numpy as np

from ..data import DataFile
from ..data import iotools as iotools

[docs] def postsim_multfiles(file_base_or_list, output_name, Nr=None, file_ending=None, fltype=None, output_fltype=None, zero_padding=0, variables=None, var_min=None): '''The multiple file postsim function uses recursive statistics for memory management and coolness factor. See http://people.revoledu.com/kardi/tutorial/RecursiveStatistic/ This function will take multiple realizations and post process the results into mean and variance for each variable. You can either pass it a list of files to iterate through or a filebase name and the number of realizations. Parameters: file_base_or_list (list) or (str): List of files or path + base name of sequentially named files output_name (str): ath (or name) of file to write output to. Nr (int): Number of realizations. Needed if file base name is passed. file_ending (str): file ending (ex. `"out"`). Used if file base name is passed. Period is not included. fltype (str): Type of data file: either ``csv``, ``gslib``, ``hdf5``, or ``gsb``. Used if file base name is passed and `file_ending` is not used. output_fltype (str): Type of output data file: either ``csv``, ``gslib``, ``hdf5``, or ``gsb``. zero_padding (int): Number of zeros to padd number in sequentially named files with. Default is 0. variables (str): List of variables to process. var_min (list) or (float): Minimum trimming limit to use. If one value is passed it will apply the trimming limit to all variables. Or a list of trimming limit for each variable can be passed. ''' if isinstance(file_base_or_list, list): N = 0 for filename in file_base_or_list: N += 1 dt = DataFile(flname=filename) # Create the post sim file in the first call if N == 1: # setup index length and variables blk_count = len(dt.data) if variables: if variables not in dt.data.columns.tolist(): raise KeyError('Variables passed do not match columns in datafile') else: variables = dt.data.columns.tolist() columns = list() for var in variables: columns.append(var + '_mean') columns.append(var + '_variance') columns.append('Nr') # create pandas file postsim = pd.DataFrame(index=np.arange(blk_count), columns=columns) # Set nan values if var_min: if isinstance(var_min, list): if len(var_min) != len(variables): raise KeyError('length of var_min list does not equal number of' ' variables being processed') else: trim_dict = dict(zip(variables, var_min)) for var in variables: dt.data.setnan(variables=var, tmin=trim_dict[var]) elif isinstance(var_min, (int, float)): dt.data.setnan(variables=variables, tmin=var_min) else: raise KeyError('var_min must be either a list or a number') # Initialize the first loop postsim.Nr = N for var in variables: col_m = var + '_mean' col_v = var + '_variance' postsim[col_m] = dt.data[var] postsim[col_v] = 0 continue # ----Continue with next files---- # Set nan values if var_min: if isinstance(var_min, list): if len(var_min) != len(variables): raise KeyError('length of var_min list does not equal number of' ' variables being processed') else: trim_dict = dict(zip(variables, var_min)) for var in variables: dt.data.setnan(variables=var, tmin=trim_dict[var]) elif isinstance(var_min, (int, float)): dt.data.setnan(variables=variables, tmin=var_min) else: raise KeyError('var_min must be either a list or a number') # calculate the stats postsim.Nr = N for var in variables: col_m = var + '_mean' col_v = var + '_variance' # Calculate the arithmetic average postsim.left_arg = ((N - 1) / N) * postsim[col_m] postsim.right_arg = (1 / N) * dt.data[var] postsim[col_m] = postsim.left_arg + postsim.right_arg # Calculate the variance postsim.left_arg = ((N - 1) / N) * postsim[col_v] postsim.temp = dt.data[var] postsim.right_arg = postsim.temp - postsim[col_m] postsim[col_v] = (postsim.left_arg + (1 / (N - 1)) * postsim.right_arg * postsim.right_arg) elif isinstance(file_base_or_list, str): for N in range(1, Nr + 1): # Create the post sim file in the first call if N == 1: if file_ending is None: if fltype.lower() == 'gslib': file_ending = 'out' elif fltype.lower() == 'csv': file_ending = 'csv' elif fltype.lower() == 'gsb': file_ending = 'gsb' elif fltype.lower() == 'h5' or fltype.lower() == 'hdf5': file_ending = 'h5' else: raise KeyError('Either file_ending or fltype is needed') filename = '{base}{number}.{ending}'.format(base=file_base_or_list, number=str(N).zfill(zero_padding), ending=file_ending) dt = DataFile(flname=filename) # Figure out the index (variable names... and total number of blocks) blk_count = len(dt.data) if variables: if variables not in dt.data.columns.tolist(): raise KeyError('Variables passed do not match columns in datafile') else: variables = dt.data.columns.tolist() columns = list() for var in variables: columns.append(var + '_mean') columns.append(var + '_variance') columns.append('Nr') columns.append('left_arg') columns.append('right_arg') columns.append('temp') # create pandas dataframe postsim = pd.DataFrame(index=np.arange(blk_count), columns=columns) # Set nan values if var_min: if isinstance(var_min, list): if len(var_min) != len(variables): raise KeyError('length of var_min list does not equal number of' ' variables being processed') else: trim_dict = dict(zip(variables, var_min)) for var in variables: dt.data.setnan(variables=var, tmin=trim_dict[var]) elif isinstance(var_min, (int, float)): dt.data.setnan(variables=variables, tmin=var_min) else: raise KeyError('var_min must be either a list or a number') # Initialize the first loop postsim.Nr = N for var in variables: col_m = var + '_mean' col_v = var + '_variance' postsim[col_m] = dt.data[var] postsim[col_v] = 0 continue # ----Continue with next files---- # open the next file filename = '{base}{number}.{ending}'.format(base=file_base_or_list, number=str(N).zfill(zero_padding), ending=file_ending) dt = DataFile(flname=filename) # Set nan values if var_min: if isinstance(var_min, list): if len(var_min) != len(variables): raise KeyError('length of var_min list does not equal number of' ' variables being processed') else: trim_dict = dict(zip(variables, var_min)) for var in variables: dt.data.setnan(variables=var, tmin=trim_dict[var]) elif isinstance(var_min, (int, float)): dt.data.setnan(variables=variables, tmin=var_min) else: raise KeyError('var_min must be either a list or a number') # calculate the stats postsim.Nr = N for var in variables: col_m = var + '_mean' col_v = var + '_variance' # Calculate the arithmetic average postsim.left_arg = ((N - 1) / N) * postsim[col_m] postsim.right_arg = (1 / N) * dt.data[var] postsim[col_m] = postsim.left_arg + postsim.right_arg # Calculate the variance postsim.left_arg = ((N - 1) / N) * postsim[col_v] postsim.temp = dt.data[var] postsim.right_arg = postsim.temp - postsim[col_m] postsim[col_v] = (postsim.left_arg + (1 / (N - 1)) * postsim.right_arg * postsim.right_arg) else: raise TypeError('file_base_or_list must be either a list or a string') # Write out the results columns.remove('left_arg') columns.remove('right_arg') columns.remove('temp') if output_fltype is None: if fltype: output_fltype = fltype elif file_ending == '.out': output_fltype = 'gslib' elif file_ending == 'csv' or file_ending == 'gsb' or file_ending == 'h5': output_fltype = file_ending else: raise KeyError('Unable to figure out what output_fltype needs to be. Please pass' ' a value') if output_fltype.lower() == 'gslib': iotools.write_gslib(postsim, output_name, variables=columns) elif output_fltype.lower() == 'csv': iotools.write_csv(postsim, output_name, variables=columns) elif output_fltype.lower() == 'gsb': iotools.write_gsb(postsim, output_name, tvar='Nr', variables=columns) elif output_fltype.lower() == 'h5' or fltype.lower() == 'hdf5': iotools.write_h5(postsim, output_name, variables=columns) else: raise NotImplementedError('output_fltype did not match any of the implemented filetypes')