예제 #1
0
    def model_init(self, policy, kwargs):
        """
        Init of the model, The provided implementation here assumes
        that `self.model_file`  is set correctly. In case of using different
        vensim models for different policies, it is recomended to extent
        this method, extract the model file from the policy dict, set 
        `self.model_file` to this file and then call this implementation through
        calling `super`.
        
        :param policy: a dict specifying the policy. In this 
                       implementation, this argument is ignored. 
        :param kwargs: additional keyword arguments. In this implementation 
                       this argument is ignored.
        """

        load_model(self.working_directory+self.model_file) #load the model
        debug("model initialized successfully")

        be_quiet() # minimize the screens that are shown
        
        try:
            initialTime  = get_val('INITIAL TIME')
            finalTime = get_val('FINAL TIME')
            timeStep = get_val('TIME STEP')
            savePer = get_val('SAVEPER')
             
            if savePer > 0:
                timeStep = savePer
            
            self.runLength = int((finalTime - initialTime)/timeStep +1)
        except VensimWarning:
            raise EMAWarning(str(VensimWarning))
예제 #2
0
 def _store_result(self, result):
     for outcome in self.outcomes:
         debug("storing {}".format(outcome))
         
         try:
             outcome_res = result[outcome]
         except KeyError:
             ema_logging.debug("%s not in msi" % outcome)
         else:
             try:
                 self.results[outcome][self.i-1, ] = outcome_res
                 self.results[outcome].flush()
             except KeyError: 
                 data =  np.asarray(outcome_res)
                 
                 shape = data.shape
                 
                 if len(shape)>2:
                     raise EMAError(self.shape_error_msg.format(len(shape)))
                 
                 shape = list(shape)
                 shape.insert(0, self.nr_experiments)
                 shape = tuple(shape)
                 
                 fh = tempfile.TemporaryFile()
                 self.results[outcome] =  np.memmap(fh, 
                                                    dtype=data.dtype, 
                                                    shape=shape)
                 self.results[outcome][:] = np.NAN
                 self.results[outcome][self.i-1, ] = data
                 self.results[outcome].flush()
예제 #3
0
    def __init__(self, gui=False, thd=False):
        '''
        
        Create a link with netlogo. Underneath, the netlogo jvm is started
        throuhg jpype.
        
        
        :param gui: boolean, if true run netlogo with gui, otherwise run in 
                    headless mode. Defaults to false.
        :param thd: boolean, if thrue start netlogo in 3d mode. Defaults to 
                    false
        
        
        '''
        if not jpype.isJVMStarted():
            # netlogo jars
            jars = [NETLOGO_HOME + r'/lib/scala-library.jar',
                    NETLOGO_HOME + r'/lib/asm-all-3.3.1.jar',
                    NETLOGO_HOME + r'/lib/picocontainer-2.13.6.jar',
                    NETLOGO_HOME + r'/lib/log4j-1.2.16.jar',
                    NETLOGO_HOME + r'/lib/jmf-2.1.1e.jar',
                    NETLOGO_HOME + r'/lib/pegdown-1.1.0.jar',
                    NETLOGO_HOME + r'/lib/parboiled-core-1.0.2.jar',
                    NETLOGO_HOME + r'/lib/parboiled-java-1.0.2.jar',
                    NETLOGO_HOME + r'/lib/mrjadapter-1.2.jar',
                    NETLOGO_HOME + r'/lib/jhotdraw-6.0b1.jar',
                    NETLOGO_HOME + r'/lib/quaqua-7.3.4.jar',
                    NETLOGO_HOME + r'/lib/swing-layout-7.3.4.jar',
                    NETLOGO_HOME + r'/lib/jogl-1.1.1.jar',
                    NETLOGO_HOME + r'/lib/gluegen-rt-1.1.1.jar',
                    NETLOGO_HOME + r'/NetLogo.jar',
                    PYNETLOGO_HOME + r'/external_files/netlogoLink.jar']
            
            # format jars in right format for starting java virtual machine
            # TODO the use of the jre here is only relevant under windows 
            # apparently
            jars = ";".join(jars)
            jarpath = '-Djava.class.path={}'.format(jars)
            jvm_dll = NETLOGO_HOME + r'/jre/bin/client/jvm.dll'    
            
            cwd = os.getcwd()
            os.chdir(NETLOGO_HOME)
