B
    QaS                 @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	m
Z
mZmZmZ d dlmZmZmZ d dlT d.ddZd/d	d
Zd0ddZd1ddZd2ddZd3ddZd4ddZd5ddZd6ddZd7dd Ze dfd!d"Zd8d#d$Zd9d%d&Z d:d'd(Z!d;d*d+Z"d<d,d-Z#dS )=    N)derampifgramStack
timeseriesgeometryDatasetNames)ptimereadfile	writefile)*c             C   s   t | }|dkr.ddt|d t|d f}t|d |d  d }t|d |d  d }d| krt|d }t|d	 }t|d
 }t|d }|||  }	|||  }
nD|||d |d f}tt j| d|dd }	tt j| d|dd }
|	|
fS )z#Get the lat/lon of the scene centerNr   WIDTHLENGTH         Y_FIRSTX_FIRSTY_STEPX_STEPlatitude)datasetNamebox	longitude)r   read_attributeintkeysfloatread)	geom_filer   metaZcol_cZrow_clat0lon0lat_steplon_steplat_cZlon_cZbox_c r#   I/home/centos/operations/rsmas_insar/sources/MintPy/mintpy/utils/utils1.pyget_center_lat_lon   s     
r%   maskTempCoh.h5	quadraticc       	      C   s  |dkrt d | }ndtj| d }tj|d d }t|||gdddkrt|| d	dkrtj| sd
|  }|d7 }t|nt| |||d}t d|  t	|j
||d}t d|  tj|tdt}|dddf tj }t|dddf }||fS )a  Calculate deramped standard deviation in space for each epoch of input timeseries file.
    Parameters: timeseries_resid_file - string, timeseries HDF5 file,
                    e.g. timeseries_ERA5_demErrInvResid.h5
                mask_file - string, mask file, e.g. maskTempCoh.h5
                ramp_type - string, ramp type, e.g. linear, quadratic, no for do not remove ramp
    Returns:    std_list  - list of float, standard deviation of deramped input timeseries file
                date_list - list of string in YYYYMMDD format, corresponding dates
    Example:    import mintpy.utils.utils as ut
                std_list, date_list = ut.get_residual_std('timeseries_ERA5_demErrInvResid.h5',
                                                          'maskTempCoh.h5')
    nozNo ramp removalz
{}_ramp.h5r   z_std.txtF)out_filein_filecheck_readablerun)r)   r*   z-Can not find input timeseries residual file: z$
Re-run dem_error.py to generate it.)	ramp_type	mask_filer)   zBcalculating residual standard deviation for each epoch from file: )maskFileoutFilezread timeseries RMS from file: )dtypeNr   )printformatospathsplitextrun_or_skipisfile	Exception
run_derampr   timeseries_stdnploadtxtbytesastypestrfloat32tolistlist)	timeseries_resid_filer.   r-   deramped_fileZstd_filemsgfcZstd_list	date_listr#   r#   r$   get_residual_std0   s,    
rI   c       	      C   s0  |dkrt d | }ndtj| d }tjtjtj|dtj|d }t|||gdddkrt|| d	dkrtj	| sd
|  }|d7 }t
|nt| |||d}t d|  t|j||d}t d|  tj|tdt}|dddf tj }t|dddf }|||fS )aV  Calculate deramped Root Mean Square in space for each epoch of input timeseries file.
    Parameters: timeseries_resid_file : string,
                    timeseries HDF5 file, e.g. timeseries_ERA5_demErrInvResid.h5
                mask_file : string,
                    mask file, e.g. maskTempCoh.h5
                ramp_type : string,
                    ramp type, e.g. linear, quadratic, no for do not remove ramp
    Returns:    rms_list : list of float,
                    Root Mean Square of deramped input timeseries file
                date_list : list of string in YYYYMMDD format,
                    corresponding dates
                rms_file : string, text file with rms and date info.
    Example:
        import mintpy.utils.utils as ut
        rms_list, date_list = ut.get_residual_rms('timeseriesResidual.h5', 'maskTempCoh.h5')
    r(   zNo ramp removalz
{}_ramp.h5r   z
rms_{}.txtF)r)   r*   r+   r,   )r)   r*   z-Can not find input timeseries residual file: z$
Re-run dem_error.py to generate it.)r-   r.   r)   z4
calculating residual RMS for each epoch from file: )r/   r0   z(read timeseries residual RMS from file: )r1   Nr   )r2   r3   r4   r5   r6   joindirnameabspathr7   r8   r9   r:   r   timeseries_rmsr<   r=   r>   r?   r@   rA   rB   rC   )	rD   r.   r-   rE   Zrms_filerF   rG   Zrms_listrH   r#   r#   r$   get_residual_rms\   s.    
rN   maskConnComp.h5c             C   sX   t | }|d }|dkr,t| j|d}ntd|  dS d|d< tj|||d |S )zDGenerate mask file for non-zero value of input multi-group hdf5 file	FILE_TYPEr   )r   z5Only ifgramStack file is supported for now, input is Nmask)r)   metadata)r   r   r   nonzero_maskr2   r   write)Filer)   r   atrkrQ   r#   r#   r$   rS      s    
rS   	coherenceFTc           	   C   s  dd }t | }	|	d }
|s:ddt|	d t|	d f}|
dkrF|ntjtj| d }|dkrjd	nd
}||rxdnd7 }|| d }| |rtd || \}}||fS d	tj| }d	|}d	|}d	|}yt
|d}| }|  |r,ydd |D d }W n   d}Y nX n|}ydd |D d }W n   d}Y nX ||kr||krt|| |gdddkrt|d  ||\}}||fS W n   Y nX d|krd}nd}|
dkrt| }|j
dd |j||||||d\}}|j}|j}|  n|
dkr<t| j||||d \}}nt j| |d!d }|rtj|rtd"|  t j|d#|d$d }tj||t|k< |dk	rd%|||k< d|||k< t|}tj| g}|rtd&|  t
|d'}||| | |  t|}|
dkrZ|d( xtt|D ].}|d)|| || || || |f  q&W n8|d* x,t|D ] }|d+|| || f  qnW |  t|d%kr|d }|d }||fS ),a  Read/Calculate Spatial Average of input file.

    If input file is text file, read it directly;
    If input file is data matrix file:
        If corresponding text file exists with the same mask file/AOI info, read it directly;
        Otherwise, calculate it from data file.

        Only non-nan pixel is considered.
    Parameters: File        - string, path of input file
                maskFile    - string, path of mask file, e.g. maskTempCoh.h5
                box         - 4-tuple defining the left, upper, right, and lower pixel coordinate
                saveList    - bool, save (list of) mean value into text file
                reverseMask - bool, perform analysis within masked regions instead of outside of them
                threshold   - float, calculate area ratio above threshold instead of spatial average
    Returns:    meanList    - list for float, average value in space for each epoch of input file
                dateList    - list of string for date info
                              date12_list, e.g. 101120-110220, for interferograms/coherence
                              date8_list, e.g. 20101120, for timeseries
                              file name, e.g. velocity.h5, for all the other file types
    Example:    meanList = spatial_average('inputs/ifgramStack.h5')[0]
                meanList, date12_list = spatial_average('inputs/ifgramStack.h5',
                                                        maskFile='maskTempCoh.h5',
                                                        saveList=True)
    c             S   sP   t j| tdt}dd |d d df D }dd |d d df D }||fS )N)r1   c             S   s   g | ]}t |qS r#   )r   ).0ir#   r#   r$   
