def label(self, task_id, img_file_list, boundingbox):
     LOG.debug('label function called! labeling following files:')
     LOG.debug(img_file_list)
     cache_manager = cachemanagement.cacheManager()
     cur_dir =os.path.dirname(os.path.realpath(__file__))
     # task_id is needed for separating labeling multiple objects
     cache_dir = os.path.dirname(os.path.realpath(__file__)) + '/tmp/s3/'
     cache_dir, img_file_list = cache_manager.cacheImageFromFileList(img_file_list, cache_dir)
     img_file_list = map(lambda x: cache_dir+'/'+x, img_file_list)
     input_img_file = cache_dir+'/'+ str(task_id) +'labeler_input_img_list.txt'
     MyUtils.writeListToFile(img_file_list, input_img_file)
     output_bx_file = cache_dir +'/'+ str(task_id) + 'labeler_output_bx_list.txt'
     cmd = cur_dir+'/TrackingApp '
     cmd += str(input_img_file) + ' '
     cmd += str(output_bx_file) + ' '
     for bx_vec in boundingbox:
         cmd += str(bx_vec) + ' '
     cmd += 'BOOSTING'
     # call tracker
     os.system(cmd)
     # get input
     output_bxes = []
     with open(output_bx_file, 'r') as bx_file:
         bxes = bx_file.read().splitlines()
         for bx in bxes:
             LOG.debug(bx)
             output_bx = ast.literal_eval(bx)
             output_bxes.append(output_bx)
     return output_bxes
    def label_old(self, task_id, img_file_list, boundingbox):
        LOG.debug('camshift labeler label function called! labeling following files:')
        LOG.debug(img_file_list)
        cache_manager = cachemanagement.cacheManager()
        cache_dir = os.path.dirname(os.path.realpath(__file__)) + '/tmp/s3'
        cache_dir, img_file_list = cache_manager.cacheImageFromFileList(img_file_list, cache_dir)
        img_file_list = map(lambda x: cache_dir+'/'+x, img_file_list)
        MyUtils.writeListToFile(img_file_list, cache_dir+'/'+'labeler_input_img_list.txt')
        initialized = False
        result_bounding_boxes=[boundingbox]
        for each_img_file in img_file_list:
            LOG.debug('read in image file' + each_img_file)
            self.frame = cv2.imread(each_img_file)
            vis = self.frame.copy()
            hsv = cv2.cvtColor(self.frame, cv2.COLOR_BGR2HSV)
            mask = cv2.inRange(hsv, np.array((0., 60., 32.)), np.array((180., 255., 255.)))

            if not initialized:
                # set up initial labeled img
                x0, y0, width, height = boundingbox
                x1 = x0 + width
                y1 = y0 + height
                self.track_window = (x0, y0, width, height)
                hsv_roi = hsv[y0:y1, x0:x1]
                mask_roi = mask[y0:y1, x0:x1]
                hist = cv2.calcHist( [hsv_roi], [0], mask_roi, [16], [0, 180] )
                cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX);
                self.hist = hist.reshape(-1)
                initialized = True
                continue
#                self.show_hist()

            prob = cv2.calcBackProject([hsv], [0], self.hist, [0, 180], 1)
            prob &= mask
            term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )
            track_box, self.track_window = cv2.CamShift(prob, self.track_window, term_crit)
#            pdb.set_trace()
            # get rectangle 
            track_rect = cv2.boundingRect(cv2.boxPoints(track_box))


            # try:
            #     pt1 = (track_rect[0],track_rect[1])
            #     pt2 = (track_rect[0] + track_rect[2], track_rect[1] + track_rect[3])
            #     cv2.rectangle(vis, pt1, pt2, (0, 255, 0), 2)
            #     cv2.ellipse(vis, track_box, (0, 0, 255), 2)
            # except:

            print track_rect
            result_bounding_boxes.append(list(track_rect))
            
        return result_bounding_boxes
from PyQt4.QtGui import QApplication
from argh import *

import view
from include import *
# TODO: need better organization
sys.path.append('../include')
import cachemanagement
from sloth.core.labeltool import LabelTool

logger = logging.getLogger('client')
handler = logging.StreamHandler(sys.stdout)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

cache_manager = cachemanagement.cacheManager()