#             jpype.startJVM(jvm_dll, jarpath)
            jpype.startJVM(jpype.getDefaultJVMPath(), jarpath)
            os.chdir(cwd)
            cwd = jpype.java.lang.System.getProperty("user.dir");
            
            debug("jvm started")
        
        gui = jpype.java.lang.Boolean(gui)
        thd = jpype.java.lang.Boolean(thd)

        link = jpype.JClass('netlogoLink.NetLogoLink')
        self.link = link(gui, thd)
예제 #4
0
    def find_box(self):
        '''
        
        Execute one iteration of the PRIM algorithm. That is, find one
        box, starting from the current state of Prim. 
        
        
        '''
        # set the indices
        self._update_yi_remaining()
        
        if self.yi_remaining.shape[0] == 0:
            info("no data remaining")
            return
        
        # log how much data and how many coi are remaining
        info(self.message.format(self.yi_remaining.shape[0],
                                 self.determine_coi(self.yi_remaining)))
        
        # make a new box that contains all the remaining data points
        box = PrimBox(self, self.box_init, self.yi_remaining[:])
        
        #  perform peeling phase
        box = self._peel(box)
        debug("peeling completed")

        # perform pasting phase        
        box = self._paste(box)
        debug("pasting completed")
        
        message = "mean: {0}, mass: {1}, coverage: {2}, density: {3} restricted_dimensions: {4}"
        message = message.format(box.mean[-1],
                                 box.mass[-1],
                                 box.coverage[-1],
                                 box.density[-1],
                                 box.res_dim[-1])

        if (self.threshold_type==ABOVE) &\
           (box.mean[-1] >= self.threshold):
            info(message)
            self.boxes.append(box)
            return box
        elif (self.threshold_type==BELOW) &\
           (box.mean[-1] <= self.threshold):
            info(message)
            self.boxes.append(box)
            return box
        else:
            # make a dump box
            info('box does not meet threshold criteria, value is {}, returning dump box'.format(box.mean[-1]))
            box = PrimBox(self, self.box_init, self.yi_remaining[:])
            self.boxes.append(box)
            return box
예제 #5
0
def read_cin_file(file_name):
    '''
    read a .cin file
    
    :param file: location of the .cin file.
    :exception: raises a :class:`~EMAExceptions.VensimWarning` if the cin file
                cannot be read.
    '''
    debug("executing COMMAND: SIMULATE>READCIN|"+file_name)
    try:
        command(r"SIMULATE>READCIN|"+file_name)
    except VensimWarning as w:
        debug(str(w))
        raise w
예제 #6
0
    def _paste(self, box):
        ''' Executes the pasting phase of the PRIM. Delegates pasting to data 
        type specific helper methods.'''
        
        x = self.x[self.yi_remaining]
        
        mass_old = box.yi.shape[0]/self.n
        
        res_dim = sdutil._determine_restricted_dims(box.box_lims[-1],
                                                    self.box_init)
        
        possible_pastes = []
        for u in res_dim:
            debug("pasting "+u)
            dtype = self.x.dtype.fields.get(u)[0].name
            pastes = self._pastes[dtype](self, box, u)
            [possible_pastes.append(entry) for entry in pastes] 
        if not possible_pastes:
            # there is no peel identified, so return box
            return box
    
        # determine the scores for each peel in order
        # to identify the next candidate box
        scores = []
        for entry in possible_pastes:
            i, box_lim = entry
            obj = self.obj_func(self, self.y[box.yi],  self.y[i])
            non_res_dim = len(x.dtype.descr)-\
                          sdutil._determine_nr_restricted_dims(box_lim,
                                                              self.box_init)
            score = (obj, non_res_dim, box_lim, i)
            scores.append(score)

        scores.sort(key=itemgetter(0,1), reverse=True)
        entry = scores[0]
        box_new, indices = entry[2:]
        mass_new = self.y[indices].shape[0]/self.n
        
        mean_old = np.mean(self.y[box.yi])
        mean_new = np.mean(self.y[indices])
        
        if (mass_new >= self.mass_min) &\
           (mass_new > mass_old) &\
           (mean_old <= mean_new):
            box.update(box_new, indices)
            return self._paste(box)
        else:
            #else return received box
            return box