<listcomp>   s    z;spatial_average.<locals>.read_text_file.<locals>.<listcomp>r   c             S   s   g | ]}|qS r#   r#   )rY   rZ   r#   r#   r$   r[      s    r   )r<   r=   r>   r?   r@   )fnameZ
txtContentmeanListdateListr#   r#   r$   read_text_file   s    z'spatial_average.<locals>.read_text_filerP   r   r
   r   r   NZ
SpatialAvgZ	AreaRatioZRevMsk z.txtz;Input file is spatial average txt already, read it directlyz# Data file: {}
z# Mask file: {}
z# AOI box: {}
z# Threshold: {}
rc             S   s   g | ]}d |kr|qS )z
# AOI box:r#   )rY   rZ   r#   r#   r$   r[      s    z#spatial_average.<locals>.<listcomp>c             S   s   g | ]}d |kr|qS )z# Mask file:r#   )rY   rZ   r#   r#   r$   r[      s    F)r)   r*   r+   skipz! already exists, read it directlyoffsetT)	print_msg)r   r/   r   	useMedianreverseMask	thresholdr   )r/   r   rf   rg   )r   zmask from file: rQ   )r   r   r   z-write average value in space into text file: wz'#	DATE12		Mean	Btemp/days	Bperp/m		Num
z%s	%.4f	%8.0f	%8.1f	%d
z#	DATE12		Mean
z%s	%.4f
)r   r   r   r4   r5   r6   basenameendswithr2   r3   open	readlinescloser7   r   spatial_averagepbaseIfgramtbaseIfgramr   r   r8   r<   nannanmeanrT   lenrange) rU   r   r/   r   ZsaveListZcheckAoirf   rg   r_   rV   rW   prefixsuffixZtxtFiler]   r^   Z	file_lineZ	mask_lineZaoi_lineZ
thres_lineZfllinesZaoi_line_origZmask_line_origre   objpbasetbasedatarQ   ZnumLinerZ   r#   r#   r$   rn      s    
$

















