def drawThreshMask(self, worm_img, worm_qimg, row_data, read_center=True):
        #in very old versions of the tracker I didn't save the area in trajectories table,
        #let's assign a default value to deal with this cases
        if 'area' in row_data:
            min_blob_area = row_data['area'] / 2
        else:
            min_blob_area = 10

        c1, c2 = (row_data['coord_x'],
                  row_data['coord_y']) if read_center else (-1, -1)

        worm_mask, worm_cnt, _ = getWormMask(
            worm_img,
            row_data['threshold'],
            strel_size=self.strel_size,
            roi_center_x=c1,
            roi_center_y=c2,
            min_blob_area=min_blob_area,
            is_light_background=self.is_light_background)

        worm_mask = QImage(worm_mask.data, worm_mask.shape[1],
                           worm_mask.shape[0], worm_mask.strides[0],
                           QImage.Format_Indexed8)
        worm_mask = worm_mask.convertToFormat(QImage.Format_RGB32,
                                              Qt.AutoColor)
        worm_mask = QPixmap.fromImage(worm_mask)

        worm_mask = worm_mask.createMaskFromColor(Qt.black)
        p = QPainter(worm_qimg)
        p.setPen(QColor(0, 204, 102))
        p.drawPixmap(worm_qimg.rect(), worm_mask, worm_mask.rect())

        if False:
            #test skeletonization
            skeleton, ske_len, cnt_side1, cnt_side2, cnt_widths, cnt_area = \
                getSkeleton(worm_cnt, np.zeros(0), 49)
            for cnt in skeleton, cnt_side1, cnt_side2:
                p.setPen(Qt.black)
                polyline = QPolygonF()
                for point in cnt:
                    polyline.append(QPointF(*point))
                p.drawPolyline(polyline)

        p.end()
def get_skeleton_from_sides(side1, side2):

    cnt_side1, cnt_side2 = side1, side2

    ht_dist = np.sum((cnt_side2[0][None] - cnt_side1[[0, -1]])**2, axis=1)
    if ht_dist[0] > ht_dist[1]:
        cnt_side1 = cnt_side1[::-1]

    head_coord = (cnt_side1[0] + cnt_side2[0]) / 2
    tail_coord = (cnt_side1[-1] + cnt_side2[-1]) / 2

    cnt_side1 = np.concatenate(
        (head_coord[None], cnt_side1[1:-1], tail_coord[None]), axis=0)
    cnt_side2 = np.concatenate(
        (head_coord[None], cnt_side2[1:-1], tail_coord[None]), axis=0)

    cnt_side1 = resample2pix(cnt_side1)
    cnt_side2 = resample2pix(cnt_side2)

    ii = 1
    cc = np.concatenate((cnt_side1[ii:ii + 3], cnt_side1[ii][None]))
    #contours must be in clockwise direction otherwise the angles algorithm will give a bad result

    # make sure the contours are in the counter-clockwise direction
    # x1y2 - x2y1(http://mathworld.wolfram.com/PolygonArea.html)
    signed_area = np.sum(cc[:-1, 0] * cc[1:, 1] - cc[1:, 0] * cc[:-1, 1]) / 2
    if signed_area > 0:
        cnt_side1, cnt_side2 = cnt_side2, cnt_side1

    contour = np.concatenate((cnt_side1, cnt_side2[::-1]), axis=0)
    #contour = np.ascontiguousarray(contour[::-1])

    skeleton, _, cnt_side1, cnt_side2, cnt_widths, _ = getSkeleton(contour)

    # resample data
    skeleton = smooth_curve(skeleton)
    cnt_widths = smooth_curve(cnt_widths)
    cnt_side1 = smooth_curve(cnt_side1)
    cnt_side2 = smooth_curve(cnt_side2)

    return skeleton, cnt_widths, cnt_side1, cnt_side2