예제 #7
0
def load_model(file_name):
    '''
    load the model 
    
    :param file: the location of the .vpm file to be loaded.
    :exception: raises a :class:`~EMAExceptions.VensimError` if the model 
                cannot be loaded.
    
    .. note: only works for .vpm files
    
    '''
    debug("executing COMMAND: SIMULATE>SPECIAL>LOADMODEL|"+file_name)
    try:
        command(r"SPECIAL>LOADMODEL|"+file_name)
    except VensimWarning as w:
        warning(str(w))
        raise VensimError("vensim file not found")
예제 #8
0
 def model_init(self, policy, kwargs):
     '''
     Method called to initialize the model.
     
     :param policy: policy to be run.
     :param kwargs: keyword arguments to be used by model_intit. This
                    gives users to the ability to pass any additional 
                    arguments. 
     
     .. note:: This method should always be implemented. Although in simple
               cases, a simple pass can suffice. 
     '''
     self.policy = policy
     
     self.netlogo = pyNetLogo.NetLogoLink()
     debug("netlogo started")
     self.netlogo.load_model(self.working_directory+self.model_file)
     debug("model opened")
예제 #9
0
    def _first_get_population(self):
        ''' called only once to initialize some stuff, returns 
        a population. After the first call, _get_population is used instead.
        
        '''
        
        debug("Start of evolution")
        
        self.pop = self.toolbox.population(self.pop_size)
        
        # Evaluate the entire population
        self.evaluate_population(self.pop, self.reporting_interval, self.toolbox, 
                                 self.ensemble)

        # This is just to assign the crowding distance to the individuals
        tools.emo.assignCrowdingDist(self.pop)        

        self.stats_callback(self.pop)
        self.stats_callback.log_stats(self.called)
        self.get_population = self._get_population
예제 #10
0
def run_simulation(file_name):
    ''' 
    Convenient function to run a model and store the results of the run in 
    the specified .vdf file. The specified output file will be overwritten 
    by default

    :param file: the location of the outputfile
    :exception: raises a :class:`~EMAExceptions.VensimError` if running 
                the model failed in some way. 
                
    '''

    try:
        debug(" executing COMMAND: SIMULATE>RUNNAME|"+file_name+"|O")
        command("SIMULATE>RUNNAME|"+file_name+"|O")
        debug(r"MENU>RUN|o")
        command(r"MENU>RUN|o")
    except VensimWarning as w:
        warning((str(w)))
        raise VensimError(str(w))
예제 #11
0
 def __init__(self, working_directory, name):
     """interface to the model
     
     :param working_directory: working_directory for the model. 
     :param name: name of the modelInterface. The name should contain only
                  alphanumerical characters. 
     
     .. note:: Anything that is relative to `self.working_directory`
               should be specified in `model_init` and not
               in `__init__`. Otherwise, the code will not work when running
               it in parallel. The reason for this is that the working
               directory is being updated by parallelEMA to the worker's 
               separate working directory prior to calling `model_init`.
     """
     super(VensimModelStructureInterface, self).__init__(working_directory, 
                                                         name)
     self.outcomes.append(Outcome('TIME' , time=True))
     
     self.outcomes = list(self.outcomes)
     
     debug("vensim interface init completed")