*
 rn   c       
      C   sv  t j| |d}|d }|dkrBtd|  t | d }|| fS |dkrtj| d }|s|dkr|d	krtd
}qd|krd}qd|}nF|dkr|| krtj| 	dd 	|d }d|}n
d| }|rtj
|rt |d }	|	|fS |dkr:t| j|d}	d|kr0d|d< d|d< n||d< n|dkrXt|  }	d|d< |rntj|	||d |	|fS )a  Calculate temporal average of multi-temporal dataset, equivalent to stacking
    For ifgramStakc/unwrapPhase, return average phase velocity

    Parameters: File : string, file to be averaged in time
                datasetName : string, dataset to be read from input file, for multiple
                    datasets file - ifgramStack - only
                    e.g.: coherence, unwrapPhase
                updateMode : bool
                outFile : string, output filename
                    None for auto output filename
                    False for do not save as output file
    Returns:    dataMean : 2D array
                outFile : string, output file name
    Examples:   avgPhaseVel = ut.temporal_average('ifgramStack.h5', datasetName='unwrapPhase')[0]
                ut.temporal_average('ifgramStack.h5', datasetName='coherence',
                                    outFile='avgSpatialCoh.h5', updateMode=True)
    )r   rP   )r   r   zBWARNING: input file is not multi-temporal file: {}, return itself.r   Nr   r   rX   zavgSpatialCoh.h5unwrapPhasezavgPhaseVelocity.h5zavg{}.h5r   zavgDisplacement{}.h5velocityzm/yearUNITdisplacement)r)   rR   )r   r   r2   r3   r   r4   r5   r6   ri   splitr8   r   temporal_averager   r   rT   )
