Source code for catmap.mappers.mapper_base

"""Class for `mapping' equilibrium coverages and rates through
descriptor space. This class acts as a base class to be inherited
by other mapper classes, but is not functional on its own.

get_rxn_parameter_map(descriptor_ranges,resolution): Uses a
    scaler object to determine the reaction parameters as a function of
    descriptor space. May be useful for debugging or providing
    intuition about rate determining steps. Should return a list of
    the form
[[descriptor_1,descriptor_2,...],[rxn_parameter1, rxn_parameter2, ...]]

save_map(map,map_file): creates a pickle of the "map" list and dumps it
    to the map_file

load_map(map_file):  loads a "map" list by loading a pickle from
    the map_file

A functional derived mapper class must also contain the methods:

get_coverage_map(descriptor_ranges,resolution): a function which
    returns a list of the form
    [[descriptor_1,descriptor_2,...], [cvg_ads1,cvg_ads2,...]]

get_rates_map(descriptor_ranges,resolution): a function which returns
    a list of the form
    [[descriptor_1,descriptor_2,...], [rate_rxn1,rate_rxn2,...]]

"""
from matplotlib.mlab import griddata
import numpy as np
import mpmath as mp
import cPickle as pickle
import os
from copy import copy
from catmap.model import ReactionModel
from catmap import ReactionModelWrapper
from catmap import plt

[docs]class MapperBase(ReactionModelWrapper): # XXX : Having an instantiated object as default parameter # may have side-effects since every instance of MapperBase will have # the identical instance of ReactionModel as its attribute # Unless this is deliberately so, one should better use e.g. None # as the default value and then instantiate ReactionModel in the # function body of __init__ .
[docs] def __init__(self,reaction_model=ReactionModel()): self._rxm = reaction_model self._solver_output = ['coverage','rate', #outputs requiring solver 'turnover_frequency','selectivity','rate_control', 'noninteracting_coverages']
[docs] def get_point_output(self,descriptors,*args,**kwargs): self.solver.compile() self._output_variables = [v for v in self.output_variables] self._descriptors = descriptors params = self.scaler.get_rxn_parameters(descriptors) self._params = params if True in [v in self._solver_output for v in self.output_variables]: if 'coverage' not in self._output_variables: self._output_variables = ['coverage'] + self._output_variables elif self._output_variables[0] != 'coverage': self._output_variables.remove('coverage') self._output_variables = ['coverage'] + self._output_variables self.output_labels['coverage'] = self.adsorbate_names self.output_labels['rate'] = self.elementary_rxns # Need coverages for solver vars for out in self._output_variables: if getattr(self,'get_point_'+out): val = getattr(self,'get_point_'+out)(descriptors,*args,**kwargs) setattr(self,'_'+out,val) self.solver.set_output_attrs(params) self.scaler.set_output_attrs(descriptors) for out in self.output_variables: mapp = getattr(self,'_'+out+'_temp',{}) mapp[repr(descriptors)] = getattr(self,'_'+out) setattr(self,'_'+out+'_temp',mapp)
[docs] def get_output_map(self,descriptor_ranges,resolution,*args,**kwargs): self.solver.compile() self._output_variables = [v for v in self.output_variables] if True in [v in self._solver_output for v in self.output_variables]: #determines whether or not solver is needed if 'coverage' not in self._output_variables: self._output_variables = ['coverage'] + self._output_variables self._coverage_map = None elif self._output_variables[0] != 'coverage': self._output_variables.remove('coverage') self._output_variables = ['coverage'] + self._output_variables # Need coverages for solver vars ismapped = False for out in self._output_variables: if getattr(self,'get_'+out+'_map'): val = getattr(self,'get_'+out+'_map')( descriptor_ranges,resolution,*args,**kwargs) setattr(self,out+'_map',val) ismapped = True if ismapped == False: d1Vals, d2Vals = self.process_resolution() for d1V in d1Vals: for d2V in d2Vals: self._descriptors = [d1V,d2V] self.get_point_output(self._descriptors) for out in self.output_variables: # if getattr(self,out+'_map'): # mapp = getattr(self,out+'_map') # else: map_dict = getattr(self,'_'+out+'_temp',[]) mapp = [] for key in map_dict: mapp.append([eval(key),map_dict[key]]) setattr(self,out+'_map',mapp) if getattr(self,out+'_map_file'): outfile = getattr(self,out+'_map_file') self.save_map(mapp,outfile)
[docs] def process_resolution(self, descriptor_ranges = None, resolution = None): if not descriptor_ranges: descriptor_ranges = self.descriptor_ranges if resolution is None: resolution = self.resolution resolution = np.array(resolution) if resolution.size == 1: resx = resy = float(resolution) elif resolution.size ==2: resx = resolution[0] resy = resolution[1] else: raise ValueError('Resolution is not the correct shape') d1min, d1max = descriptor_ranges[0] d2min, d2max = descriptor_ranges[1] d1Vals = np.linspace(d1min, d1max, resx) d2Vals = np.linspace(d2min, d2max, resy) return d1Vals, d2Vals