예제 #12
0
    def __init__(self, gui=False, thd=False):
        '''
        
        Create a link with netlogo. Underneath, the netlogo jvm is started
        throuhg jpype.
        
        
        :param gui: boolean, if true run netlogo with gui, otherwise run in 
                    headless mode. Defaults to false.
        :param thd: boolean, if thrue start netlogo in 3d mode. Defaults to 
                    false
        
        
        '''
        if not jpype.isJVMStarted():
            # netlogo jars
            jars = [NETLOGO_HOME + r'/lib/scala-library.jar',
                    NETLOGO_HOME + r'/lib/asm-all-3.3.1.jar',
                    NETLOGO_HOME + r'/lib/picocontainer-2.13.6.jar',
                    NETLOGO_HOME + r'/lib/log4j-1.2.16.jar',
                    NETLOGO_HOME + r'/lib/jmf-2.1.1e.jar',
                    NETLOGO_HOME + r'/lib/pegdown-1.1.0.jar',
                    NETLOGO_HOME + r'/lib/parboiled-core-1.0.2.jar',
                    NETLOGO_HOME + r'/lib/parboiled-java-1.0.2.jar',
                    NETLOGO_HOME + r'/lib/mrjadapter-1.2.jar',
                    NETLOGO_HOME + r'/lib/jhotdraw-6.0b1.jar',
                    NETLOGO_HOME + r'/lib/quaqua-7.3.4.jar',
                    NETLOGO_HOME + r'/lib/swing-layout-7.3.4.jar',
                    NETLOGO_HOME + r'/lib/jogl-1.1.1.jar',
                    NETLOGO_HOME + r'/lib/gluegen-rt-1.1.1.jar',
                    NETLOGO_HOME + r'/NetLogo.jar',
                    PYNETLOGO_HOME + r'/external_files/netlogoLink.jar']
            
            # format jars in right format for starting java virtual machine
            # TODO the use of the jre here is only relevant under windows 
            # apparently
            # might be solvable by setting netlogo home user.dir

            joined_jars = jar_separator.join(jars)
            jarpath = '-Djava.class.path={}'.format(joined_jars)
            
            jvm_handle = jpype.getDefaultJVMPath() 
            jpype.startJVM(jvm_handle, jarpath, "-Xms128M","-Xmx1024m")  
            jpype.java.lang.System.setProperty('user.dir', NETLOGO_HOME)

            if sys.platform=='darwin':
                jpype.java.lang.System.setProperty("java.awt.headless", "true");            
            
            debug("jvm started")
        
        link = jpype.JClass('netlogoLink.NetLogoLink')
        debug('NetLogoLink class found')

        if sys.platform == 'darwin' and gui:
            info('on mac only headless mode is supported')
            gui=False
        
        self.link = link(gui, thd)
        debug('NetLogoLink class instantiated')
예제 #13
0
    def run_model(self, case):
        """
        Method for running an instantiated model structure. 
        
        This method should always be implemented.
        
        :param case: keyword arguments for running the model. The case is a 
                     dict with the names of the uncertainties as key, and
                     the values to which to set these uncertainties. 
        
        .. note:: This method should always be implemented.
        
        """
        for key, value in case.iteritems():
            try:
                self.netlogo.command(self.command_format.format(key, value))
            except jpype.JavaException as e:
                warning('variable {0} throws exception: {}'.format((key,
                                                                    str(e))))
            
        debug("model parameters set successfully")
          
        # finish setup and invoke run
        self.netlogo.command("setup")
        
        commands = []
        fns = {}
        for outcome in self.outcomes:
            if outcome.time:
                name = outcome.name
                fn = r'{0}{3}{1}{2}'.format(self.working_directory,
                               name,
                               ".txt",
                               os.sep)
                fns[name] = fn
                fn = '"{}"'.format(fn)
                fn = fn.replace(os.sep, '/')
                
                if self.netlogo.report('is-agentset? {}'.format(name)):
                    # if name is name of an agentset, we
                    # assume that we should count the total number of agents
                    nc = r'{2} {0} {3} {4} {1}'.format(fn,
                                                       name,
                                                       "file-open",
                                                       'file-write',
                                                       'count')
                else:
                    # it is not an agentset, so assume that it is 
                    # a reporter / global variable
                    
                    nc = r'{2} {0} {3} {1}'.format(fn,
                                                       name,
                                                       "file-open",
                                                       'file-write')

                commands.append(nc)
                

        c_start = "repeat {} [".format(self.run_length)
        c_end = "go ]"
        c_middle = " ".join(commands)
        command = " ".join((c_start, c_middle, c_end))
        self.netlogo.command(command)
        
        # after the last go, we have not done a write for the outcomes
        # so we do that now
        self.netlogo.command(c_middle)
        
        self.netlogo.command("file-close-all")
        self._handle_outcomes(fns)
