U
    ; cʌ                     @   s  d dl Z 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mZmZ dZdZdZd_d	d
Zd`ddZdd ZdaddZdd ZdbddZdcddZdd Zdd Zdd Zdd Zddd!d"Zd#d$ Zd%d& Zd'd( Zded)d*Z d+d, Z!d-d. Z"d/d0 Z#d1ej$ ej$gfd2d3Z%dfd5d6Z&dgd7d8Z'dhd9d:Z(did<d=Z)d>d? Z*d@dA Z+dBdC Z,dDdE Z-djdGdHZ.dIdJ Z/dkdLdMZ0dldOdPZ1dmdQdRZ2dSdT Z3dUdV Z4dWdX Z5dYdZ Z6dnd[d\Z7d]d^ Z8dS )o    N)ndimage)CRSProjTransformeriJxg    MXAgHz'D@   Tc                 C   s   d|   kr$|dkr$d}|r$td t| d t| d  }}t| d t| d  }}|||d   }|| d	 }|rtd
|  td|  td|  |dkrt|tjS tj|||d}	|dkrt|	tjS t|	|df}
t|
tjS dS )a  Calculate slant range distance from input attribute dict
    Parameters: atr : dict, including the following ROI_PAC attributes:
                    STARTING_RANGE
                    RANGE_PIXEL_SIZE
                    LENGTH
                    WIDTH
                dimension : int, choices = [0,1,2]
                    2 for 2d matrix, vary in range direction, constant in az direction,
                        for radar coord only
                    1 for 1d matrix, in range direction, for radar coord file
                    0 for center value
    Returns:    np.array (0, 1 or 2 D) : range distance between antenna and ground target in meters
    Y_FIRSTr   zGinput file is geocoded, return center range distance for the whole areaSTARTING_RANGERANGE_PIXEL_SIZELENGTHWIDTH          @znear   range : %.2f mzcenter range : %.2f mzfar    range : %.2f m)numN)	keysprintfloatintnparrayfloat32linspacetile)atr	dimension	print_msgrange_ndRlengthwidthrange_fZrange_cZrange_xZrange_xy r    J/home/exouser/operations/rsmas_insar/sources/MintPy/mintpy/utils/utils0.pyrange_distance!   s&    r"   c              	   C   s  d|   kr$|dkr$d}|r$td t| d }t| d }t| d }t| d }t| d }|||  }	tjt|d	 |d	  || d	  d	| |   d
 tj }
tjt|d	 |	d	  || d	  d	| |	   d
 tj }|
| d }|r$td|
 td| td| |dkr4|}n|dkrVtj|
||dtj	d}n|d	krt| d }|dk	rt
| d	dd}tjt|| d	 |d	  || d	  d	||  |   d
 tj }n"ttj|
||dtj	d|df}ntd||S )a  Calculate 2D matrix of incidence angle from ROI_PAC attributes, very accurate.
    Parameters: atr : dict - ROI_PAC attributes including the following items:
                     STARTING_RANGE
                     RANGE_PIXEL_SIZE
                     EARTH_RADIUS
                     HEIGHT
                     WIDTH
                     LENGTH     #for dimension=2
                dem : 2D array for height to calculate local incidence angle
                dimension : int,
                            2 for 2d matrix
                            1 for 1d array
                            0 for one center value
                print_msg : bool
    Returns:    inc_angle : 2D np.array, incidence angle in degree for each pixel
    Example:    dem = readfile.read('hgt.rdr')[0]
                atr = readfile.read_attribute('filt_fine.unw')
                inc_angle = ut.incidence_angle(atr, dem=dem)
    r   r   z9input file is geocoded, return center incident angle onlyr   r	   EARTH_RADIUSHEIGHTr   r        f@r   z&near   incidence angle : {:.4f} degreez&center incidence angle : {:.4f} degreez&far    incidence angle : {:.4f} degreer   FALSE)r   endpointdtyper
   NFr   r   z un-supported dimension input: {})r   r   r   r   r   piarccosformatr   r   r"   r   	Exception)r   demr   r   r   r   rHr   r   Zinc_angle_nZinc_angle_fZinc_angle_c	inc_angler   
range_distr    r    r!   incidence_angleJ   sV    >>


 

& r3   c                 C   s   t |trt|}tj|tjdd tj }t| d }t| d }|| ttj|  }t|| }|| }|t| }|S )a  Calculate the corresponding slant range distance given an incidence angle

    Law of sines:
               r + H                   r               range_dist
       --------------------- = ----------------- = ------------------ = 2R
        sin(pi - inc_angle)     sin(look_angle)     sin(range_angle)

    where range_angle = inc_angle - look_angle
          R is the radius of the circumcircle.

    link: http://www.ambrsoft.com/TrigoCalc/Triangle/BasicLaw/BasicTriangle.htm

    Parameters: atr         - dict, metadata including the following items:
                                  EARTH_RADIUS
                                  HEIGHT
                inc_angle   - float / np.ndarray, incidence angle in degree
    Returns:    slant_range - float, slant range distance
    r(      r#   r$   )	
isinstancestrr   r   r   r   r*   sinarcsin)r   r1   r/   r0   ZR2Z
look_angleZrange_angler2   r    r    r!   $incidence_angle2slant_range_distance   s    
r:   Fc                 C   sJ   d|   krtd dS t| d|d}t| d t|d tj  }|S )zkGet range resolution on the ground in meters,
        from ROI_PAC attributes, for file in radar coord
    X_FIRSTz5Input file is in geo coord, no range resolution info.Nr   r)   r	   r%   )r   r   r3   r   r   r8   r*   )r   r   r1   rg_stepr    r    r!   range_ground_resolution   s     r=   c                 C   s   d|   krtd dS z| d }W n   d}Y nX |dkrpt| d }t| d }t| d	 | ||  }n|d
krt| d	 }|S )zmGet azimuth resolution on the ground in meters,
        from ROI_PAC attributes, for file in radar coord
    r;   z7Input file is in geo coord, no azimuth resolution info.N	PROCESSORisce)roipacr?   r#   r$   AZIMUTH_PIXEL_SIZEgamma)r   r   r   )r   procReheightaz_stepr    r    r!   azimuth_ground_resolution   s    
rG   c           
   	   C   s  t ttt| d }t| }t| }|tt | |tt |  }|tt | |tt |  }t 	|| ||  }||9 }||9 }|dkrd| 
 krt| d t| d  d }nd}t |tt t |  }t |t d }	|	|fS )a}  Get the default lat/lon step size for geocoding.

    Treat the pixel in radar coordinates as an rotated rectangle. Use the bounding box
    of the rotated rectangle for the ratio between lat and lon steps. Then scale the
    lat and lon step size to ensure the same area between the pixels in radar and geo
    coordinates.

    Link: https://math.stackexchange.com/questions/4001034

    Parameters: atr      - dict, standard mintpy metadata
                lat_c    - float, central latitude in degree
    Returns:    lat_step - float, latitude  step size in degree
                lon_step - float, longitude step size in degree
    HEADINGNLAT_REF1LAT_REF3r   r         )r   deg2radabsheading2azimuth_angler   rG   r=   cosr8   sqrtr   rad2degr#   )
r   Zlat_caz_anglerF   r<   x_stepy_stepscale_factorlon_steplat_stepr    r    r!   auto_lat_lon_step_size   s    $$rX   c              
   C   s   | sdS t | tr| g} dd | D } | D ]>}tj|r*t|d t|| td|  W 5 Q R X q*t| dkr~| d } | S )a  python equivalent function to Unix utily - touch
    It sets the modification and access times of files to the current time of day.
    If the file doesn't exist, it is created with default permissions.
    Inputs/Output:
        fname_list - string / list of string
    Nc                 S   s   g | ]}|d k	r|qS Nr    ).0xr    r    r!   
<listcomp>  s      ztouch.<locals>.<listcomp>aztouch r   r   )	r6   r7   ospathisfileopenutimer   len)Z
fname_listtimesfnamer    r    r!   touch   s    
rf   c                 C   s6   t dt| dd | d dkd}| d }|S )zConvert UTM Zone string to EPSG code.
    Parameters: utm_zone - str, atr['UTM_ZONE']
    Returns:    epsg     - str, EPSG code
    Examples:   epsg = utm_zone2epsg_code('11N')
    ZutmNS)Zprojzonesouthr   )r   Z	from_dictr   Zto_authority)Zutm_zoneZcrsZepsgr    r    r!   utm_zone2epsg_code  s    
rk   c           	      C   st   ddl m} || }| }| s<|ddkr<||fS t| }td}t	||}|
||\}}||fS )a  Convert x, y in the projection coordinates of the file to lon/lat in degree.

    Similar functionality also exists in utm.to_latlon() at:
        https://github.com/Turbo87/utm#utm-to-latitudelongitude

    Parameters: infile - str, GDAL supported file path
                x/y    - scalar or 1/2D np.ndarray, coordiantes in x and y direction
    Returns:    y/x    - scalar or 1/2D np.ndarray, coordinates in latitutde and longitude
    r   )gdalunitdegreez	epsg:4326)osgeorl   OpenZGetSpatialRefZIsProjectedGetAttrValuer   GetProjectionr   Z	from_proj	transform)	infiler[   yrl   dssrsZp_inZp_outZtransformerr    r    r!   	to_latlon#  s    

rx   c                 C   s6  d}d}|d }|d }dgd }dd t t| D }| d d | d d  }|| }d	| | d d  | }	||	 | d
 }
|| |	 d|
d   }d	| t|d|   d }|
d	| d	|   }t|d ||	  }||| |	  d|  }t|| |d  | }|t| ||  }t| d ||d< t| d | d |d< || d	 t|d | d d   | |d< t|d |d< t|d |d< |d |d< |d }|d	| d  }ttt|d |d  |d  }t	|d |d  t
|d |d   }d	t| }||fS )a  Calculate satellite height and ellpsoid local radius from orbital state vector.

    This is a simplified version of the following functions from ISCE-2:
    + isce.isceobj.Planet.xyz_to_llh()
    + isce.isceobj.Ellipsoid.localRadius()

    Parameters: xyz    - tuple of 3 float, orbital state vector
    Reference:  height - float, satellite altitude in m
                radius - float, Earth radius in m
    g   @TXAgk{?r   r      c                 S   s   g | ]}d gd qS )r   ry   r    rZ   ir    r    r!   r\   T  s     z'xyz_to_local_radius.<locals>.<listcomp>r   g      ?g      @g      @r   gUUUUUU?      ?)rangerc   mathrP   atan2degreesatantanradiansrO   r8   )Zxyzr]   e2a2Ze4Zr_llhZd_llhxy2pqr/   stuvwkDrE   bZlatgargradiusr    r    r!   xyz_to_local_radius@  s:    
.*,r   c                 C   sN   | \}}}}|||||g}|||||g}dd dd t||D  d }|S )zConvert the input bounding box in SNWE into WKT format POLYGON.

    Parameters: snwe    - list of 4 float, south, north, west and east in degrees/meters
    Returns:    polygon - str, WKT format POLYGON
    z	POLYGON((,c                 S   s   g | ]\}}| d | qS ) r    )rZ   lonlatr    r    r!   r\   z  s     z'snwe_to_wkt_polygon.<locals>.<listcomp>z)))joinzip)Zsnwerh   NWElatslonspolygonr    r    r!   snwe_to_wkt_polygonq  s
    "r   r   c              	   C   s  t | d t | d  }}|dkr.dd||f}g }|dk	r^t|d}	t|	 }W 5 Q R X d|krt|dV}	|	d |d |d |d |d	 f }
|	d
 |d |d |d |d	 f }W 5 Q R X n$d|  krt| d }t| d }t| d ||d d   }t| d ||d d   }|d |d  }|d	 |d  }|||d   }|||d   }|d	krtj|||d |||d f \}
}n>|dkrtj|||dd}
tj|||dd}nt	d
|nd}|d7 }t	|tj|
tjd}
tj|tjd}|| dkr|
jdkrN|
dd| }
|dd| }n<|
jd	kr|
dd|dd|f }
|dd|dd|f }|
|fS )a  Extract precise pixel-wise lat/lon.

    For meta dict in geo-coordinates OR geom_file with latitude/longitude dataset

    Returned lat/lon are corresponds to the pixel center

    Parameters: meta      - dict, including LENGTH, WIDTH and Y/X_FIRST/STEP
                box       - 4-tuple of int for (x0, y0, x1, y1)
                dimension - int, output lat/lon matrix dimension, 1 or 2
                y/xstep   - int, number of pixels to skip for each output pixel
    Returns:    lats      - 1/2D np.array for latitude  in size of (length, _width_)
                lons      - 1/2D np.array for longitude in size of (_length_, width)
    r
   r   Nr   r/   latituder   ry   r   	longituder   Y_STEPX_STEPr|   r;   y              ?T)r   r'   zun-supported dimension = {}zCan not get pixel-wise lat/lon!z]
meta dict is not geocoded and/or geometry file does not contains latitude/longitude dataset.r4   )r   h5pyFilelistr   r   r   mgridr   
ValueErrorr,   r   r   ndim)metaZ	geom_fileboxr   ystepxstepr   r   ds_listfr   r   rW   rV   Zlat0Zlon0Zlat_numZlon_numlat1Zlon1msgr    r    r!   get_lat_lon~  sV    (6
  
r   c           	         s  d   krtdt d t d  }} fdddD } fdddD }tj||ftjd	}tj||ftjd	}t|D ]}t|D ]}|d
 ||d |d
   |  ||d |d
   |  |||f< |d
 ||d |d
   |  ||d |d
   |  |||f< qq||fS )ab  Get 2D array of lat and lon for metadata dict in radar-coord.

    WARNING: This is a rough lat/lon value, NOT accurate!

    Parameters: meta : dict, including LENGTH, WIDTH and LAT/LON_REF1/2/3/4
    Returns:    lats : 2D np.array for latitude  in size of (length, width)
                lons : 2D np.array for longitude in size of (length, width)
    r   zJInput file is in geo-coordinates, use more accurate get_lat_lon() instead.r
   r   c                    s   g | ]}t  d | qS )z	LAT_REF{}r   r,   rz   r   r    r!   r\     s     z#get_lat_lon_rdc.<locals>.<listcomp>)r   r   ry      c                    s   g | ]}t  d | qS )z	LON_REF{}r   rz   r   r    r!   r\     s     r4   r   r   r   )r   r-   r   r   zerosr   r}   )	r   r   r   r   r   r   r   r{   jr    r   r!   get_lat_lon_rdc  s    	@Dr   c                 C   s"   d|  }|t |d d 8 }|S )a  Convert azimuth angle from ISCE los.rdr band2 into satellite orbit heading angle

    ISCE-2 los.* file band2 is azimuth angle of LOS vector from ground target to the satellite
        measured from the north in anti-clockwise as positive

    Below are typical values in deg for satellites with near-polar orbit:
        ascending  orbit: heading angle of -12  and azimuth angle of 102
        descending orbit: heading angle of -168 and azimuth angle of -102
    Z        v@r   round)rR   
head_angler    r    r!   azimuth2heading_angle  s    
r   c                 C   s"   d|  }|t |d d 8 }|S )zNConvert satellite orbit heading angle into azimuth angle as defined in ISCE-2.r   r   r   )r   rR   r    r    r!   rN     s    rN   c                 C   s   |dkr"|dk	rt |}ntd| tt| tt| d |tt| tt|  |tt|  }|S )a  Project east/north/up motion into the line-of-sight direction defined by incidence/azimuth angle.
    Parameters: e          - np.ndarray or float, displacement in east-west direction, east as positive
                n          - np.ndarray or float, displacement in north-south direction, north as positive
                u          - np.ndarray or float, displacement in vertical direction, up as positive
                inc_angle  - np.ndarray or float, local incidence angle from vertical, in the unit of degrees
                head_angle - np.ndarray or float, azimuth angle of the SAR platform along track direction
                             measured from the north with clockwise direction as positive, in the unit of degrees
                az_angle   - np.ndarray or float, azimuth angle of the LOS vector from the ground to the SAR platform
                             measured from the north with anti-clockwise direction as positive, in the unit of degrees
                             head_angle = 90 - az_angle
    Returns:    v_los      - np.ndarray or float, displacement in line-of-sight direction, moving toward satellite as positive

    Typical values in deg for satellites with near-polar orbit:
        For AlosA: inc_angle = 34, head_angle = -12.9,  az_angle = 102.9
        For AlosD: inc_angle = 34, head_angle = -167.2, az_angle = -102.8
        For  SenD: inc_angle = 34, head_angle = -168.0, az_angle = -102.0
    Nzaz_angle can not be None!rg   )rN   r   r   r8   rL   rO   )enr   r1   r   rR   Zv_losr    r    r!   enu2los  s    
&"r   c           	      C   sl   t | d }t | d }t| d }t| d }t| d }t| d }|||  }|||  }||||fS )a	  Get the 4 corners coordinates from metadata dict in geo-coordinates.
    Parameters: atr - dict
    Returns:    south, north, west, east - float, in degrees or meters
    Examples:   S, N, W, E = ut.four_corners(atr)
                SNWE = ut.four_corners(atr)
    r   r
   r   r   r;   r   )r   r   )	r   r   r   rV   rW   westnorthrj   eastr    r    r!   four_corners  s    r   c           	      C   sJ   |\}}t j| || |  ||  f \}}|d |d  |d k}|S )z5Get mask of pixels within circle defined by (x, y, r)r   )r   ogrid)	r[   ru   r   shaper   r   yyxxcmaskr    r    r!   get_circular_mask-  s     r   c              	   C   s  t | d }t | d }t|tr(|}n t|tr8|}n|dd }dd |D }z>t |d }t |d }t t|d	 }td
|||f  W n   zt|d }t|d }	t t|d	 }t	|t| d  t| d  }t	|	t| d  t| d  }td
||	| W n4   td|  td td td Y Y dS X Y nX tj| || | || f \}
}|d	 |
d	  |d	 k}|S )a  Return Index of Elements within a Circle centered at input pixel
    Parameters: atr : dictionary
                    containging the following attributes:
                    WIDT
                    LENGTH
                circle_par : string in the format of 'y,x,radius'
                    i.e. '200,300,20'          for radar coord
                         '31.0214,130.5699,20' for geo   coord
    Returns:    idx : 2D np.array in bool type
                    mask matrix for those pixel falling into the circle
                    defined by circle_par
    Examples:   idx_mat = ut.circle_index(atr, '200,300,20')
                idx_mat = ut.circle_index(atr, '31.0214,130.5699,20')
    r   r
   r   r   c                 S   s   g | ]}t |qS r    )r7   rz   r    r    r!   r\   O  s     z circle_index.<locals>.<listcomp>r   r   r   z+Input circle index in y/x coord: %d, %d, %dr   r   r;   r   z7Input circle index in lat/lon coord: {:.4f}, {:.4f}, {}z*
ERROR: Unrecognized circle index format: zSupported format:z4--circle 200,300,20            for radar coord inputz5--circle 31.0214,130.5699,20   for geo   coord input
)r   r6   tupler   replacesplitr   r   r   rintr,   r   )r   Z
circle_parr   r   Zcir_parZc_yZc_xr   Zc_latZc_lonru   r[   idxr    r    r!   circle_index6  sD    

""  
&r   rK   c                 C   s.   |\}}t | }|t || ||  }|S )zWrap data into a range.
    Parameters: data_in    : np.array, array to be wrapped
                wrap_range : list of 2 float, range to be wrapped into
    Returns:    data       : np.array, data after wrapping
    )r   r   mod)Zdata_inZ
wrap_rangeZw0Zw1datar    r    r!   wrapn  s    
r        @c                 C   sJ   t | } g }t| dd}t | sF|| | |N } t| dd}q|S )aH  Get all connected component with number of pixels larger than threshold
    Parameters: mask_in  : 2D np.array with zero as background and non-zero as foreground
                min_num_pixel : int/float, minimum number of pixels to be identified and output
    Returns:    mask_out : list of 2D np.array in np.bool_ format
    r   )min_num_pixel)r   r   get_largest_conn_componentallappend)mask_inr   mask_outZmask_ccr    r    r!   get_all_conn_componentsz  s    

r   c           	      C   s   t | jt j}t| d }t t | dd }||k rF|S t 	t | dd d }||k}|rt
jddddgd\}}|d |  |d | |d | |A  t
  |S )	a  Extract the largest connected component from an 2D array
       with zero as background value
    Parameters: mask_in  : 2D np.array with zero as background and non-zero as foreground
                min_num_pixel : int/float, minimum number of pixels to be identified and output
                display : bool, display the result or not.
    Returns:    mask_out : 2D np.array in np.bool_ format
    r   r   Nry         )nrowsncolsZfigsizer   )r   r   r   bool_r   labelmaxbincountflattenargmaxpltZsubplotsimshowshow)	r   r   displayr   labels	num_pixelZ	max_labelZfigaxr    r    r!   r     s     r   c                 C   s  ddl m} t| dk\}}t|dd|ddf}||}t|dk\}}t|dd|ddf}||\}	}
t|	}|| }||
|  }|	| }|rt	  t
| d |d   t|d |d g|d |d gd t  |||fS )at  Calculate the min distance between two regions of pixels marked by mask1 and mask2
    Parameters: mask1/2 : 2D np.array in size of (length, width) in np.bool_ format
    Returns:    pts1 : tuple of 2 int, bridge point in mask1, in (x, y)
                pts2 : tuple of 2 int, bridge point in mask2, in (x, y)
                min_dist : float, min euclidean distance
    r   )cKDTreerg   r   r   z-o)Zscipy.spatialr   r   wherehstackreshapequeryargminr   Zfigurer   Zplotr   )Zmask1Zmask2r   r   ru   r[   Zpts1treeZpts2distr   Zidx_minr   Zxy1min_distr    r    r!   min_region_distance  s"    
&r   linearc           
   	   C   s   ddl m} | j}t|d t|d f}ttjd|d d |d ddtjd|d d |d dd\}}t|dd|ddf}||| |dd||}	|	S )aa  Interpolate input 2D matrix into different shape.
    Used to get full resolution perp baseline from ISCE coarse grid baseline file.
    Parameters: inData : 2D array
                outShape : tuple of 2 int in (length, width)
                interpMethod : string, choose in [nearest, linear, cubic]
    Returns:    outData : 2D array in outShape
    r   )RegularGridInterpolatorr   F)r'   rg   )methodZbounds_error)	Zscipy.interpolater   r   r   arangemeshgridr   r   r   )
ZinDataZoutShapeZinterpMethodZRGIZinShapeZinPtsr   r   ZoutPtsZoutDatar    r    r!   interpolate_data  s     r   c                 C   sT   ddl m}m} |\}}|d||fd}||j| ddd tj|tjd}|S )ar  Create a 2D mask (numpy array in binary) from a polygon.

    Link: https://stackoverflow.com/questions/3654289/scipy-create-2d-polygon-mask
    Parameters: polygon - list of tuples of 2 int, e.g. [(x1, y1), (x2, y2), ...]
                shape   - list/tuple of 2 int, for length and width
    Returns:    mask    - 2D np.ndarray in bool in size of (length, width)
    r   )Image	ImageDrawLr   )outlinefillr4   )	ZPILr   r   newZDrawr   r   r   r   )r   r   r   r   r   r   imgmaskr    r    r!   polygon2mask  s    r  c                 C   sD   t t| d   }|d dkr(dS |d dkr8dS tdS dS )	zHgarrettdreyfus on Github: https://gist.github.com/garrettdreyfus/8153571z (y/n): r   ru   Tr   FzUhhhh... please enter N)r7   inputlowerstrip	yes_or_no)ZquestionZreplyr    r    r!   r    s    r  c                 C   sd   d}|   D ]R}t| | }||  kr@|t|| kr@|dksT||  krZ|dkrZt qd}q|S )z)Compare new attributes with exsiting onesFNoneT)r   r7   next)Zatr_newZatr_origupdatekeyvaluer    r    r!   update_attribute_or_not  s    $
r  c                 C   sj   dd }t j| d r&|| rf| S n@t jd t jD ],}|d}t j|| }||r8|  S q8dS )zTest if executable existsc                 S   s   t j| ot | t jS rY   )r^   r_   r`   accessX_OK)fpathr    r    r!   is_exe  s    zwhich.<locals>.is_exer   PATH"N)r^   r_   r   environpathsepr
  r   )programr  r_   Zexe_filer    r    r!   which   s    

