def __call__(self, data ):

        if self.nlevels == None: raise NotImplementedError("incomplete implementation of %s" % str(self))

        labels = DataTree.getPaths( data )        
        debug( "transform: started with paths: %s" % labels)
        assert len(labels) >= self.nlevels, "expected at least %i levels - got %i" % (self.nlevels, len(labels))
        
        paths = list(itertools.product( *labels[:-self.nlevels] ))
        for path in paths:
            work = DataTree.getLeaf( data, path )
            if not work: continue
            new_data = self.transform( work, path )
            if new_data:
                if path:
                    DataTree.setLeaf( data, path, new_data )
                else:
                    # set new root
                    data = new_data
            else:
                warn( "no data at %s - removing branch" % str(path))
                DataTree.removeLeaf( data, path )

        debug( "transform: finished with paths: %s" % DataTree.getPaths( data ))

        return data
    def __call__(self, data, path ):
        '''iterate over leaves/branches in data structure.

        This method will call the :meth:`render` method for 
        each leaf/branch at level :attr:`nlevels`.
        '''
        if self.nlevels == None: raise NotImplementedError("incomplete implementation of %s" % str(self))

        result = ResultBlocks( title = path2str(path) )

        labels = DataTree.getPaths( data )
        if len(labels) < self.nlevels:
            self.warn( "at %s: expected at least %i levels - got %i: %s" %\
                           (str(path), self.nlevels, len(labels), str(labels)) )
            result.append( EmptyResultBlock( title = path2str(path) ) )
            return result

        paths = list(itertools.product( *labels[:-self.nlevels] ))

        for p in paths:
            work = DataTree.getLeaf( data, p )
            if not work: continue
            try:
                result.extend( self.render( work, path + p ) )
            except:
                self.warn("exeception raised in rendering for path: %s" % str(path+p))
                raise 
            
        return result
    def transform(self,data,path):

        from rpy2.robjects import r as R

        paths, lengths, values = [],[],[]

        labels = DataTree.getPaths(data)
        paths = list(itertools.product( *labels[:-1]))

        for path in paths:
            
            work = DataTree.getLeaf(data, path)
            try:
                lengths.append(len(work[self.pval]))
                values.extend(work[self.pval])

            except TypeError:
                lengths.append(0)
                values.append(work[self.pval])
            
        padj = R["p.adjust"](values, method = self.method)

        padj = [x for x in padj]
    
        for path in paths:

            num = lengths.pop(0)
            
            if num > 0:
                new_values = padj[0:num]
                padj = padj[num:]
            else:
                new_values = padj[0]
                padj = padj[1:]

        
            if path:
                work = odict(DataTree.getLeaf(data,path))
                work["P-adjust"] = new_values
                DataTree.setLeaf(data,path,work)
            else:
                data["P-adjust"] = new_values


        return data
    def render(self):
        """supply the :class:`Renderer.Renderer` with the data to render. 
        
        The data supplied will depend on the ``groupby`` option.

        return resultblocks
        """
        self.debug("%s: rendering data started for %i items" % (self, len(self.data)))

        results = ResultBlocks(title="main")

        # get number of levels required by renderer
        try:
            renderer_nlevels = self.renderer.nlevels
        except AttributeError:
            renderer_nlevels = 0

        data_paths = DataTree.getPaths(self.data)
        nlevels = len(data_paths)

        group_level = self.group_level

        self.debug(
            "%s: rendering data started. levels=%i, required levels>=%i, group_level=%i, data_paths=%s"
            % (self, nlevels, renderer_nlevels, group_level, str(data_paths)[:100])
        )

        if nlevels < renderer_nlevels:
            # add some dummy levels if levels is not enough
            d = self.data
            for x in range(renderer_nlevels - nlevels):
                d = odict((("all", d),))
            results.append(self.renderer(d, path=("all",)))

        elif group_level < 0 or renderer_nlevels < 0:
            # no grouping
            results.append(self.renderer(self.data, path=()))
        else:
            # group at level group_level
            paths = list(itertools.product(*data_paths[: group_level + 1]))
            for path in paths:
                work = DataTree.getLeaf(self.data, path)
                if not work:
                    continue
                try:
                    results.append(self.renderer(work, path=path))
                except:
                    results.append(ResultBlocks(Utils.buildException("rendering")))

        if len(results) == 0:
            self.warn("tracker returned no data.")
            raise ValueError("tracker returned no data.")

        self.debug("%s: rendering data finished with %i blocks" % (self.tracker, len(results)))

        return results
    def prune(self):
        """prune data tree.

        Remove all empty leaves.

        Remove all levels from the data tree that are
        superfluous, i.e. levels that contain only a single label
        all labels in the hierarchy below are the same.
       
        Ignore both the first and last level for this analyis.
        """

        # remove all empty leaves
        DataTree.removeEmptyLeaves(self.data)

        # prune superfluous levels
        data_paths = DataTree.getPaths(self.data)
        nlevels = len(data_paths)

        # get number of levels required by renderer
        try:
            renderer_nlevels = self.renderer.nlevels
        except AttributeError:
            renderer_nlevels = 0

        # do not prune for renderers that want all data
        if renderer_nlevels < 0:
            return

        levels_to_prune = []

        for level in range(1, nlevels - 1):

            # check for single label in level
            if len(data_paths[level]) == 1:
                label = data_paths[level][0]
                prefixes = DataTree.getPrefixes(self.data, level)
                keep = False
                for prefix in prefixes:
                    leaves = DataTree.getLeaf(self.data, prefix)
                    if len(leaves) > 1 or label not in leaves:
                        keep = True
                        break
                if not keep:
                    levels_to_prune.append((level, label))

        levels_to_prune.reverse()

        # only prune to the minimum of levels required by renderer at most
        # levels_to_prune = levels_to_prune[:nlevels - renderer_nlevels]
        for level, label in levels_to_prune:
            self.debug("pruning level %i from data tree: label='%s'" % (level, label))
            DataTree.removeLevel(self.data, level)