1#=========================================================================== 2# 3# StrConverter 4# 5#=========================================================================== 6 7 8"""StrConverter module containing class StrConverter.""" 9 10#=========================================================================== 11# Place all imports after here. 12# 13from __future__ import (absolute_import, division, print_function, 14 unicode_literals) 15 16import six 17from six.moves import xrange 18 19import matplotlib.units as units 20from matplotlib.cbook import iterable 21 22# Place all imports before here. 23#=========================================================================== 24 25__all__ = [ 'StrConverter' ] 26 27#=========================================================================== 28class StrConverter( units.ConversionInterface ): 29 """: A matplotlib converter class. Provides matplotlib conversion 30 functionality for string data values. 31 32 Valid units for string are: 33 - 'indexed' : Values are indexed as they are specified for plotting. 34 - 'sorted' : Values are sorted alphanumerically. 35 - 'inverted' : Values are inverted so that the first value is on top. 36 - 'sorted-inverted' : A combination of 'sorted' and 'inverted' 37 """ 38 39 #------------------------------------------------------------------------ 40 @staticmethod 41 def axisinfo( unit, axis ): 42 """: Returns information on how to handle an axis that has string data. 43 44 = INPUT VARIABLES 45 - axis The axis using this converter. 46 - unit The units to use for a axis with string data. 47 48 = RETURN VALUE 49 - Returns a matplotlib AxisInfo data structure that contains 50 minor/major formatters, major/minor locators, and default 51 label information. 52 """ 53 54 return None 55 56 #------------------------------------------------------------------------ 57 @staticmethod 58 def convert( value, unit, axis ): 59 """: Convert value using unit to a float. If value is a sequence, return 60 the converted sequence. 61 62 = INPUT VARIABLES 63 - axis The axis using this converter. 64 - value The value or list of values that need to be converted. 65 - unit The units to use for a axis with Epoch data. 66 67 = RETURN VALUE 68 - Returns the value parameter converted to floats. 69 """ 70 71 if ( units.ConversionInterface.is_numlike( value ) ): 72 return value 73 74 if ( value == [] ): 75 return [] 76 77 # we delay loading to make matplotlib happy 78 ax = axis.axes 79 if axis is ax.get_xaxis(): 80 isXAxis = True 81 else: 82 isXAxis = False 83 84 axis.get_major_ticks() 85 ticks = axis.get_ticklocs() 86 labels = axis.get_ticklabels() 87 88 labels = [ l.get_text() for l in labels if l.get_text() ] 89 90 if ( not labels ): 91 ticks = [] 92 labels = [] 93 94 95 if ( not iterable( value ) ): 96 value = [ value ] 97 98 newValues = [] 99 for v in value: 100 if ( (v not in labels) and (v not in newValues) ): 101 newValues.append( v ) 102 103 for v in newValues: 104 if ( labels ): 105 labels.append( v ) 106 else: 107 labels = [ v ] 108 109 #DISABLED: This is disabled because matplotlib bar plots do not 110 #DISABLED: recalculate the unit conversion of the data values 111 #DISABLED: this is due to design and is not really a bug. 112 #DISABLED: If this gets changed, then we can activate the following 113 #DISABLED: block of code. Note that this works for line plots. 114 #DISABLED if ( unit ): 115 #DISABLED if ( unit.find( "sorted" ) > -1 ): 116 #DISABLED labels.sort() 117 #DISABLED if ( unit.find( "inverted" ) > -1 ): 118 #DISABLED labels = labels[ ::-1 ] 119 120 # add padding (so they do not appear on the axes themselves) 121 labels = [ '' ] + labels + [ '' ] 122 ticks = list(xrange( len(labels) )) 123 ticks[0] = 0.5 124 ticks[-1] = ticks[-1] - 0.5 125 126 axis.set_ticks( ticks ) 127 axis.set_ticklabels( labels ) 128 # we have to do the following lines to make ax.autoscale_view work 129 loc = axis.get_major_locator() 130 loc.set_bounds( ticks[0], ticks[-1] ) 131 132 if ( isXAxis ): 133 ax.set_xlim( ticks[0], ticks[-1] ) 134 else: 135 ax.set_ylim( ticks[0], ticks[-1] ) 136 137 result = [] 138 for v in value: 139 # If v is not in labels then something went wrong with adding new 140 # labels to the list of old labels. 141 errmsg = "This is due to a logic error in the StrConverter class. " 142 errmsg += "Please report this error and its message in bugzilla." 143 assert ( v in labels ), errmsg 144 result.append( ticks[ labels.index(v) ] ) 145 146 ax.viewLim.ignore(-1) 147 return result 148 149 #------------------------------------------------------------------------ 150 @staticmethod 151 def default_units( value, axis ): 152 """: Return the default unit for value, or None. 153 154 = INPUT VARIABLES 155 - axis The axis using this converter. 156 - value The value or list of values that need units. 157 158 = RETURN VALUE 159 - Returns the default units to use for value. 160 Return the default unit for value, or None. 161 """ 162 163 # The default behavior for string indexing. 164 return "indexed" 165