U
    QaA                     @   s   z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 }	t |D ]8}
|
j|	krd|||
jk< |rtd|
j|
j|
j qt 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   4regions 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>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   s2    



r4   c           
      C   s   |dkrt ||f}t| |t j}t|}t||k r|rLt	d dd |D }t| D ]8}|j
|krdd| | |j
k< |rdt	d|j
|j|j qdt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   r   c                 S   s   g | ]
}|j qS r   r   r   r   r   r   r   `   s     z"label_boundary.<locals>.<listcomp>r   r   Tr   thick)mode)r    r!   r   r"   r#   r$   r   r%   r&   r   r   r   r'   r(   segZfind_boundaries)
r-   r.   r+   r,   r/   r0   r1   r2   r3   Zlabel_boundr   r   r   label_boundaryK   s(    



r8   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@   rA   r   r   r   __init__   s    zconnectComponent.__init__r	   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>)r4   r@   labelImgnumLabelr8   
labelBoundrC   rD   labelRefr?   r   r%   r    argmaxr   )rH   r*   r+   r,   regionsidxr   r   r   r      s,    


zconnectComponent.labelc                 C   s>  t | j}g }t| jD ]}|t|| j qt | _	t
j| j| jft
jd| _t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< qh| 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   distance{}_{})r   r%   rM   rangerL   appendr   coordsdictconnDictr    zerosfloat32distMat	itertoolscombinationsqueryargminstrr   )rH   rP   ZtreesijdistrQ   idx_minZyxjZyxiZdist_minn0n1connr   r   r   get_all_bridge   s(    *
zconnectComponent.get_all_bridgec                 C   sD  t | ds|   t| j}tj|| jd dd\}}g | _t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| qJt| 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}]
        r^   r   F)i_startdirectedrV   r   x0y0x1y1label0label1rT   g      ?rU   )hasattrrk   csgminimum_spanning_treer^   breadth_first_orderrN   bridgesrW   r   rc   r[   r   rZ   rX   r&   Z
num_bridge)rH   Z
distMatMstZsuccsZpredsrd   rh   ri   nnrj   ro   rn   rq   rp   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 )Nrn   ro   rp   rq   r   rR   T)	maxr   rG   rF   r    r\   rK   rE   bool_)rH   rz   radiusrn   ro   rp   rq   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\}}| 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 || q|d k	rv||7 }|rt
dt   |  |S )Ng?rR   g        zestimate a {} ramp)rA   r   rr   rs   g       @r   z2phase diff {}_{}: {:04.1f} rad --> num of jump: {}ztime used: {:.2f} secs.)timer   r   r@   rE   r    arrayr]   rC   rD   r   r   rK   rN   r   rA   rx   r   	nanmedianabspi)rH   unwr   	ramp_typer,   
start_timeZ	ramp_maskramprz   r   r   label_mask0label_mask1Zvalue0Zvalue1Z
diff_valueZnum_jumpr   r   r   unwrap_conn_comp7  sB    
 


z!connectComponent.unwrap_conn_compjetc                 C   s   |j | j|dd | 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|j| j
| jddd |S )Nnearest)cmapinterpolationrn   rp   ro   rq   zw-r   )lwr   r   rr   rs   grayg333333?)r   alphavminvmaxksrT   )ms)imshowrK   rx   plotr   r    mamasked_wherer\   rE   rD   rC   )rH   axr   r   rz   r   r   r   r   Zmask0mask1r   r   r   plot_bridgeg  s"    
  zconnectComponent.plot_bridge)r	   r
   F)r|   )r|   NF)r   r|   )r>   r=   __qualname____doc__rI   r   rk   r{   r   r   r   r   r   r   r   r9   u   s   
D+

0r9   )r	   r
   F)r
   F)skimager   r   r7   r   r   ImportErrorr   r_   numpyr    scipy.sparser   ru   scipy.spatialr   r   r   r4   r8   r9   r   r   r   r   <module>
   s   
2
*