예제 #14
0
    def run_model(self, case):
        """
        Method for running an instantiated model structure. 
        the provided implementation assumes that the keys in the 
        case match the variable names in the Vensim model. 
        
        If lookups are to be set specify their transformation from 
        uncertainties to lookup values in the extension of this method, 
        then call this one using super with the updated case dict.
        
        if you want to use cin_files, set the cin_file, or cin_files in
        the extension of this method to `self.cin_file`.
        
        :param case: the case to run
        
        
        .. note:: setting parameters should always be done via run_model.
                  The model is reset to its initial values automatically after
                  each run.  
        
        """
                
        if self.cin_file:
            try:
                read_cin_file(self.working_directory+self.cin_file)
            except VensimWarning as w:
                debug(str(w))
            else:
                debug("cin file read successfully")
            
        for key, value in case.items():
            set_value(key, value)
        debug("model parameters set successfully")
        
        debug("run simulation, results stored in " + self.working_directory+self.result_file)
        try:
            run_simulation(self.working_directory+self.result_file)
        except VensimError:
            raise

        results = {}
        error = False
        for output in self.outcomes:
            debug("getting data for %s" %output.name)
            result = get_data(self.working_directory+self.result_file, 
                              output.name 
                              )
            debug("successfully retrieved data for %s" %output.name)
            if not result == []:
                if result.shape[0] != self.runLength:
                    got = result.shape[0]
                    data = np.empty((self.runLength))
                    data[:] = np.NAN
                    data[0:result.shape[0]] = result
                    result = data
                    error = True

            if not output.time:
                result = [-1]
            else:
                result = result[0::self.step]
            try:
                results[output.name] = result
            except ValueError as e:
                print "what"
                raise e
        self.output = results   
        if error:
            raise CaseError("run not completed, got %s, expected %s" %
                            (got, self.runLength), case)  
