B
    QaA                 @   s   yd dl mZmZmZ W n ek
r4   edY nX d dlZd dlZd dl	Z
d dlmZ d dlmZ ddlmZ dddZdddZG dd dZdS )    )measuresegmentation
morphologyzCould not import skimage!N)csgraph)cKDTree   )deramp     @   Fc             C   s,  t j| ddd\}}t||jd }|r:tdt| tj||dd} d|| dk< t j|ddd\}}|dkr$t	
||f}t||t	j}t |}t||k r$|rtd d	d
 |D }	xFt |D ]8}
|
j|	krd|||
jk< |rtd|
j|
j|
j qW t j|ddd\}}||fS )a  Label / clean up the conn comp (mask)

    Parameters: mask         - 2D np.ndarray of bool/int
                min_area     - float, minimum region/area size
                erosion_size - int (odd number), size of erosion structure
                               set to 0 to turn it off.
    Returns:    label_img    - 2d np.ndarray of int, labeled array where all 
                               connected regions are assigned the same value
                num_label    - int, number of labeled regions
    r   T)connectivity
return_numg~jth?zremove regions with area < {})min_sizer   r   z4regions lost during morphological erosion operation:c             S   s   g | ]
}|j qS  )label).0regr   r   M/home/centos/operations/rsmas_insar/sources/MintPy/mintpy/objects/conncomp.py
<listcomp><   s    z#label_conn_comp.<locals>.<listcomp>zlabel: {}, area: {}, bbox: {})r   r   minsizeprintformatintmorphremove_small_objectsnponeserosionastypeuint8regionpropslenareabbox)maskmin_areaerosion_size	print_msg	label_img	num_labelerosion_structurelabel_erosion_imgerosion_regionslabel_erosionorig_regr   r   r   label_conn_comp   s0    



r/   c       
      C   s   |dkrt ||f}t| |t j}t|}t||k r|rLt	d dd |D }xFt| D ]8}|j