rU   r   Z
updateModer0   rV   rW   r{   extZprocessMarkZdataMeanr#   r#   r$   r   2  sF     





r   c       
      C   s   | sg S t | tr| g} dd | D } g }xBtt| D ]2}| | }t|}|ttt|t| 7 }q8W |rdd |D }|dk	rxlt|D ]`}t	|}|dkrd|
 kr|| q|dkrd|
 kr|| qd|}	t|	qW |S )	aR  Get all existed files matching the input list of file pattern
    Parameters: file_list - string or list of string, input file/directory pattern
                abspath - bool, return absolute path or not
                coord - string, return files with specific coordinate type: geo or radar
                    if none, skip the checking and return all files
    Returns:    file_list_out - list of string, existed file path/name, [] if not existed
    Example:    file_list = get_file_list(['*velocity*.h5','timeseries*.h5'])
                file_list = get_file_list('timeseries*.h5')
    c             S   s   g | ]}|d kr|qS )Nr#   )rY   xr#   r#   r$   r[     s    z!get_file_list.<locals>.<listcomp>c             S   s   g | ]}t j|qS r#   )r4   r5   rL   )rY   rZ   r#   r#   r$   r[     s    N)geor   )ZradarZrdrZrdcz"un-recognized input coord type: {})
isinstancer@   rt   rs   globsortedrC   setr   r   r   remover3   
ValueError)
	file_listrL   coordZfile_list_outrZ   Zfile0Z
file_list0r\   rV   rF   r#   r#   r$   get_file_listt  s0    


 

r   c                s   | sHdddddddg}dd	d
g}g } x"|D ] |  fdd|D 7 } q*W g }yt | }W n&   |r|td td t|  dS d}xP|D ]H}t|}x8dD ]0}	ytj||	ddd }
|}P W q   Y qX qW qW |s|rtd dS | rtj|}|S )a  Find lookup table file with/without input file pattern
    Parameters: filePattern - list of str
                abspath     - bool, return absolute path or not
                print_msg   - bool, printout message or not
    Returns:    outFile     - str, path of the lookup file
    zgeometryRadar.h5zgeometryGeo_tight.h5zgeometryGeo.h5zgeomap*lks_tight.transzgeomap*lks.transzsim*_tight.UTM_TO_RDCzsim*.UTM_TO_RDCinputsr`   z	../inputsc                s   g | ]}t j |qS r#   )r4   r5   rJ   )rY   r\   )rK   r#   r$   r[     s    z#get_lookup_file.<locals>.<listcomp>z-ERROR: No geometry / lookup table file found!zIt should be like:N)r   
rangeCoordF)r   rd   r   z.No lookup table info range/lat found in files.)r   r2   r   r   r   r4   r5   rL   )ZfilePatternrL   rd   ZfileListZdirListZ
existFilesr0   r\   rV   dsNamedsetr#   )rK   r$   get_lookup_file  sF    




r   r   c                s   t | tr| g} x"| D ]}|tkrtd|qW s@t fdddD }t||d}t|dkrz|rvt	d dS x0t
|D ]$ t fd	d
| D r|  qW t|dkr|rt	d|  dS |d }|rtj|}|S )z4Find geometry file containing input specific datasetz&unrecognized geometry dataset name: {}c                s   g | ]}t j |qS r#   )r4   r5   rJ   )rY   rZ   )work_dirr#   r$   r[     s    z%get_geometry_file.<locals>.<listcomp>)z*geometry*.h5z*/*geometry*.h5z../*/geometry*.h5)r   r   zNo geometry file found.Nc             3   s   | ]}|t  kV  qd S )N)r   get_dataset_list)rY   r   )r\   r#   r$   	<genexpr>  s    z$get_geometry_file.<locals>.<genexpr>z&No geometry file with dataset {} found)r   r@   r   r   r3   r4   getcwdr   rs   r2   rC   anyr   r5   rL   )Z	dset_listr   r   rL   rd   r   
fname_listr   r#   )r\   r   r$   get_geometry_file  s0    

