#NEWLINE# def plot( self , form = 'mass' , horizontal_spacing = 'uniform' , color_nodes = [ ] , colormap = 'Dark2' ) : #NEWLINE# #INDENT# '\n        Plot the level set tree as a dendrogram and return coordinates and\n        colors of the branches.\n\n        Parameters\n        ----------\n        form : {\'mass\', \'density\', \'branch-mass\'}, optional\n\n            Main form of the plot.\n\n            - \'density\': the traditional form of the LST dendrogram where the\n              vertical scale is density levels.\n\n            - \'mass\' (default): very similar to the \'density\' form, but draws\n              the dendrogram based on the mass of upper (density) level sets.\n\n            - \'branch-mass\': each node is drawn in the dendrogram so that its\n              length is proportional to its mass, *excluding* the masses of the\n              node\'s children. In this form, the lengths of the segments\n              representing the tree nodes sum to 1.\n\n        horizontal_spacing : {\'uniform\', \'proportional\'}, optional\n            Determines how much horizontal space each level set tree node is\n            given. The default of "uniform" gives each child node an equal\n            fraction of the parent node\'s horizontal space. If set to\n            \'proportional\', then horizontal space is allocated proportionally\n            to the mass of a node relative to its siblings.\n\n        color_nodes : list, optional\n            Nodes to color in the level set tree. For each node, the subtree\n            for which that node is the root is drawn with a single color.\n\n        colormap : str, optional\n            Matplotlib colormap, used only if \'color_nodes\' contains at least\n            one node index. Default is the \'Dark2\' colormap. "Qualitative"\n            colormaps are highly recommended.\n\n        Returns\n        -------\n        fig : matplotlib figure\n            Use fig.show() to view, fig.savefig() to save, etc.\n\n        node_colors : dict\n            RGBA 4-tuple\n\n        node_coords : dict\n            Coordinates of vertical line segment endpoints representing LST\n            nodes.\n\n        split_coords : dict\n            Coordinates of horizontal line segment endpoints, representing\n            splits in the level set tree. There is a horizontal line segment\n            for *each* child in a split, and the keys in the \'split_coords\'\n            dictionary indicate to which *child* the line segment belongs.\n\n        Examples\n        --------\n        >>> X = numpy.random.rand(100, 2)\n        >>> tree = debacl.construct_tree(X, k=8, prune_threshold=5)\n        >>> plot = tree.plot(form=\'density\')\n        >>> fig = plot[0]\n        >>> fig.show()\n        ' #NEWLINE# if ( not isinstance ( color_nodes , list ) ) : #NEWLINE# #INDENT# raise TypeError ( "The 'color_nodes' parameter must be a list." ) #NEWLINE# #UNINDENT# if ( not set ( color_nodes ) . issubset ( self . nodes . keys ( ) ) ) : #NEWLINE# #INDENT# raise ValueError ( ( ( ( "The 'color_nodes' parameter contains values " + 'that do not correspond to tree nodes. This ' ) + "tree's node indices are found in the first " ) + 'column of the printed tree.' ) ) #NEWLINE# #UNINDENT# gap = 0.05 #NEWLINE# min_node_width = 1.2 #NEWLINE# node_coords = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# split_coords = { #NEWLINE# #INDENT# #NEWLINE# #UNINDENT# } #NEWLINE# ix_root = _np . array ( [ k for ( k , v ) in self . nodes . iteritems ( ) if ( v . parent is None ) ] ) #NEWLINE# n_root = len ( ix_root ) #NEWLINE# census = _np . array ( [ len ( self . nodes [ x ] . members ) for x in ix_root ] , dtype = _np . float ) #NEWLINE# n = sum ( census ) #NEWLINE# seniority = _np . argsort ( census ) [ : : ( - 1 ) ] #NEWLINE# ix_root = ix_root [ seniority ] #NEWLINE# census = census [ seniority ] #NEWLINE# if ( horizontal_spacing == 'proportional' ) : #NEWLINE# #INDENT# weights = ( census / n ) #NEWLINE# intervals = _np . cumsum ( weights ) #NEWLINE# intervals = _np . insert ( intervals , 0 , 0.0 ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# intervals = _np . linspace ( 0.0 , 1.0 , ( n_root + 1 ) ) #NEWLINE# #UNINDENT# for ( i , ix ) in enumerate ( ix_root ) : #NEWLINE# #INDENT# if ( form == 'branch-mass' ) : #NEWLINE# #INDENT# branch = self . _construct_mass_map ( ix , 0.0 , ( intervals [ i ] , intervals [ ( i + 1 ) ] ) , horizontal_spacing ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# branch = self . _construct_branch_map ( ix , ( intervals [ i ] , intervals [ ( i + 1 ) ] ) , form , horizontal_spacing , sort = True ) #NEWLINE# #UNINDENT# ( branch_node_coords , branch_split_coords , _ , _ ) = branch #NEWLINE# node_coords . update ( branch_node_coords ) #NEWLINE# split_coords . update ( branch_split_coords ) #NEWLINE# #UNINDENT# node_widths = { k : max ( min_node_width , ( ( 12.0 * len ( node . members ) ) / n ) ) for ( k , node ) in self . nodes . items ( ) } #NEWLINE# primary_ticks = [ ( x [ 0 ] [ 1 ] , x [ 1 ] [ 1 ] ) for x in node_coords . values ( ) ] #NEWLINE# primary_ticks = _np . unique ( _np . array ( primary_ticks ) . flatten ( ) ) #NEWLINE# primary_labels = [ str ( round ( tick , 2 ) ) for tick in primary_ticks ] #NEWLINE# ( fig , ax ) = _plt . subplots ( ) #NEWLINE# ax . set_position ( [ 0.11 , 0.05 , 0.78 , 0.93 ] ) #NEWLINE# ax . set_xlim ( ( ( - 0.04 ) , 1.04 ) ) #NEWLINE# ax . set_xticks ( [ ] ) #NEWLINE# ax . set_xticklabels ( [ ] ) #NEWLINE# ax . yaxis . grid ( color = 'gray' ) #NEWLINE# ax . set_yticks ( primary_ticks ) #NEWLINE# ax . set_yticklabels ( primary_labels ) #NEWLINE# if ( form == 'branch-mass' ) : #NEWLINE# #INDENT# kappa_max = max ( primary_ticks ) #NEWLINE# ax . set_ylim ( ( ( ( ( - 1.0 ) * gap ) * kappa_max ) , ( 1.04 * kappa_max ) ) ) #NEWLINE# ax . set_ylabel ( 'branch mass' ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( form == 'density' ) : #NEWLINE# #INDENT# ax . set_ylabel ( 'density level' ) #NEWLINE# ymin = min ( [ v . start_level for v in self . nodes . itervalues ( ) ] ) #NEWLINE# ymax = max ( [ v . end_level for v in self . nodes . itervalues ( ) ] ) #NEWLINE# rng = ( ymax - ymin ) #NEWLINE# ax . set_ylim ( ( ymin - ( gap * rng ) ) , ( ymax + ( 0.05 * rng ) ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if ( form == 'mass' ) : #NEWLINE# #INDENT# ax . set_ylabel ( 'mass level' ) #NEWLINE# ymin = min ( [ v . start_mass for v in self . nodes . itervalues ( ) ] ) #NEWLINE# ymax = max ( [ v . end_mass for v in self . nodes . itervalues ( ) ] ) #NEWLINE# rng = ( ymax - ymin ) #NEWLINE# ax . set_ylim ( ( ymin - ( gap * rng ) ) , ( ymax + ( 0.05 * ymax ) ) ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# raise ValueError ( 'Plot form not understood' ) #NEWLINE# #UNINDENT# #UNINDENT# #UNINDENT# node_colors = { k : [ 0.0 , 0.0 , 0.0 , 1.0 ] for ( k , v ) in self . nodes . items ( ) } #NEWLINE# palette = _plt . get_cmap ( colormap ) #NEWLINE# colorset = palette ( _np . linspace ( 0 , 1 , len ( color_nodes ) ) ) #NEWLINE# for ( i , ix ) in enumerate ( color_nodes ) : #NEWLINE# #INDENT# subtree = self . _make_subtree ( ix ) #NEWLINE# for ix_sub in subtree . nodes . keys ( ) : #NEWLINE# #INDENT# node_colors [ ix_sub ] = list ( colorset [ i ] ) #NEWLINE# #UNINDENT# #UNINDENT# line_coords = [ node_coords [ c ] for c in node_coords . keys ( ) ] #NEWLINE# line_widths = [ node_widths [ c ] for c in node_coords . keys ( ) ] #NEWLINE# line_colors = [ node_colors [ c ] for c in node_coords . keys ( ) ] #NEWLINE# node_lines = _LineCollection ( line_coords , linewidths = line_widths , colors = line_colors ) #NEWLINE# ax . add_collection ( node_lines ) #NEWLINE# line_coords = [ split_coords [ c ] for c in split_coords . keys ( ) ] #NEWLINE# line_colors = [ node_colors [ c ] for c in split_coords . keys ( ) ] #NEWLINE# split_lines = _LineCollection ( line_coords , colors = line_colors ) #NEWLINE# ax . add_collection ( split_lines ) #NEWLINE# return ( fig , node_coords , line_coords , node_colors )