|krfd| | |j
k< |rft	d|j
|j|j qfW tj
| ddd\} }tj|d	d
t j}	|	|9 }	| ||	fS )a  Label the boundary of the labeled array

    Parameters: label_img    - 2d np.ndarray of int, labeled array where all connected regions are assigned the same value
                num_label    - int, number of labeled regions
    Returns:    label_img    - 2d np.ndarray of int, labeled array where all connected regions are assigned the same value
                num_label    - int, number of labeled regions
                label_bound  - 2d np.ndarrary of bool, where True represent a boundary pixel.
    r   z4regions lost during morphological erosion operation:c             S   s   g | ]
}|j qS r   )r   )r   r   r   r   r   r   `   s    z"label_boundary.<locals>.<listcomp>zlabel: {}, area: {}, bbox: {}r   T)r   r   thick)mode)r   r   r   r   r   r   r   r    r!   r   r   r   r"   r#   segZfind_boundaries)
r(   r)   r&   r'   r*   r+   r,   r-   r.   Zlabel_boundr   r   r   label_boundaryK   s&    



r3   c               @   sP   e Zd ZdZdd ZdddZd	d
 Zdd ZdddZdddZ	dddZ
dS )connectComponenta7   Object for bridging connected components.

    Example:
        unw_file = 'filt_fine.unw'
        # prepare connectComponent object
        atr = readfile.read_attribute(unw_file)
        conncomp = readfile.read(unw_file+'.conncomp')[0]
        cc = connectComponent(conncomp=conncomp, metadata=atr)
        cc.label()
        cc.find_mst_bridge()

        # run bridging
        unw = readfile.read(unw_file)[0]
        bdg_unw = cc.unwrap_conn_comp(unw, ramp_type='linear')

        # write output file
        writefile.write(bdg_unw, 'bdg_'+unw_file, atr)
    c             C   s~   t |jtjkr$tdt |j|| _|| _d| kr^t	| jd | _
t	| jd | _nd| _
d| _| jj\| _| _dS )zsParameters: conncomp : 2D np.ndarray in np.bool_ format
                       metadata : dict, attributes
        z$Input conncomp is not np.ndarray: {}REF_YREF_XN)type
__module__r   __name__
ValueErrorr   conncompmetadatakeysr   refYrefXshapelengthwidth)selfr;   r<   r   r   r   __init__   s    zconnectComponent.__init__     @r
   Fc             C   s   t | j||d\| _| _t| j| j||d\| _| _| _| jdk	rj| j| j| jf | _| jdkrt	dn,t
| j}tdd |D }|| j| _dS )z Label the connected components
        Returns: self.labelImg   - 2D np.ndarray in int64 to mask areas to be corrected
                 self.labelBound - 2D np.ndarray in uint8 for label boundaries to find bridges
        )r%   r'   )r&   r'   Nr   z>input reference point is NOT included in the connectComponent.c             S   s   g | ]
}|j qS r   )r"   )r   regionr   r   r   r      s    z*connectComponent.label.<locals>.<listcomp>)r/   r;   labelImgnumLabelr3   
labelBoundr>   r?   labelRefr:   r   r    r   argmaxr   )rC   r%   r&   r'   regionsidxr   r   r   r      s    


zconnectComponent.labelc             C   sF  t | j}g }x&t| jD ]}|t|| j qW t | _	t
j| j| jft
jd| _xtt| jdD ]\}}|| || j\}}t
|}|| j|ddf }|| j|| ddf }	|| }
t|d t|d  }}t }|	||< |||< |
|d< || j	d||< |
 | j||f< | j||f< qnW | j	| jfS )a	   Search all possible connections among labeled regions
        Returns:    connDict : dict of connection, i.e.:
                        {'1_2': {'1': array([1232,  345]),
                                 '2': array([868, 239]),
                                 'distance': 379.1200337623956},
                         '1_3': {'1': array([1232,  345]),
                                 '3': array([1089,  191]),
                                 'distance': 210.1547049199708},
                         '1_4': {'1': array([1204, 1143]),
                                 '4': array([1217, 1157]),
                                 'distance': 19.1049731745428},
                         '1_5': {'1': array([1263,  557]),
                                 '5': array([1270,  565]),
                                 'distance': 10.63014581273465},
                         '2_3': {'2': array([868, 239]),
                                 '3': array([891, 249]),
                                 'distance': 25.079872407968907},
                         '2_4': {'2': array([868, 239]),
                                 '4': array([1273, 1103]),
                                 'distance': 954.2122405419037},
                         '2_5': {'2': array([868, 239]),
                                 '5': array([1269,  566]),
                                 'distance': 517.4263232577175},
                         '3_4': {'3': array([996, 275]),
                                 '4': array([1319, 1085]),
                                 'distance': 872.0258023705492},
                         '3_5': {'3': array([1015,  264]),
                                 '5': array([1289,  545]),
                                 'distance': 392.4754769409167},
                         '4_5': {'4': array([1319, 1085]),
                                 '5': array([1305,  670]),
                                 'distance': 415.2360774306587}
                        }
                    distMat : 2D np.array in size of (nLabel, nLabel), i.e.:
                        array([[  0.      , 379.12003 , 210.15471 ,  19.104973,  10.630146],
                               [379.12003 ,   0.      ,  25.079872, 954.2122  , 517.42633 ],
                               [210.15471 ,  25.079872,   0.      , 872.0258  , 392.47546 ],
                               [ 19.104973, 954.2122  , 872.0258  ,   0.      , 415.23608 ],
                               [ 10.630146, 517.42633 , 392.47546 , 415.23608 ,   0.      ]],
                              dtype=float32)
        )dtype   Nr   distancez{}_{})r   r    rI   rangerH   appendr   coordsdictconnDictr   zerosfloat32distMat	itertoolscombinationsqueryargminstrr   )rC   rL   ZtreesijdistrM   idx_minZyxjZyxiZdist_minn0n1connr   r   r   get_all_bridge   s(    *
 zconnectComponent.get_all_bridgec             C   sH  t | ds|   t| j}tj|| jd dd\}}g | _xtd|j	D ]}|||  d }|| d }||krt
|t
|g}nt
|t
|g}| jd|d |d  }|t
| \}	}
|t
| \}}t }|
|d< |	|d< ||d	< ||d
< ||d< ||d< ||
 d ||	 d  d |d< | j| qLW t| j| _| jS )a   Search for bridges to connect all labeled areas using the minimum spanning tree algorithm
        Returns:    bridges : list of dict, i.e.:
                        [{'label0': 1, 'label1': 3, 'x0': 345, 'x1': 191, 'y0': 1232, 'y1': 1089},
                         {'label0': 1, 'label1': 4, 'x0': 1143, 'x1': 1157, 'y0': 1204, 'y1': 1217},
                         {'label0': 1, 'label1': 5, 'x0': 557, 'x1': 565, 'y0': 1263, 'y1': 1270},
                         {'label0': 3, 'label1': 2, 'x0': 249, 'x1': 239, 'y0': 891, 'y1': 868}]
        rX   r   F)i_startdirectedz{}_{}r   x0y0x1y1label0label1rO   g      ?rP   )hasattrre   csgminimum_spanning_treerX   breadth_first_orderrJ   bridgesrQ   r   r]   rU   r   rT   rR   r!   Z
num_bridge)rC   Z
distMatMstZsuccsZpredsr^   rb   rc   nnrd   ri   rh   rk   rj   bridger   r   r   find_mst_bridge   s2    
 z connectComponent.find_mst_bridge2   c             C   s   |d |d  }}|d |d  }}t d|| }t| j|| }t d|| }	t| j|| }
t d|| }t| j|| }t d|| }t| j|| }tj| jjtjd}tj| jjtjd}d||	|
||f< d|||||f< ||fS )Nrh   ri   rj   rk   r   )rN   T)	maxr   rB   rA   r   rV   rG   r@   bool_)rC   rt   radiusrh   ri   rj   rk   Zx00x01Zy00y01Zx10x11Zy10Zy11	aoi_mask0	aoi_mask1r   r   r   get_bridge_endpoint_aoi_mask(  s        z-connectComponent.get_bridge_endpoint_aoi_maskNc             C   s  t   }tt|t| jjd }tj|tjd}| jd k	r\||dk  || j| j	f 8  < |d k	r|rvt
d| | j| jk}t|||| jd\}}x| jD ]}| j||d\}	}
| j|d k}| j|d k}t||	|  }t||
|  }|| }t|tj d	tj  }|d
kr*|d9 }||  d	tj | 7  < |rt
d|d |d || qW |d k	rz||7 }|rt
dt   |  |S )Ng?)rN   g        zestimate a {} ramp)r<   )ry   rl   rm   g       @r   z2phase diff {}_{}: {:04.1f} rad --> num of jump: {}ztime used: {:.2f} secs.)timer   r   r;   r@   r   arrayrW   r>   r?   r   r   rG   rJ   r   r<   rr   r   	nanmedianabspi)rC   unwry   	ramp_typer'   
start_timeZ	ramp_maskramprt   r}   r~   label_mask0label_mask1Zvalue0Zvalue1Z
diff_valueZnum_jumpr   r   r   unwrap_conn_comp7  s@    
 

z!connectComponent.unwrap_conn_compjetc             C   s   |j | j|dd x| jD ]}|j|d |d g|d |d gddd	 |d
kr| j||d\}}| j|d k}| j|d k}tj||  t| jj	}	tj||  t| jj	}
|j |	ddd
dd |j |
ddd
dd qW |j| j
| jddd |S )Nnearest)cmapinterpolationrh   rj   ri   rk   zw-r   )lwr   )ry   rl   rm   grayg333333?)r   alphavminvmaxksrO   )ms)imshowrG   rr   plotr   r   mamasked_whererV   r@   r?   r>   )rC   axr   ry   rt   r}   r~   r   r   Zmask0mask1r   r   r   plot_bridgeg  s    zconnectComponent.plot_bridge)rE   r
   F)rv   )rv   NF)r   rv   )r9   r8   __qualname____doc__rD   r   re   ru   r   r   r   r   r   r   r   r4   u   s   
D+

0r4   )r	   r
   F)r
   F)skimager   r   r2   r   r   ImportErrorr   rY   numpyr   scipy.sparser   ro   scipy.spatialr   r   r   r/   r3   r4   r   r   r   r   <module>
   s   
2
*