class EVO(NetLogoModelStructureInterface):
    model_file = r"/ModelSebastiaanGreeven.nlogo"

    run_length = 100

    uncertainties = [
        ParameterUncertainty((1.01, 1.03), 'ExpFactor'),
        ParameterUncertainty((0.8, 1.2), 'ImpactFactor'),
        ParameterUncertainty((0, 50), 'TimeHorizonGov1'),
        ParameterUncertainty((0, 50), 'TimeHorizonGov2'),
        ParameterUncertainty((0, 50), 'TimeHorizonGov3'),
        ParameterUncertainty((0, 50), 'TimeHorizonGov4'),
        ParameterUncertainty((0, 50), 'TimeHorizonGov5'),
        ParameterUncertainty((0, 50), 'TimeHorizonInd1'),
        ParameterUncertainty((0, 50), 'TimeHorizonInd2'),
        ParameterUncertainty((0, 50), 'TimeHorizonInd3'),
        ParameterUncertainty((0, 50), 'TimeHorizonInd4'),
        ParameterUncertainty((0, 50), 'TimeHorizonInd5'),
        ParameterUncertainty((0, 1), 'DemocraticValue1'),
        ParameterUncertainty((0, 1), 'DemocraticValue2'),
        ParameterUncertainty((0, 1), 'DemocraticValue3'),
        ParameterUncertainty((0, 1), 'DemocraticValue4'),
        ParameterUncertainty((0, 1), 'DemocraticValue5'),
        ParameterUncertainty((0, 20), 'SDTimeHorizonDistribution'),
        ParameterUncertainty((0.2, 1), 'MitigationEnforcementFactor'),
        ParameterUncertainty((0.5, 1),
                             'EffectInternationalPolicyOnIndividuals'),
        ParameterUncertainty((0.5, 1),
                             'EffectInternationalPolicyOnNationalPolicy'),
        ParameterUncertainty((0.01, 0.1), 'BaseChanceOfClimateDisaster'),
        ParameterUncertainty((0, 1),
                             'EffectOfClimateChangeOnClimateDisasters'),
        ParameterUncertainty((0, 0.30), 'InitialSeverityOfClimateDisaster'),
        ParameterUncertainty((0, 0.30), 'PredictionError'),
        CategoricalUncertainty(('1', '3', '5'), 'EmissionMemory'),
        CategoricalUncertainty(('5', '10', '15'),
                               'YearsBetweenInternationalNegotiations'),
        CategoricalUncertainty(('"Cooperative"', '"Prisoners"'), 'GameTheory'),
        CategoricalUncertainty(('1', '3', '5'), 'ClimateDisasterMemory'),
        CategoricalUncertainty(('True', 'False'),
                               'ClimateDisasterIncreaseMitigation')
    ]

    outcomes = [
        Outcome('CumulativeGHGreduction', time=True),
        Outcome('AnnualGHGreduction', time=True),
        Outcome('TotalAgreementEffect', time=True),
        Outcome('BottomUpMitigationRatio', time=True),
        Outcome('TotalClimateDisasterEffect', time=True)
    ]

    nr_replications = 100

    def __init__(self, working_directory, name, defaults={}):
        super(EVO, self).__init__(working_directory, name)

        self.oois = self.outcomes[:]

        temp_outcomes = []
        for outcome in self.outcomes:
            temp_outcomes.append(Outcome(outcome.name + '_mean', time=True))
            temp_outcomes.append(Outcome(outcome.name + '_std', time=True))
        self.outcomes = temp_outcomes

        self.defaults = defaults

        unc_to_remove = self.defaults.keys()
        self.uncertainties = [
            unc for unc in self.uncertainties if unc.name not in unc_to_remove
        ]

    def run_model(self, case):

        for key, value in self.defaults.items():
            case[key] = value

        replications = defaultdict(list)

        for i in range(self.nr_replications):
            ema_logging.debug('running replication {}'.format(i))
            self._run_case(case)

            for key, value in self.output.items():
                replications[key].append(value)

        for key, value in replications.items():
            data = np.asarray(value)
            self.output[key + '_mean'] = np.mean(data, axis=0)
            self.output[key + '_std'] = np.std(data, axis=0)

    def _run_case(self, case):
        """
        Method for running an instantiated model structure. 
        
        This method should always be implemented.
        
        :param case: keyword arguments for running the model. The case is a 
                     dict with the names of the uncertainties as key, and
                     the values to which to set these uncertainties. 
        
        .. note:: This method should always be implemented.
        
        """
        for key, value in case.iteritems():
            try:
                self.netlogo.command(self.command_format.format(key, value))
            except jpype.JavaException as e:
                warning('variable {0} throws exception: {}'.format(
                    (key, str(e))))

        debug("model parameters set successfully")

        # finish setup and invoke run
        self.netlogo.command("setup")

        time_commands = []
        end_commands = []
        fns = {}
        for outcome in self.oois:
            name = outcome.name

            fn = r'{0}{3}{1}{2}'.format(self.working_directory, name, ".txt",
                                        os.sep)
            fns[name] = fn
            fn = '"{}"'.format(fn)
            fn = fn.replace(os.sep, '/')

            if self.netlogo.report('is-agentset? {}'.format(name)):
                # if name is name of an agentset, we
                # assume that we should count the total number of agents
                nc = r'{2} {0} {3} {4} {1}'.format(fn, name, "file-open",
                                                   'file-write', 'count')
            else:
                # it is not an agentset, so assume that it is
                # a reporter / global variable

                nc = r'{2} {0} {3} {1}'.format(fn, name, "file-open",
                                               'file-write')
            if outcome.time:
                time_commands.append(nc)
            else:
                end_commands.append(nc)

        c_start = "repeat {} [".format(self.run_length)
        c_close = "go ]"
        c_middle = " ".join(time_commands)
        c_end = " ".join(end_commands)
        command = " ".join((c_start, c_middle, c_close))
        debug(command)
        self.netlogo.command(command)

        # after the last go, we have not done a write for the outcomes
        # so we do that now
        self.netlogo.command(c_middle)

        # we also need to save the non time series outcomes
        self.netlogo.command(c_end)

        self.netlogo.command("file-close-all")
        self._handle_outcomes(fns)