r   =c             C   sl  d}t | }x0| D ]$\}}|| kr|| |krd}qW |sTtd|   | S | d }t|d}xt| dD ]}	dd |	 |d	D }
|	d
sFt	|
d	krF|
d }t
|
d	 dddd  }|dd}|| krF|| |krFt|d | |	d }|||| }|	||d	}	td||||  ||	 qrW |  t||  | S )zEUpdate option value in template_file with value from input extra_dictFTz)No new option value found, skip updating z.tmprh   ra   c             S   s   g | ]}|  qS r#   )strip)rY   rZ   r#   r#   r$   r[     s    z(update_template_file.<locals>.<listcomp>r   )%#r   
r`   r   r	   z\*z[\s]*z    {}: {} --> {})r   read_templateitemsr   r2   rk   r   r   
startswithrs   r@   replacerefindallr3   rT   rm   shutilmove)template_fileZ
extra_dict	delimiterupdateZ	orig_dictkeyvalueZtmp_fileZf_tmplinecZold_value_strZnew_value_strr#   r#   r$   update_template_file  s2    

 r   c             C   s   t | }t||}|s$td | S t| d}xt| D ]p\}}|dksV|dkry"|j	| |rvtd
| W q   Y qX q>t||j|< |r>td
|t| q>W |  | S )a#  Add/update input attribute into File
    Parameters: File - string, path/name of file
                atr_new - dict, attributes to be added/updated
                    if value is None, delete the item from input File attributes
    Returns:    File - string, path/name of updated file
    zeAll updated (removed) attributes already exists (do not exists) and have the same value, skip update.zr+NoneNz	remove {}z{} = {})r   r   update_attribute_or_notr2   h5pyrU   iterr   attrspopr3   r@   rm   )rU   atr_newrd   rV   r   fr   r   r#   r#   r$   add_attribute  s&    

r   c       	      C   s@  | s| ddfS g }g }x2| D ]*}t |}||d  ||d  qW |sVt|}|sbt|}t| }||t|ks||t|kr6td td td td||f  td xXtt| D ]H}|| |ks|| |krtd	| | || || f  |	| |  qW td
t
t|  td |||fS )zXCheck file size in the list of files, and drop those not in the same size with majority.Nr
   r   z-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%z2WARNING: Some files may have the wrong dimensions!z$All files should have the same size.z9The width and length of the majority of files are: %s, %szNBut the following files have different dimensions and thus will not be loaded:z%s    width: %s  length: %sz
Number of files left: z,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)r   r   appendmost_commonrC   countrs   r2   rt   r   r@   )	r   Z
mode_widthZmode_lengthZ
width_listZlength_listr\   rV   Zfname_list_outrZ   r#   r#   r$   check_file_size=  s:    


r   c             C   s4   yt | |dd }t| W n   d}Y nX |S )a  Check if any file in the file list 1) exists and 2) readable
    Parameters: file_list : list of string, file name with/without wildcards
                abspath   : bool, return absolute file name/path or not
    Returns:    file_path : string, found file name/path; None if not.
    )rL   r   N)r   r   r   )r   rL   filer#   r#   r$   is_file_existh  s    
r   c             C   s   | sdS t | tr| g} tdd | D s.dS |r|yt| d }|d }W n.   |rjtd| d  t| d  dS |rt	|}|rt
dd |D }td	d | D }||krdS |rtd
| | dS )a  Check whether to update out_file or not.
    return run if any of the following meets:
        1. out_file is empty, e.g. None, []
        2. out_file is not existed
        3. out_file is not readable by readfile.read_attribute() when check_readable=True
        4. out_file is older than in_file, if in_file is not None
    Otherwise, return skip.

    If in_file=None and out_file exists and readable, return skip

    Parameters: out_file : string or list of string, output file(s)
                in_file  : string or list of string, input file(s)
                check_readable : bool, check if the 1st output file has attribute 'WIDTH'
                print_msg      : bool, print message
    Returns:    run/skip : str, whether to update output file or not
    Example:    if ut.run_or_skip(out_file='timeseries_ERA5_demErr.h5', in_file='timeseries_ERA5.h5'):
                if ut.run_or_skip(out_file='exclude_date.txt',
                                  in_file=['timeseries_ERA5_demErrInvResid.h5',
                                           'maskTempCoh.h5',
                                           'smallbaselineApp.cfg'],
                                  check_readable=False):
    r,   c             s   s   | ]}t j|V  qd S )N)r4   r5   r8   )rY   rZ   r#   r#   r$   r     s    zrun_or_skip.<locals>.<genexpr>r   r
   z'{} exists, but can not read, remove it.c             S   s   g | ]}t j|qS r#   )r4   r5   getmtime)rY   rZ   r#   r#   r$   r[     s    zrun_or_skip.<locals>.<listcomp>c             S   s   g | ]}t j|qS r#   )r4   r5   r   )rY   rZ   r#   r#   r$   r[     s    z({} exists and is newer than {} --> skip.rb   )r   r@   allr   r   r2   r3   r4   r   r   maxmin)r)   r*   r+   rd   rV   widthZt_inZt_outr#   r#   r$   r7   v  s2    
r7   "defaults/smallbaselineApp_auto.cfgc       	      C   s   t jt jtj|}t|}d}| |d	 }|dkrF|| }|dkrVd|d< x4| 
 D ](\}}|dkr`|| kr`|| | |< q`W dddddd	}x4| 
 D ](\}}|	 }|| kr|| | |< qW | S )