@contextlib.contextmanager
def exception_handler():
    try:
        yield
    except xmlrpclib.ProtocolError as err:
        print("A protocol error occurred")
        print("URL: %s" % err.url)
        print("HTTP/HTTPS headers: %s" % err.headers)
        print("Error code: %d" % err.errcode)
        print("Error message: %s" % err.errmsg)
    except socket.error as err:
        logger.error("socket error: failed to connect to remote server")
    except:
        print 'error!'
    def train(self, task_id, training_set, testing_set, **kwargs):
        print 'caffe train called'

        self.output_dir_prefix = os.path.abspath('./classifier/caffenet_')
        # create an output folder for each task
        if None != task_id:
            self.output_dir = self.output_dir_prefix + str(task_id)
        else:
            timestamp = time.strftime("%m_%d_%y_%H_%M_%S")
            self.output_dir = self.output_dir_prefix + timestamp

        # TODO: changed to user input parameter?
        max_iter = 500
        if 'iteration' in kwargs:
            max_iter = kwargs['iteration']

        MyUtils.create_dir(self.output_dir)


        # connect to database manager
        self.db_manager = MongoDBManager(CaffeNetTrainer.dbname, ip_addr='128.2.213.107')
        self.storage_manager = StorageManager('test1')

        # make intermediate folder
        self.ori_image_dir = CaffeNetTrainer.local_tmp_dir + '/' +'original'
        self.crop_image_dir = CaffeNetTrainer.local_tmp_dir + '/' +'crop'
        self.cache_manager = cacheManager(self.ori_image_dir)
        MyUtils.create_dir(self.ori_image_dir)
        MyUtils.create_dir(self.crop_image_dir)
        # get image file list and bounding boxes

        # get objects regardless of their videos, since same object in different video belongs to same identitfy
        # summarize to get all objects
        obj_set = {}
        for obj, vid in training_set.iteritems():
            if obj not in obj_set:
                obj_set[obj] = []
            obj_set[obj].extend(vid)
        print obj_set

        # for each object, get images
        training_set_obj_file_path ={}
        for obj, vids in obj_set.iteritems():
            # 1. download image
            # 2. crop image based on bounding boxes
            obj_image_path = []
            obj_bounding_boxes_with_image = {}
            for vid in vids:
                obj_bounding_boxes_each_vid = self.db_manager.getBoundingBoxWithImageByVidAndObj(vid, obj)
                # TODO: probably can be a bit more efficient. right now is downloading vid repeatedly if it appears
                # multiple times in train yaml
                self.cache_manager.cacheImageFiles(vid, dir=False)
                obj_bounding_boxes_with_image.update(obj_bounding_boxes_each_vid)

            for image, bx_list in obj_bounding_boxes_with_image.iteritems():
#                self.storage_manager.download(image, self.ori_image_dir)
                idx =0
                for bx in bx_list:
                    im = Image.open(self.ori_image_dir+'/'+image)
                    left_x = bx[0]
                    left_y = bx[1]
                    right_x = left_x + bx[2]
                    right_y = left_y + bx[3]
                    output_file_path = self.crop_image_dir + '/' +os.path.splitext(image)[0] + '_' + str(obj) + str(idx) \
                                       + os.path.splitext(image)[1]
                    im.crop((left_x,left_y, right_x, right_y)).save(output_file_path)
                    obj_image_path.append(output_file_path)
                    idx +=1
            training_set_obj_file_path[obj] = obj_image_path

        # generate training file
        training_set_obj_file_path, testing_set_obj_file_path =self.split_train_file(training_set_obj_file_path, 10)
        self.generate_caffe_train_file(training_set_obj_file_path, self.output_dir + '/train.txt')
        self.generate_caffe_train_file(testing_set_obj_file_path, self.output_dir +'/test.txt')
        # generate label file for corresponds label to object names
        self.generate_caffe_label_file(training_set_obj_file_path, self.output_dir + '/label.txt')

        # modify network prototxt
        num_output_category = len(obj_set)

        train_file_path = os.path.abspath(self.output_dir + '/train.txt')
        test_file_path = os.path.abspath(self.output_dir + '/test.txt')

        output_train_val_path = self.output_dir + '/' + 'train_val_custom.prototxt'
        output_solver_path = self.output_dir + '/' + 'solver_custom.prototxt'
        output_deploy_path = self.output_dir + '/' + 'deploy_custom.prototxt'
        # fine-tuning output
        self.custom_net_path = self.output_dir + '/train_val_custom.prototxt'
        self.custom_snapshot_prefix= self.output_dir + '/caffenet_custom'
        self.output_layer_name ="fc8_custom"
        self.output_net_name="CaffeNetCustom"
        # original model
        self.original_output_layer_name ='fc8'
        # reference design file locations
        input_file_prefix = os.path.abspath('./bvlc_reference_caffenet')
        train_file ='train_val.prototxt'
        solver_file ='solver.prototxt'
        deploy_file ='deploy.prototxt'

        self.mod_caffe_net(input_file_prefix+'/' + train_file, num_output_category, train_file_path,
                           test_file_path, output_train_val_path)
        self.mod_caffe_solver(input_file_prefix+ '/' +solver_file,
                              max_iter, output_solver_path)
        self.mod_caffe_deploy(input_file_prefix + '/' + deploy_file,
                              num_output_category, output_deploy_path)

        cmd ="/opt/caffe/build/tools/caffe train"
        cmd += " -solver " + output_solver_path
        cmd += " -weights ./bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel"
        cmd += " | tee " + self.output_dir + '/' + 'log.txt'

        print cmd
        # issue train
        os.system(cmd)
        MyUtils.zipdir(self.output_dir)
        zip_file = self.output_dir + '.zip'
        print 'uploading file to s3...'
        key = self.storage_manager.uploadFile(zip_file)
        print 'updating database...'

        # TODO: maybe send this information to controller?
        # add meta data info to database
        classifier_metadata={'name': key,
                             'training_set':training_set,
                             'testing_set':testing_set,
                             'accuracy': 'see log',
                             'filepath': key}
        self.db_manager.addClassifier(classifier_metadata)
        return