r     c                 C   s   d}| dkr(d}|rt d d|ddfS zddlm}m} W n,   t d t d	 d}d|ddf Y S X tt | |}|dkrd}t d
 t dt  n|rt d|  z||||fW S    ||ddf Y S X dS )aE  Check parallel option based file num and installed module
    Link: https://joblib.readthedocs.io/en/latest/parallel.html
    Examples:
        num_cores, inps.parallel, Parallel, delayed = ut.check_parallel(len(file_list))
        Parallel(n_jobs=num_cores)(delayed(subset_file)(file, vars(inps)) for file in file_list)
    Tr   Fz2parallel processing is disabled for one input fileNr   )ParalleldelayedzCan not import joblibzparallel is disabled.zNparallel processing is disabled because min of the following two numbers <= 1:z(available cpu number of the computer: {}z&parallel processing using %d cores ...)r   Zjoblibr  r  minr^   	cpu_countr,   )Zfile_numr   ZmaxParallelNumZenable_parallelr  r  Z	num_coresr    r    r!   check_parallel  s0    r!  c                 C   sL   | }|D ]6}| ds0d|kr0|d| d7 }q|d| 7 }qt| dS )zprint the command line with "" for arguments containing *.

    Parameters: script_name - str, e.g. prep_isce.py
                args        - list(str), list of input arguments
    -*z "r  r   N)