예제 #16
0
def show_boxes_together(boxes, results, uv=[], filter=True):
    '''
    
    This functions visually shows the size of a list of prim boxes. 
    Each box has its own color. The dump box is not shown. The size of the
    boxes is normalized, where 0 is the lowest sampled value for each
    uncertainty and 1 is the highest sampled value for each uncertainty. his
    is visualized using a light grey background.
    
    :param boxes: the list of prim objects as returned by :func:`perform_prim`.
    :param results: the results as returnd by :meth:`perform_experiments`
    :param uv: the uncertainties to show in the plot. Defaults to an empty list,
               meaning all the uncertainties will be shown. If the list is not
               empty only the uncertainties specified in uv will be plotted. 
    :param filter: boolean, if True, the uncertainties for which all the boxes
                   equal the size of the dump box are not visualized 
                   (default=True)
    :rtype: a `figure <http://matplotlib.sourceforge.net/api/figure_api.html>`_ instance
    
    '''
    experiments, results = results
    boxes = [element.box for element in boxes]
    
    #determine minima and maxima
    boxes = __normalize(boxes, experiments)
    
    dump_box = boxes[-1]
    boxes = boxes[0:-1]
    
    uncertainties = sort_uncertainities(experiments, boxes[0], dump_box)
    
#    uncertainties = []
#    for entry in experiments.dtype.descr:
#        uncertainties.append(entry[0])

    if not uv:
        uv = uncertainties
    
    #plot results    
    figure = plt.figure()
    ax = figure.add_subplot(111)
    
    #iterate over uncertainties
    
    names = []
    i = -1
    for name in uncertainties:
        if name in uv:
            show_uncertainty = True
            if filter:
                show_uncertainty=False
                #determine whether to show
                for box in boxes:
                    minimum = box[name][0]
                    maximum = box[name][1]
                    value = box.dtype.fields.get(name)[0]
                    if value == 'object':
                        debug("filtering name")
                        debug(dump_box[name][0])
                        debug(minimum)
                        a = dump_box[name][0]
                        if len(minimum) == len(a):
                            ans = np.all(np.equal(a, minimum))
                        else:
                            ans = False
                        if not ans:
                            show_uncertainty = True
                            break
                    elif (minimum > dump_box[name][0]) or\
                         (maximum < dump_box[name][1]):
                        show_uncertainty = True
                        break
            if show_uncertainty:    
                i+=1
                names.append(name)
                
                #iterate over boxes
                for j, box in enumerate(boxes):
                    if value == 'object':
                        y = box[name][0]
                        x = [i+0.1*(j+1) for entry in range(len(y))]
                        ax.scatter(x,y,edgecolor=COLOR_LIST[j%len(COLOR_LIST)],
                                   facecolor=COLOR_LIST[j%len(COLOR_LIST)])
                    else:
                        ax.plot([i+0.1*(j+1), i+0.1*(j+1)], box[name][:], 
                                c=COLOR_LIST[j%len(COLOR_LIST)])

    rect = mpl.patches.Rectangle((-0.5, 0), i+1.5, 1, facecolor="#C0C0C0",
                                 alpha=0.25, edgecolor="#C0C0C0")
    ax.add_patch(rect)
    ax.set_xlim(xmin= -0.5, xmax=len(names)-0.5)
    ax.set_ylim(ymin=-0.2, ymax=1.2)
    
    ax.xaxis.set_ticks([x for x in range(len(names))])
    xtickNames = plt.setp(ax, xticklabels = names)
    plt.setp(xtickNames, rotation=90, fontsize=12)
    
    ytickNames = ax.get_yticklabels()
    plt.setp(ytickNames, rotation=90, fontsize=12)
    
    ax.set_ylabel('normalized uncertainty bandwidth', 
               rotation=90, 
               fontsize=12)     
    return figure