z7Replace auto value based on the input auto config file.zmintpy.compute.clusterautolocalZ40zmintpy.compute.numWorkerTFN)yestruer(   falsenone)r4   r5   rJ   rK   mintpy__file__r   r   getlowerr   r   )	ZtemplateDictZ	auto_fileZtemplateAutoFileZtemplateAutoDictZcluster_keyZclusterr   r   ZspecialValuesr#   r#   r$   check_template_auto_value  s*    
r   c             C   sZ  t   }t| }|d }t|d }	t|d }
td||  |sbtj| \}}d||}|dkrn| }tj	|rt
|d }td|  ntj|	|
ftjd	}td
 d}|r6tjtj| d }tjtj|d|}t|d6}|d|  |d| |d| W dQ R X |dkrDtj|| dd td t|  }t|}tj|d}xt|D ]}|rt|d}|d||  W dQ R X tj
| || dd }t|||||dd }tj||d||d d|	d|
gdd |j|d d|d |d qW |  td| n|dkrt| }|jdd  |sld!}t !| d<}|| }d"|}||" kr|| }td#| n,|j#||j$|	|
ftj%ddd$}td%| tj|j$d}xt|j$D ]}|r4t|d }|dt&|j'|  W dQ R X ||ddddf }t|||||dd }|||ddddf< |j|d d|d |j$d qW |  td|  W dQ R X nr|rt|d}|d|d  W dQ R X t
| d }t|||||dd }td&| tj||| d' t(t   | d(\}}td)|| |S )*a   Remove ramp from each 2D matrix of input file
    Parameters: fname     : str, data file to be derampped
                ramp_type : str, name of ramp to be estimated.
                mask_file : str, file of mask of pixels used for ramp estimation
                out_file  : str, output file name
                datasetName     : str, output dataset name, for ifgramStack file type only
                save_ramp_coeff : bool, save the estimated ramp coefficients to text file
    Returns:    out_file  : str, output file name
    rP   r   r
   zremove {} ramp from file: {}z	{}_ramp{}r   r   zread mask file: )r1   zuse mask of the whole areaNzrampCoeff_{}.txtrh   z# input  file: {}
z# output file: {}
z# ramp type: {}
r   T)ref_filerd   z,estimating phase ramp one date at a time ...)maxValueaz{}    )r   )r-   rR   
coeff_filer   F)r   blockrd   z{}/{})rv   zfinished writing to file: {})rd   r|   z{}_rampzaccess HDF5 dataset /{})shaper1   chunkscompressionzcreate HDF5 dataset /{}zwriting >>> {})r)   r   <   z'time used: {:02.0f} mins {:02.1f} secs.))timer   r   r   r2   r3   r4   r5   r6   r8   r   r<   onesbool_ri   rJ   rK   rk   rT   r   layout_hdf5r   get_date_listrs   r   progressBarrt   r   write_hdf5_blockr   rm   r   r   rU   r   create_dataset	numIfgramrA   r@   
date12Listdivmod)r\   r-   r.   r)   r   Zsave_ramp_coeff
start_timerV   rW   lengthr   fbasefextrQ   r   r   rH   num_dateprog_barrZ   r{   rx   dsZ	dsNameOutZdsOutmsr#   r#   r$   r:     s    


$


$&r:   )N)r&   r'   )r&   r'   )rO   N)rX   NNFTFN)rX   FN)FN)NFT)Nr   TT)r   )NN)T)NTT)r   )NNNF)$r4   r   r   r   r   r   numpyr<   r   mintpy.objectsr   r   r   r   mintpy.utilsr   r   r   mintpy.utils.utils0r%   rI   rN   rS   rn   r   r   r   r   r   dictr   r   r   r7   r   r:   r#   r#   r#   r$   <module>   s8   

,
3
 
 
B
*
5
"
%#
+

9
#