startswithr   )Zscript_nameargscmdr   r    r    r!   print_command_line9  s    r'  LTol?c                 C   s   t | } | jdkr*| jd }| |d} |dkr@t j| dd}| jdkrht |ddd| jd f}t jt | | dd| }|S )a  Compute the median absolute deviation of the data along the LAST axis.

    This function is also included as:
        scipy.stats.median_abs_deviation() in scipy v1.5.0
            https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.median_abs_deviation.html
        statsmodels.robust.mad() in statsmodels
            https://www.statsmodels.org/dev/generated/statsmodels.robust.scale.mad.html

    The differences are:
        1. scipy: out = out / scale while mintpy: out = out * scale
        2. scipy propagates nan by default, while mintpy omit nan by default.

    The following two are equivalent for a 2D np.ndarray X:
        mintpy.utils.utils0.median_abs_deviation(X)
        scipy.stats.median_abs_deviation(X, axis=-1, center=np.nanmedian, scale=1./0.67449, nan_policy='omit')

    Parameters: data   - 1/2D np.ndarray, input array
                center - 0/1D np.ndarray or None
                scale  - float, the normalization constant
    Returns:    mad    - 0/1D np.ndarray
    r   r   rg   N)axisr   )r   r   r   r   r   	nanmedianr   rM   )r   centerscaleZntimemadr    r    r!   median_abs_deviationM  s    