def trajectories2Skeletons(skeletons_file, 
                            masked_image_file,
                            resampling_N=49, 
                            min_blob_area=50, 
                            strel_size=5, 
                            worm_midbody=(0.35, 0.65),
                            analysis_type="WORM", 
                            skel_args = {'num_segments' : 24, 
                                         'head_angle_thresh' : 60}
                            ):
    
    #get the index number for the width limit
    midbody_ind = (int(np.floor(
        worm_midbody[0]*resampling_N)), int(np.ceil(worm_midbody[1]*resampling_N)))
    
    #read trajectories data with pandas
    with pd.HDFStore(skeletons_file, 'r') as ske_file_id:
        trajectories_data = ske_file_id['/trajectories_data']
    
    # extract the base name from the masked_image_file. This is used in the
    # progress status.
    base_name = masked_image_file.rpartition('.')[0].rpartition(os.sep)[-1]
    progress_prefix =  base_name + ' Calculating skeletons.'
        
    
    
    # open skeleton file for append and #the compressed videos as read
    with tables.File(skeletons_file, "r+") as ske_file_id:

        #attribute useful to understand if we are dealing with dark or light worms
        bgnd_param = ske_file_id.get_node('/trajectories_data')._v_attrs['bgnd_param']
        bgnd_param = json.loads(bgnd_param.decode("utf-8"))

        is_light_background = ske_file_id.get_node('/trajectories_data')._v_attrs['is_light_background']
        if len(bgnd_param) > 0:
            #invert (at least if is_light_background is true)
            is_light_background = not is_light_background

        
        #get generators to get the ROI for each frame
        ROIs_generator = generateMoviesROI(masked_image_file, 
                                         trajectories_data, 
                                         bgnd_param = bgnd_param,
                                         progress_prefix = progress_prefix)

        # add data from the experiment info (currently only for singleworm)
        with tables.File(skeletons_file, "r") as mask_fid:  
            if '/experiment_info' in ske_file_id:
                    ske_file_id.remove_node('/', 'experiment_info')
            if '/experiment_info' in mask_fid:
                dd = mask_fid.get_node('/experiment_info').read()
                ske_file_id.create_array('/', 'experiment_info', obj=dd)
        
                
        #initialize arrays to save the skeletons data
        tot_rows = len(trajectories_data)
        skel_arrays, has_skeleton = _initSkeletonsArrays(ske_file_id, tot_rows, resampling_N, worm_midbody)
        
        
        # dictionary to store previous skeletons
        prev_skeleton = {}
        
        for worms_in_frame in ROIs_generator:
            for ind, roi_dat in worms_in_frame.items():
                row_data = trajectories_data.loc[ind]
                worm_img, roi_corner = roi_dat
                skeleton_id = int(row_data['skeleton_id'])
                
                # get the previous worm skeletons to orient them
                worm_index = row_data['worm_index_joined']
                if worm_index not in prev_skeleton:
                    prev_skeleton[worm_index] = np.zeros(0)

                if analysis_type == "ZEBRAFISH":
                     output = _zebra_func(worm_img, skel_args, resampling_N)
                else:
                    _, worm_cnt, _ = getWormMask(worm_img, 
                                                 row_data['threshold'], 
                                                 strel_size,
                                                 min_blob_area=row_data['area'] / 2, 
                                                 is_light_background = is_light_background)
                    # get skeletons
                    output = getSkeleton(worm_cnt, prev_skeleton[worm_index], resampling_N, **skel_args)

                
                
                
                if output is not None and output[0].size > 0:
                    skeleton, ske_len, cnt_side1, cnt_side2, cnt_widths, cnt_area = output
                    prev_skeleton[worm_index] = skeleton.copy()

                    #mark row as a valid skeleton
                    has_skeleton[skeleton_id] = True
                    
                    # save segwrom_results
                    skel_arrays['skeleton_length'][skeleton_id] = ske_len
                    skel_arrays['contour_width'][skeleton_id, :] = cnt_widths
                    
                    mid_width = np.median(cnt_widths[midbody_ind[0]:midbody_ind[1]+1])
                    skel_arrays['width_midbody'][skeleton_id] = mid_width

                    # convert into the main image coordinates
                    skel_arrays['skeleton'][skeleton_id, :, :] = skeleton + roi_corner
                    skel_arrays['contour_side1'][skeleton_id, :, :] = cnt_side1 + roi_corner
                    skel_arrays['contour_side2'][skeleton_id, :, :] = cnt_side2 + roi_corner
                    skel_arrays['contour_area'][skeleton_id] = cnt_area