<s> '''<STR_LIT>''' <EOL> import sys <EOL> import os <EOL> import numpy <EOL> import hcluster <EOL> import logging <EOL> logger = logging . getLogger ( __name__ ) <EOL> logger . setLevel ( logging . DEBUG ) <EOL> class DistanceMatrixError ( Exception ) : <EOL> pass <EOL> class DistanceMatrix ( object ) : <EOL> def __init__ ( self , similarity_dict ) : <EOL> self . sim = similarity_dict <EOL> self . keys = [ ] <EOL> self . get_keys ( ) <EOL> self . calculate_distance_matrix ( ) <EOL> self . cluster_method = self . get_cluster_method ( ) <EOL> self . Z = self . cluster_method ( self . distance_matrix ) <EOL> self . node = hcluster . to_tree ( self . Z ) <EOL> self . print_node ( self . node , self . keys ) <EOL> self . image_file = None <EOL> def get_keys ( self ) : <EOL> pairs = self . sim . keys ( ) <EOL> p1 = set ( ) <EOL> p2 = set ( ) <EOL> for ( x , y ) in pairs : <EOL> p1 . add ( x ) <EOL> p2 . add ( y ) <EOL> self . keys = list ( p1 . union ( p2 ) ) <EOL> def calculate_distance_matrix ( self ) : <EOL> key_count = len ( self . keys ) <EOL> Y = numpy . zeros ( ( key_count , key_count ) ) <EOL> for i in range ( key_count ) : <EOL> Y [ i ] [ i ] = <NUM_LIT:0.0> <EOL> a = self . keys [ i ] <EOL> for j in range ( i ) : <EOL> b = self . keys [ j ] <EOL> k1 = ( a , b ) <EOL> k2 = ( b , a ) <EOL> if self . sim . get ( k1 ) : <EOL> Y [ i ] [ j ] = <NUM_LIT:1.0> - self . sim [ k1 ] <EOL> Y [ j ] [ i ] = Y [ i ] [ j ] <EOL> elif self . sim . get ( k2 ) : <EOL> Y [ j ] [ i ] = <NUM_LIT:1.0> - self . sim [ k2 ] <EOL> Y [ i ] [ j ] = Y [ j ] [ i ] <EOL> else : <EOL> logger . warning ( '<STR_LIT>' , k1 ) <EOL> logger . debug ( Y ) <EOL> self . distance_matrix = Y <EOL> def get_cluster_method ( self , algorithm = '<STR_LIT>' ) : <EOL> logger . debug ( '<STR_LIT>' , algorithm ) <EOL> if algorithm == '<STR_LIT>' : <EOL> return hcluster . average <EOL> elif algorithm == '<STR_LIT>' : <EOL> return hcluster . single <EOL> elif algorithm == '<STR_LIT>' : <EOL> return hcluster . complete <EOL> elif algorithm == '<STR_LIT>' : <EOL> return hcluster . weighted <EOL> elif algorithm == '<STR_LIT>' : <EOL> return hcluster . centroid <EOL> elif algorithm == '<STR_LIT>' : <EOL> return hcluster . median <EOL> elif algorithm == '<STR_LIT>' : <EOL> return hcluster . ward <EOL> else : <EOL> sys . exit ( '<STR_LIT>' ) <EOL> def print_node ( self , node , labels , depth = <NUM_LIT:0> ) : <EOL> prefix = '<STR_LIT:U+0020>' * depth <EOL> if node . id < len ( labels ) : <EOL> filepath = labels [ node . id ] <EOL> p = os . path . dirname ( filepath ) <EOL> crash_id = os . path . basename ( p ) <EOL> label = '<STR_LIT>' + crash_id <EOL> else : <EOL> label = '<STR_LIT>' % ( node . id , node . dist ) <EOL> print '<STR_LIT>' % ( prefix , label ) <EOL> if node . left : <EOL> self . print_node ( node . left , labels , depth + <NUM_LIT:1> ) <EOL> if node . right : <EOL> self . print_node ( node . right , labels , depth + <NUM_LIT:1> ) <EOL> def to_image ( self , filename ) : <EOL> self . image_file = filename <EOL> self . drawdendrogram ( ) <EOL> def drawdendrogram ( self ) : <EOL> try : <EOL> from PIL import Image , ImageDraw <EOL> except ImportError : <EOL> raise DistanceMatrixError ( '<STR_LIT>' ) <EOL> h = self . getheight ( self . node ) * <NUM_LIT:20> <EOL> w = <NUM_LIT> <EOL> depth = self . getdepth ( self . node ) <EOL> scaling = float ( w - <NUM_LIT> ) / depth <EOL> img = Image . new ( '<STR_LIT>' , ( w , h ) , ( <NUM_LIT:255> , <NUM_LIT:255> , <NUM_LIT:255> ) ) <EOL> draw = ImageDraw . Draw ( img ) <EOL> draw . line ( ( <NUM_LIT:0> , h / <NUM_LIT:2> , <NUM_LIT:10> , h / <NUM_LIT:2> ) , fill = ( <NUM_LIT:255> , <NUM_LIT:0> , <NUM_LIT:0> ) ) <EOL> self . drawnode ( draw , self . node , <NUM_LIT:10> , ( h / <NUM_LIT:2> ) , scaling ) <EOL> print "<STR_LIT>" % self . image_file <EOL> img . save ( self . image_file ) <EOL> def getheight ( self , clust ) : <EOL> if clust . left == None and clust . right == None : return <NUM_LIT:1> <EOL> return self . getheight ( clust . left ) + self . getheight ( clust . right ) <EOL> def getdepth ( self , clust ) : <EOL> if clust . left == None and clust . right == None : return <NUM_LIT:0> <EOL> return max ( self . getdepth ( clust . left ) , self . getdepth ( clust . right ) ) + clust . dist <EOL> def is_leaf ( self , node ) : <EOL> if node . left : return False <EOL> if node . right : return False <EOL> return True <EOL> def drawnode ( self , draw , clust , x , y , scaling ) : <EOL> if self . is_leaf ( clust ) : <EOL> draw . text ( ( x + <NUM_LIT:5> , y - <NUM_LIT:7> ) , self . _crash_id_from_path ( self . keys [ clust . id ] ) , ( <NUM_LIT:0> , <NUM_LIT:0> , <NUM_LIT:0> ) ) <EOL> else : <EOL> h1 = self . getheight ( clust . left ) * <NUM_LIT:20> <EOL> h2 = self . getheight ( clust . right ) * <NUM_LIT:20> <EOL> top = y - ( h1 + h2 ) / <NUM_LIT:2> <EOL> bottom = y + ( h1 + h2 ) / <NUM_LIT:2> <EOL> ll = clust . dist * scaling <EOL> draw . line ( ( x , top + h1 / <NUM_LIT:2> , x , bottom - h2 / <NUM_LIT:2> ) , fill = ( <NUM_LIT:255> , <NUM_LIT:0> , <NUM_LIT:0> ) ) <EOL> draw . line ( ( x , top + h1 / <NUM_LIT:2> , x + ll , top + h1 / <NUM_LIT:2> ) , fill = ( <NUM_LIT:255> , <NUM_LIT:0> , <NUM_LIT:0> ) ) <EOL> draw . line ( ( x , bottom - h2 / <NUM_LIT:2> , x + ll , bottom - h2 / <NUM_LIT:2> ) , fill = ( <NUM_LIT:255> , <NUM_LIT:0> , <NUM_LIT:0> ) ) <EOL> self . drawnode ( draw , clust . left , x + ll , top + h1 / <NUM_LIT:2> , scaling ) <EOL> self . drawnode ( draw , clust . right , x + ll , bottom - h2 / <NUM_LIT:2> , scaling ) <EOL> def _crash_id_from_path ( self , path ) : <EOL> parts = path . split ( '<STR_LIT:/>' ) <EOL> idx = parts . index ( '<STR_LIT>' ) + <NUM_LIT:1> <EOL> return parts [ idx ] </s>