r.        @c                 C   s.   |dkrt | }t| |d}|||  }|S )zvcalculate rms_threshold based on the standardised residual

    Outlier detection with median absolute deviation.
    N)r+  )r   r*  r.  )r   r+  cutoffr-  	thresholdr    r    r!   median_abs_deviation_thresholdt  s
    
r2  c                 C   s~   t |  } |dk	rLt | }| j|jkrDtd| j|j| |8 } | t |   } t t | d | jd  }|S )z5Calculate the root-mean-square error between x and y.Nz+Input x & y have different size: {} vs. {}!r   r   )	r   r   r   sizer   r,   isnanrP   sum)r[   ru   Zrmser    r    r!   root_mean_sq_error  s    r6  c                 C   sB   t ttt| }t| | }|| kr2|}n|d|  }|S )z@Return the most significant digit of input number and ceiling it
   r   r   floorlog10rM   r   )r[   digitZx_roundZx_ceilr    r    r!   	ceil_to_1  s    r<  c                 C   s$   t ttt| }t| | S )z1Return the most significant digit of input numberr8  )r[   r;  r    r    r!   
round_to_1  s    r=  c                 C   s"   t | d d d }|t jS )zfRound a float up to the next odd integer .
    Link: https://stackoverflow.com/questions/31648729
    r   r   )r   ceilastypeint16)r[   ru   r    r    r!   round_up_to_odd  s    rA  c                 C   s&   t dt t | }t |}|S )z7Given a number x, find the highest power of 2 that <= xr   )r   powerr9  log2r@  )r[   resr    r    r!   highest_power_of_2  s    
rE  c                 C   s<   ddl m} || }dd ||D }|dkr8|d }|S )zReturn the k most common item in the list L.
    Examples:
        5, 8 = most_common([4,5,5,5,5,8,8,8,9], k=2)
        'duck' = most_common(['goose','duck','duck','dog'])
        'goose' = most_common(['goose','duck','duck','goose'])
    r   )Counterc                 S   s   g | ]}|d  qS )r   r    rz   r    r    r!   r\     s     zmost_common.<locals>.<listcomp>r   )collectionsrF  most_common)r  r   rF  cntZitem_mmr    r    r!   rH    s    rH  c                 C   s*   zt |  W dS  tk
r$   Y dS X dS )a	  Check string is a number.
    Not using str.isnumeric() because it can not handle floating point nor negative sign.
    Link: https://elearning.wsldp.com/python3/python-check-string-is-a-number/
    Parameters: string - str, a string
    Returns:    True/False
    TFN)r   r   )stringr    r    r!   	is_number  s
    rK  )r   T)Nr   T)F)N)N)NNr   r   r   )NN)r   )r   F)F)r   )r   Tr  )Nr(  )Nr/  )N)r   )9r^   r~   r   numpyr   Zmatplotlib.pyplotZpyplotr   scipyr   Zpyprojr   r   r   SPEED_OF_LIGHTr#   Kr"   r3   r:   r=   rG   rX   rf   rk   rx   r   r   r   r   r   rN   r   r   r   r   r*   r   r   r   r   r   r  r  r  r  r!  r'  r.  r2  r6  r<  r=  rA  rE  rH  rK  r    r    r    r!   <module>   s`   
)
B#

+
1
J
#	8




(
'


