00001 import numpy as np
00002 import matplotlib.pyplot as pb
00003 import matplotlib.patches as patches
00004 import matplotlib.transforms as transforms
00005 import hrl_lib.util as ut
00006
00007 LIGHTBLUE = '#33CCFF'
00008 DARKBLUE = '#008AB8'
00009 LIME = '#CCFF33'
00010 GREY = '#E0E0E0'
00011
00012
00013
00014
00015 def random_color():
00016 r = '%02X'%np.random.randint(0, 255)
00017 g = '%02X'%np.random.randint(0, 255)
00018 b = '%02X'%np.random.randint(0, 255)
00019 c = '#' + r + g + b
00020 return c
00021
00022
00023
00024 class SelectRect:
00025 def __init__(self, x_start, x_end, axes_objects, color='#FFCC33', alpha=.3):
00026 self.rects = []
00027 for axes_object in axes_objects:
00028 trans = transforms.blended_transform_factory(axes_object.transData,
00029 axes_object.transAxes)
00030 rect = patches.Rectangle((x_start, 0), width=(x_end-x_start),
00031 height=1, transform=trans, color=color, alpha=alpha)
00032 axes_object.add_patch(rect)
00033 self.rects.append(rect)
00034
00035 self.x_start = x_start
00036 self.x_end = x_end
00037 self.name = None
00038
00039 def set_color(self, color):
00040 for r in self.rects:
00041 r.set_color(color)
00042
00043 def set_start(self, x):
00044 self.x_start = x
00045 for rect in self.rects:
00046 rect.set_x(self.x_start)
00047 rect.set_width(self.x_end - self.x_start)
00048
00049 def set_end(self, x):
00050 self.x_end = x
00051 for rect in self.rects:
00052 rect.set_width(self.x_end - self.x_start)
00053
00054 def get_start(self):
00055 return self.x_start
00056
00057 def get_end(self):
00058 return self.x_end
00059
00060 def set_name(self, n):
00061 self.name = n
00062
00063 def get_name(self):
00064 return self.name
00065
00066
00067
00068
00069 class TimeSeriesDisplay:
00070
00071 def __init__(self, list_of_time_series, labels, limits=None, color='b', save='segments.pkl', name="", marker=''):
00072
00073 self.figure = pb.figure()
00074 self.figure.set_facecolor('w')
00075 self.axes = []
00076
00077
00078 time_idxes = [t for t, d in list_of_time_series]
00079 min_time = np.min(np.concatenate(time_idxes))
00080 max_time = np.max(np.concatenate(time_idxes))
00081
00082 for idx, time_series in enumerate(list_of_time_series):
00083 tlist, ylist = time_series
00084
00085 axis = pb.subplot(len(list_of_time_series), 1, idx+1)
00086 print labels[idx], len(tlist), len(ylist)
00087 lines = pb.plot(tlist, ylist, marker+'-', color=color)
00088 pb.xlim(min_time, max_time)
00089 if limits != None and limits[idx] != None:
00090 ymin, ymax = limits[idx]
00091 pb.ylim(ymin, ymax)
00092 pb.ylabel(labels[idx])
00093
00094 self.axes.append(axis)
00095
00096
00097 pb.suptitle(name)
00098 self.figure.canvas.mpl_connect('button_press_event', self.button_press_handler)
00099 self.figure.canvas.mpl_connect('key_press_event', self.key_press_handler)
00100
00101 self.save_filename = save
00102 self.mode = 'EDIT'
00103 self.state = 'START'
00104 self.rects = []
00105 self.x = None
00106 self.active_idx = None
00107 self.ACTIVE_COLOR = LIME
00108 self.INACTIVE_COLOR = GREY
00109
00110 self.load_state()
00111
00112 def _set_active(self, idx):
00113 for r in self.rects:
00114 r.set_color(self.INACTIVE_COLOR)
00115
00116 self.active_idx = idx % len(self.rects)
00117 self.rects[self.active_idx].set_color(self.ACTIVE_COLOR)
00118 print 'TimeSeriesDisplay._set_active(): selected', self.rects[self.active_idx].get_name()
00119
00120 def _inactivate_current_rect(self):
00121 if self.active_idx != None:
00122 self.rects[self.active_idx].set_color(self.INACTIVE_COLOR)
00123
00124 def key_press_handler(self, event):
00125
00126 if self.mode == 'EDIT':
00127 if event.key == 'escape':
00128 self.state = 'START'
00129 self._inactivate_current_rect()
00130
00131 elif event.key == 'right':
00132 if self.active_idx != None:
00133 self._set_active(self.active_idx + 1)
00134 self.state = 'TWO_POINTS'
00135
00136 elif event.key == 'left':
00137 if self.active_idx != None:
00138 self._set_active(self.active_idx - 1)
00139 self.state = 'TWO_POINTS'
00140
00141 elif event.key == ' ':
00142 if self.active_idx != None:
00143 print 'Current name is', self.rects[self.active_idx].get_name(), '. Enter a new name:'
00144 n = raw_input()
00145 self.rects[self.active_idx].set_name(n)
00146
00147 elif event.key == 'w':
00148 if len(self.rects) > 0:
00149 self.save_state()
00150 elif event.key == 'e':
00151 if self.mode == 'EDIT':
00152 self.mode = 'INTERACT'
00153 else:
00154 self.mode = 'EDIT'
00155 print self.mode
00156
00157 self.figure.canvas.draw()
00158
00159
00160 def load_state(self):
00161 try:
00162 rects = ut.load_pickle(self.save_filename)
00163 srects = []
00164 for r in rects:
00165 start, end, name = r
00166 srect = SelectRect(start, end, self.axes)
00167 srect.set_name(name)
00168 srects.append(srect)
00169 self.rects = srects
00170 self._set_active(0)
00171 self.state = 'TWO_POINTS'
00172 self.figure.canvas.draw()
00173 except IOError, e:
00174 print 'INFO: was not able to load', self.save_filename
00175
00176 def save_state(self):
00177 segments = []
00178 for r in self.rects:
00179 segments.append([r.get_start(), r.get_end(), r.get_name()])
00180 ut.save_pickle(segments, self.save_filename)
00181 print 'saved state to', self.save_filename
00182
00183 def button_press_handler(self, event):
00184
00185
00186
00187 if self.mode == 'EDIT':
00188
00189 if event.button == 1 and event.xdata != None:
00190 if self.state == 'ONE_POINT':
00191 sm = min(self.x, event.xdata)
00192 sx = max(self.x, event.xdata)
00193 active_rect = SelectRect(sm, sx, self.axes)
00194 self.rects.append(active_rect)
00195 self._set_active(len(self.rects) - 1)
00196 self.state = 'TWO_POINTS'
00197
00198 elif self.state == 'TWO_POINTS':
00199 if event.xdata > self.rects[self.active_idx].get_end():
00200 self.rects[self.active_idx].set_end(event.xdata)
00201 elif event.xdata < self.rects[self.active_idx].get_start():
00202 self.rects[self.active_idx].set_start(event.xdata)
00203 else:
00204 dend = abs(event.xdata - self.rects[self.active_idx].get_end())
00205 dstart = abs(event.xdata - self.rects[self.active_idx].get_start())
00206 if dstart < dend:
00207 self.rects[self.active_idx].set_start(event.xdata)
00208 else:
00209 self.rects[self.active_idx].set_end(event.xdata)
00210
00211 elif event.button == 3 and event.xdata != None:
00212 if self.state == 'START':
00213 self.x = event.xdata
00214 self.state = 'ONE_POINT'
00215
00216 elif self.state == 'TWO_POINTS':
00217 self.x = event.xdata
00218 self.state = 'ONE_POINT'
00219 self._inactivate_current_rect()
00220
00221
00222 self.figure.canvas.draw()