def __init__(self, track_x, track_y, tracks_Z, gEpG, oracle):
     self.track_x = track_x
     self.track_y = track_y
     self.tracks_Z = tracks_Z
     self.xO = Counter(soft_fetch(oracle, track_x))
     self.yO = Counter(soft_fetch(oracle, track_y))
     """
     Errors in the xO/yO track operand
     if len(_O)==0 we don' t kow much about the track because supervised
         information is not available
     if len(_O)==1 track_y is a correct track as far as we know !!!
     if len(_O)>1  track_y is already wrong before the computation !!!
     """
     self.ZO = [
         Counter(fetch(oracle, track_z_it))
         for track_z_it in tracks_z]
     """
     Errors in the results Z:
     tracks_z and ZO may contain 0,1 or 2 elements
         0:if the computation discarded both points
             (should it happen? maybe, maybe not,
             probably should be a rare event)
         1:if the computation merged the tracks
         2:if the computation splitted the tracks
     for zO in ZO:
         if len(zO)==0 we don' t kow much about the track because supervised
         information is not available
         if len(zO)==1 the resulting track is correct as far as we know
         if len(zO)>1 the resulting track is wrong
     completeness:
         missing keypoints:
         keypoints that
             are in the operands
             are not in the results
         spilled keypoints:
         missing keypoints that
             should be in the results
             have the same oracle of some result
     """
     kps2views = lambda some_keypoint_key_sequence: {
         view_key: v
         for v in track_x.allViews() + track_y.allViews()
         if view_key == v.key()
         for view_key in some_keypoint_key_sequence}
     operand_kp = set([
         v.key() for v in track_x.allViews() + track_y.allViews()])
     result_kp = reduce(
             lambda a, b: a + b,
             [[v.key() for v in track_z] for track_z in tracks_Z],
             [])
     result_kp = set(result_kp)
     missing = operand_kp.difference(result_kp)
     missing_views = kps2views(missing)
     missing_oracles = soft_fetch_views(oracle, missing_views.values())
     dominant_oracles_of_results = set([dominant(zO) for zO in ZO])
     self.spilled_oracles = Counter([o
             for o in missing_oracles
             if o in dominant_oracles_of_results])
     self.spilled = sum(self.spilled_oracles.values())
     pass
def print_merge_operation(track_x, track_y, result, gEpG, oracle):
        """
        arguments:
        track_x,track_y :   track operands
        result          :   list resulting from merging operands
        gEpG            :   epipolar geometries
        oracle          :   oracle partition

        print to a string a table with columns:
        Im      : image identifier
        -       : header identifier or keypoint oracle
        P       : point P
        Q       : point Q
        Z1,Z2   : results

        for each image in the merge problem an header made of 3 lines is printed
        O       : oracle header, for each track the dominant oracle
        X/Y     : coordinates for the each track on the image

        for each keypoint observed in the image a line will display
        keypoint oracle identifier
        keypoint identifier in the column of every track that referece it
        """
        tracks = [track_x, track_y] + results
        labels = ['Im', '', 'P', 'Q', 'Z1', 'Z2']
        s = ""
        Tc = map(compactPoint, tracks)
        # {image_id:(image_id,homogeneus_keypoint,keypoint_radius)}
        # Tc is a list of compacted tracks
        images = set(track_x.views.keys() + track_y.views.keys())
        keypoints = {
            im_id:
            set(sum(
                    [t.getKeypointsIds(im_id) for t in tracks],
                    []  # sum with lists as argument
                        #catenate the lists, [] is initial
               ))
            for im_id in images}
        s += line(labels)
        for im_id in sorted(images):
            keypoints_im = [
                set([
                    v.id_keypoint
                    for v in t.views[im_id]]
                ) for t in tracks]
            # image header:
            # 1-oracle header
            image_oracles = [
                dominant(soft_fetch_views(t.views[im]))
                for t in tracks]
            s += line([im_id, 'O'] + image_oracles)
            # 2-X header
            xs = [tc[im_id][1][0] for tc in Tc]
            s += line([im_id, 'X'] + xs)
            # 3-Y header
            ys = [tc[im_id][1][1] for tc in Tc]
            s += line([im_id, 'Y'] + ys)
            for kp_id in keypoints[im_id]:
                o = oracle.views[im_id].get(kp_id)
                track_has_kp = [
                    kp_id if (kp_id in kp_set) else ' '
                    for kp_set in keypoints_im]
                if o:
                    s += line([im_id, o] + track_has_kp)
                else:
                    s += line([im_id, o] + track_has_kp)
            s += '\n'
        s += print_list_epipolar_constraints(images, gEpG)
        return s