U
     c                  
   @   s`  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 d dlm	Z	m
Z
 d dlmZ d dlmZ d dlmZmZmZmZmZ dZdd	d
ddddgZedZdZdZd?ddZd@ddZdd Zdd ZdAddZ dBd d!Z!d"d# Z"dCd$d%Z#dDd'd(Z$dEd*d+Z%dFd-d.Z&dGd/d0Z'dHd2d3Z(d4d5 Z)dId7d8Z*dJd9d:Z+dKd;d<Z,e-d=kr\e,ej.d>d  dS )L    N)linalg)ifgramStackcluster)decorrelation)get_template_content)readfile	writefileptimeutils	arg_utilszmintpy.networkInversion.obsDatasetName	numIfgram
weightFuncmaskDatasetmaskThresholdminRedundancyminNormVelocityinvert_networku  references:
  Berardino, P., Fornaro, G., Lanari, R., & Sansosti, E. (2002). A new algorithm for surface
    deformation monitoring based on small baseline differential SAR interferograms. IEEE TGRS,
    40(11), 2375-2383. doi:10.1109/TGRS.2002.803792
  Pepe, A., and Lanari, R. (2006), On the extension of the minimum cost flow algorithm for phase unwrapping
    of multitemporal differential SAR interferograms, IEEE-TGRS, 44(9), 2374-2383.
  Perissin, D., and Wang, T. (2012), Repeat-pass SAR interferometry with partially coherent targets, IEEE TGRS,
    50(1), 271-280, doi:10.1109/tgrs.2011.2160644.
  Samiei-Esfahany, S., Martins, J. E., Van Leijen, F., and Hanssen, R. F. (2016), Phase Estimation for Distributed
    Scatterers in InSAR Stacks Using Integer Least Squares Estimation, IEEE TGRS, 54(10), 5671-5687.
  Seymour, M. S., and Cumming, I. G. (1994), Maximum likelihood estimation for SAR interferometry, 1994.
    IGARSS '94., 8-12 Aug 1994.
  Yunjun, Z., Fattahi, H., and Amelung, F. (2019), Small baseline InSAR time series analysis: Unwrapping error
    correction and noise reduction, Computers & Geosciences, 133, 104331, doi:10.1016/j.cageo.2019.104331.
  Yunjun, Z., Fattahi, H., Brancato, V., Rosen, P., Simons, M. (2021), Oral: Tectonic displacement mapping from SAR
    offset time series: noise reduction and uncertainty quantification, ID 590, FRINGE 2021, 31 May – 4 Jun, 2021, Virtual.
a  example:
  ifgram_inversion.py inputs/ifgramStack.h5 -t smallbaselineApp.cfg --update
  ifgram_inversion.py inputs/ifgramStack.h5 -w no  # turn off weight for fast processing
  ifgram_inversion.py inputs/ifgramStack.h5 -c no  # turn off parallel processing
  # offset
  ifgram_inversion.py inputs/ifgramStack.h5 -i rangeOffset   -w no -m waterMask.h5 --md offsetSNR --mt 5
  ifgram_inversion.py inputs/ifgramStack.h5 -i azimuthOffset -w no -m waterMask.h5 --md offsetSNR --mt 5
c              
   C   s  d}t d t d t }tdd }tj||||| d}|jddd |jd	d
ddd |jddddtdd |jddddd |jddddddd |jdd d!d |jd"d#d$d%d&d' |	d(d)}|jd*d+d,d-d-d.d/d0hd1d2 |jd3d4d5d6d' |jd7d8d9d:d9gd;d2 |jd<d=d%d>d' |	d?d@}|jdAdBdCdDdEd |jdFdGdHdIdJt
dKdLdM |jdNdOdPdQdJt
dRdSdM t|}t|}|jdTdUd%dVd' |S )WNz2Invert network of interferograms into time-series.
.)synopsisdescriptionepilog
subparsersifgramStackFilez(interferograms stack file to be inverted)helpz-tz
--templatetemplateFileztemplate text file with options)destr   z-iz-dz--dsetr   zkdataset name of unwrap phase / offset to be used for inversion
e.g.: unwrapPhase, unwrapPhase_bridging, ...)r   typer   z-mz--water-maskwaterMaskFilez4Skip inversion on the masked out region, i.e. water.z-oz--outputoutfile   )ZTS_FILEZ	TCOH_FILEZNUM_INV_FILEz)Output file name. (default: %(default)s).)r   nargsmetavarr   z
--ref-dateref_datez&Reference date, first date by default.z--skip-referencez
--skip-refskip_ref
store_truez:[for offset and testing] do not apply spatial referencing.)r   actionr   solverz(solver for the network inversion problemz-wz--weight-funcr   varZfimcohnozfunction used to convert coherence to weight for inversion:
var - inverse of phase variance due to temporal decorrelation (default)
fim - Fisher Information Matrix as weightcoh - spatial coherence
no  - no/uniform weight)r   defaultchoicesr   z--min-norm-phaser   store_falsezoEnable inversion with minimum-norm deformation phase, instead of the default minimum-norm deformation velocity.z--normresidualNormL2L1z;Optimization mehtod, L1 or L2 norm. (default: %(default)s).z
--calc-covcalcCovzdCalculate time-series STD via linear propagation from the network of interferograms or offset pairs.maskz&mask observation data before inversionz--mask-dsetz--mask-datasetz--mdr   zBdataset used to mask unwrapPhase, e.g. coherence, connectComponentz--mask-thresz--mask-thresholdz--mtr   NUM皙?zIthreshold to generate mask when mask is coherence (default: %(default)s).)r   r$   r   r-   r   z--min-redunz--min-redundancyz--mrr         ?zWminimum redundancy of interferograms for every SAR acquisition. (default: %(default)s).z--updateupdate_modezEnable update mode, and skip inversion if output timeseries file already exists,
readable and newer than input interferograms file)	REFERENCETEMPLATEEXAMPLE__name__splitr   create_argument_parseradd_argumentstradd_argument_groupfloatadd_memory_argumentadd_parallel_argument)r   r   r   nameparserr)   r4    rG   N/home/exouser/operations/rsmas_insar/sources/MintPy/mintpy/ifgram_inversion.pycreate_parserA   sp        



	


rI   c           
      C   s8  t  }|j| d}t|j}|d dkr<td|d |jrTt|j|\}}nt	 }t
tj|j|j|_|jr|jdkrtd d |_|jrtj|jsd |_|js`d|_dd	d
d}d}|| kr|| r||  dd}| j|| 7  _td| td|j t|j}|jdd |j|jkr`d|j|j}	t|	d|j krd| krd| krd|_|js"|jdrtj|jdrdddg|_ndddg|_nH|jdrd d!d"g|_n,|jd#rd$d%d&g|_ntd'|j|j\|_|_ |_!|S )(N)args	FILE_TYPE)r   z0input is {} file, support ifgramStack file only.1zJWARNING: number of workers is 1, turn OFF parallel processing and continueunwrapPhaseZ	_bridgingZ_phaseClosureZ_bridging_phaseClosure)bridgingphase_closurezbridging+phase_closurezmintpy.unwrapError.method  z3phase unwrapping error correction "{}" is turned ONzuse dataset "{}" by defaultF	print_msgz-input dataset name "{}" not found in file: {}offsetREF_XREF_YTionztimeseriesIon.h5ztemporalCoherenceIon.h5znumInvIon.h5ztimeseries.h5ztemporalCoherence.h5znumInvIfgram.h5azimuthOffsetztimeseriesAz.h5zresidualInvAz.h5znumInvOffAz.h5rangeOffsetztimeseriesRg.h5zresidualInvRg.h5znumInvOffRg.h5z0un-recognized input observation dataset name: {})"rI   
parse_argsr   read_attributer   
ValueErrorformatr   read_template2inpsdictr@   r   DaskClusterformat_num_worker	numWorkerprintr    ospathisfiler   keyslowerreplacer   opendatasetNamesr&   r!   
startswithbasenametsFileinvQualityFile
numInvFile)
iargsrF   inpsatrtemplateZobs_suffix_mapkeyZunw_err_method	stack_objmsgrG   rG   rH   cmd_line_parse   sb    


rx   c                    s.  |s
t  }t|}t| tfddt| D }|D ]L}t|  }|dkrf|||< qD|rD|dkrt	|||< qD|dkrD|||< qDd  fddt| D }|D ]P} |  }|dkr|||< q|r|d	krt
|||< q|d
krt	|||< qdD ]}|| sd||< q|fS )z/Read input template options into Namespace inpsc                    s    g | ]}t |   kr|qS rG   )
key_prefixrg   .0i)rt   rG   rH   
<listcomp>   s      z&read_template2inps.<locals>.<listcomp>)r   r   r   )r   r   )r0   r    zmintpy.compute.c                    s    g | ]} |   kr|qS rG   rg   rz   dask_key_prefixrt   rG   rH   r}      s      )r   config)rb   )	maxMemory)r   r,   )rx   varsr   read_templateutcheck_template_auto_valuelistrg   ry   rB   r@   )template_filerr   iDictkeyListru   valuerG   r   rH   r^      s<    





r^   c              	      s  t d t d d}tdd jD s>d}t dj ntjd d	}|d
 jd }W 5 Q R X tj	jd }||krd}t djd  nt dj tj
d	(}t|j jdtjj
}W 5 Q R X tdd jD }||krd}t dj nt dj |dkrtj
 tjttj
jdd_fdddD }tfddtD rd}t dt nB|rt fdd|D rd}t d| nt dt t d| |S )N2--------------------------------------------------zupdate mode: ONskipc                 s   s   | ]}t j|V  qd S N)rd   re   rf   rz   rG   rG   rH   	<genexpr>   s     zrun_or_skip.<locals>.<genexpr>runz"1) NOT ALL output files found: {}.r   r
timeseries   z'1) output file {} is NOT fully written.z"1) output files already exist: {}.MODIFICATION_TIMEc                 s   s   | ]}t j|V  qd S r   )rd   re   getmtimerz   rG   rG   rH   r     s     z52) output files are NOT newer than input dataset: {}.z22) output dataset is newer than input dataset: {}.T
dropIfgramc                    s   g | ]}|   kr|qS rG   r~   rz   )atr_tsrG   rH   r}     s      zrun_or_skip.<locals>.<listcomp>)rV   rU   c                 3   s.   | ]&}t t|  t| d kV  qdS )NoneN)r@   r   getry   r{   ru   )r   rr   rG   rH   r      s     z83) NOT all key configuration parameters are the same: {}c                 3   s   | ]}|  | kV  qd S r   rG   r   )atr_ifgr   rG   rH   r   #  s     z(3) NOT all the metadata are the same: {}z53) all key configuration parameters are the same: {}.zrun or skip: {}.)rc   allr!   r]   h5pyFilesizerd   re   getsizer   rB   r   attrsr   r   minr   r[   rn   lenr   get_date12_listr   any
configKeys)rr   flagf	fsize_reffsizetito	meta_keysrG   )r   r   rr   rH   run_or_skip   sD    ,

 r   Th㈵>r7   temporalCoherencec
              	   C   s  | | jd d}|dk	r,| | jd d}| jd d }
|jd }tj|
|ftjd}|dkrhtj}nd}d}t|| ||gd\}\} }}ttj| dkdd	|k r|||fS z8|rb|dk	rt	j
t||t|||d
dd \}}nt	j
|||d
dd \}}|dkr.t|||||||	d}|t|d|f }tj|dd	|ddddf< n|dk	rt	j
t| |t|||d
dd \}}nt	j
| ||d
dd \}}|dkrt| ||||||	d}||ddddf< W n t	jk
r   Y nX | jd }|||fS )a'  Estimate time-series from a stack/network of interferograms with
    Least Square minimization on deformation phase / velocity.

    Problem: A X = y
    opt 1: X = np.dot(np.dot(numpy.linalg.inv(np.dot(A.T, A)), A.T), y)
    opt 2: X = np.dot(numpy.linalg.pinv(A), y)
    opt 3: X = np.dot(scipy.linalg.pinv(A), y)
    opt 4: X = scipy.linalg.lstsq(A, y)[0] [recommend and used]

    opt 4 supports weight.
    scipy.linalg provides more advanced and slighted faster performance than numpy.linalg.
    This function relies on the LAPACK routine gelsd. It computes the minimum-norm
    solution to a linear least squares problem using the singular value decomposition
    of A and a divide and conquer method.

    opt 4 is faster than opt 1/2/3 because it estimates X directly without calculating
    the A_inv matrix.

    opt 2/3 is better than opt 1 because numpy.linalg.inv() can not handle rank defiency of
    design matrix B

    Traditional Small BAseline Subsets (SBAS) algorithm (Berardino et al., 2002, IEEE-TGRS)
    is equivalent to the setting of:
        min_norm_velocity=True
        weight_sqrt=None

    Parameters: A                 - 2D np.ndarray in size of (num_pair, num_date-1)
                B                 - 2D np.ndarray in size of (num_pair, num_date-1),
                                    design matrix B, each row represents differential temporal
                                    baseline history between reference and secondary date of one interferogram
                y                 - 2D np.ndarray in size of (num_pair, num_pixel),
                                    phase/offset of all interferograms with no-data value: NaN.
                tbase_diff        - 2D np.ndarray in size of (num_date-1, 1),
                                    differential temporal baseline history, in the unit of years
                weight_sqrt       - 2D np.ndarray in size of (num_pair, num_pixel),
                                    square root of weight of all interferograms
                min_norm_velocity - bool, assume minimum-norm deformation velocity, or not
                rcond             - cut-off ratio of small singular values of A or B, to maintain robustness.
                                    It's recommend to >= 1e-5 by experience, to generate reasonable result.
                min_redundancy    - float, min redundancy defined as min num_pair for every SAR acquisition
                inv_quality_name  - str, inversion quality type/name
                                    temporalCoherence for phase
                                    residual          for offset
                                    no to turn OFF the calcualtion
    Returns:    ts                - 2D np.ndarray in size of (num_date, num_pixel), phase time-series
                inv_quality       - 1D np.ndarray in size of (num_pixel), temporal coherence (for phase) or residual (for offset)
                num_inv_obs       - 1D np.ndarray in size of (num_pixel), number of observations (ifgrams / offsets)
                                    used during the inversion
    r   r   N   dtyperesidual        mat_listaxis)cond   r,   )inv_quality_nameweight_sqrtrS   )reshapeshapenpzerosfloat32nanskip_invalid_obsr   sumr   lstsqmultiplycalc_inv_qualitytilecumsumLinAlgError)ABy
tbase_diffr   min_norm_velocityrcondmin_redundancyr   rS   num_date	num_pixeltsinv_qualitynum_inv_obsXe2Zts_diffrG   rG   rH   estimate_timeseries/  sd    5




 




r   c                 C   s   | | jd d}| | jd d}tj| jd | jd ftjd}t|| |gd\}\} }ttj| dkdd|k r||S t	| }t
t| }tj|||jg}|S )a!  Estimate the time-series covariance from network of STD via linear propagation.
    Pixel by pixel only.

    For a system of linear equations: A X = y, propagate the STD from y to X.

    Parameters: G      - 2D np.ndarray in size of (num_pair, num_date-1), design matrix
                y      - 2D np.ndarray in size of (num_pair, 1), stack of obs
                y_std  - 2D np.ndarray in size of (num_pair, 1), stack of obs std. dev.
    Returns:    ts_cov - 2D np.ndarray in size of (num_date-1, num_date-1), time-series obs std. dev.
    r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   pinvdiagsquareflatten	multi_dotT)Gr   y_stdr   r   ts_covZGplusZ	stack_covrG   rG   rH   estimate_timeseries_cov  s     	
r   c                 C   sr   t t | rjt | dddf   }| |ddf } t|D ]$\}}|dk	rD||ddf ||< qD| |fS )a  Skip invalid observations in the stack of phase/offset and update corresponding matrices.
    This applies to the pixel-wised inversion only, because the region-wised inversion has valid obs in all pairs.
    Parameters: obs      - 2D np.ndarray in size of (num_pair, num_pixel),
                           observations (phase / offset) of all interferograms with no-data value: NaN.
                mat_list - list of 2D np.ndarray in size of (num_pair, *) or None
    Returns:    obs / mat_list
    Nr   )r   r   isnanr   	enumerate)obsr   r   r|   matrG   rG   rH   r     s    r   c              	   C   s~  |j \}}tj|tjd}	ttd| }
||
krtt||
 }|r^td	||
| t
|D ]b}||
 }t|d |
 |}|dkr|dd||f t| |dd||f  }ttjtd| dd	| |	||< n|d
kr|dk	rV|dd||f t| |dd||f  }ttjt|d dd	|	||< n4||| jdkr|t||| ntj|	||< tdtt|d }|rf|d | dkrftd	|d | qfn|dkr|t| | }ttjtd| dd	| }	nn|d
krl|dk	rN|| | }ttjt|d dd	}	n|jdkrdt|ntj}	ntd| |	S )a  Calculate the inversion quality of the time series estimation.

    Parameters: G                - 2D np.ndarray in size of (num_pair, num_date-1), design matrix A or B
                X                - 2D np.ndarray in size of (num_date-1, num_pixel), solution
                y                - 2D np.ndarray in size of (num_pair, num_pixel), phase or offset
                e2               - 1D np.ndarray in size of (num_pixel,), square of the sum of the 2-norm residual
                inv_quality_name - str, name of the inversion quality parameter
                                   temporalCoherence for phase
                                   residual          for offset
                weight_sqrt      - 2D np.ndarray in size of (num_pair, num_pixel),
                                   weight square root, None for un-weighted estimation.
    Returns:    inv_quality      - 1D np.ndarray in size of (num_pixel), temporalCoherence / residual
    r   g     jAz=calculating {} in chunks of {} pixels: {} chunks in total ...r   r   Ny              ?r   r   r   r      chunk {} / {}z&un-recognized inversion quality name: )r   r   r   r   intr   
round_to_1ceilrc   r]   ranger   dotabsr   expsqrtr   r   maxr\   )r   r   r   r   r   r   rS   num_pairr   r   
chunk_size	num_chunkr|   c0c1eZ
chunk_steprG   rG   rH   r     sF    

  0,

0(4
$

 r   r*   c                 C   s   t | jdd}t |d }|dkrNtj||jd k rtd td nTtj||jd k rtd td	 td
 td td td td t |S )z<
    Check Rank of Design matrix for weighted inversion
    Tr   r   r,   r   z@WARNING: singular design matrix! Inversion result can be biased!z-continue using its SVD solution on all pixelszERROR: singular design matrix!z;    Input network of interferograms is not fully connected!z6    Can not invert the weighted least square solution.zYou could try:zC    1) Add more interferograms to make the network fully connected:z6       a.k.a., no multiple subsets nor network islandsz8    2) Use '-w no' option for non-weighted SVD solution.)	r   r   get_design_matrix4timeseriesr   r   matrix_rankr   rc   	Exception)ifgram_fileweight_funcdate12_listr   rG   rG   rH   check_design_matrix@  s     
r  rM   c              	   C   s   | j |dd }|r&td||| | j|||dd|d}|dk	rV|rtd nJd	| jkr|rltd
 t| jd}|d	 dd }W 5 Q R X nt	dt
|D ]8}	||	ddf dk}
||	ddf |
  ||	 8  < q|S )a&  Read unwrapPhase / azimuthOffset / rangeOffset from ifgramStack file

    Parameters: stack_obj - ifgramStack object
                box       - tuple of 4 int
                ref_phase - 1D array or None
    Returns:    stack_obs - 2D array of unwrapPhase in size of (num_pair, num_pixel)
    r   r   reading {} in {} * {} ...FdatasetNameboxr   rS   r   Nzuse input reference valuerefPhasezread reference phase from filer   zJNo reference value input/found on file! unwrapped phase is not referenced!r   )get_sizerc   r]   readr   rk   r   r   filer   r   )rv   r  	ref_phaseobs_ds_namer   rS   r   	stack_obsr   r|   r4   rG   rG   rH   read_stack_obsX  s0    
 

"r  r6   c              	   C   s  |j |dd }|r||jkr|r8td||| |j|||dd|d}	d|	t|	< tj|	j	tj
d}
|dkr|
|	dk9 }
|rtd	| n|d
kr|
|	|k9 }
|rtd|| n|dr|
|	|k9 }
|rtd|| d}tj| j	d dftjd}t| j	d D ] }t| | |
|  ||< qt| t|d| j	d f |	d  }t|	|d k||k}d|
|< |rtd||d | ntd|tj| |
dk< |dk	rtj||
dk< ~	~
| |fS )z5Mask input unwrapped phase by setting them to np.nan.r   r   r  Fr  r   r   connectComponentz3mask out pixels with {} == 0 by setting them to NaN	coherence	offsetSNRz3mask out pixels with {} < {} by setting them to NaN	OffsetStdz3mask out pixels with {} > {} by setting them to NaN
   r   r   r   z'keep pixels with {} <= {} and SNR >= {}#Un-recognized mask dataset name: {}r   N)r  rk   rc   r]   r  r   r   r   onesr   bool_endswithr   r   r   	nanmedianr   r   r   r\   r   )r  rv   r  mask_ds_namemask_threshold	stack_stdr   rS   r   Zmsk_datamskZmin_snrZobs_medr|   Zobs_snrZmsk_snrrG   rG   rH   mask_stack_obs  sR     (
r  c                 C   sP   | j |dd }|r$td|| | jd||dd|d}d|t|< |S )	z 
    Read spatial coherence
    r   r   z reading coherence in {} * {} ...r  Fr  r   r   )r  rc   r]   r  r   r   r   )rv   r  r   rS   r   Zcoh_datarG   rG   rH   read_coherence  s     r  順 c                 C   s\  t d t| ||d}|jd }d| j kr>t| jd }n$t| jd t| jd  }|d }tt	|
td}tt|| }t dj||d	 t|D ]}	|	| }
t|	d | |}|	d
krd}nd}tj|dd|
|f ||d|d|dd|
|f< t|dd|
|f |dd|
|f< |	d d d
krt d|	d | q|S )zTRead coherence and calculate weight_sqrt from it, chunk by chunk to save memory
    z-calculating weight from spatial coherence ...)r  r   r   
NCORRLOOKSALOOKSRLOOKSg
ףp=
?zLconvert coherence to weight in chunks of {c} pixels: {n} chunks in total ...)cnr   TFNg?)LepsilonrS   r   )rc   r  r   metadatarg   rB   r   r   r   rintastyper   r]   r   r   decorZcoherence2weightr   )rv   r  r   r   r   weightr   r&  r   r|   r   r   rS   rG   rG   rH   calc_weight_sqrt  s:    
 *r-  c           
      C   s   t jt j| j}t j|d}t|d }|dkrXt j|d}t j|sXd}|rt j|rtt	j
|tdt}|sd}|d7 }t|| jd	d
}| jd	d
}| j||dd }t	||k}||}	||	||fS )a  Get the design matrix for time-series STD calculation.
    Parameters: stack_obj - ifgramStack object
    Returns:    A_std     - 2D np.ndarray of float32 in size of (num_ifg, num_date-1)
                ref_ind   - int, index of the reference date in date_list
                ref_date  - str, reference date
                flag_std  - 1D np.ndarray of bool in size of (num_date)
    zsmallbaselineApp.cfgzmintpy.reference.dateautozreference_date.txtNr   z;reference date is required for time-series STD calculation,z'but NOT found in mintpy.reference.date!Tr   )refDater   )rd   re   dirnamer	  joinr   r   rf   r@   r   loadtxtbytesr*  r\   r   get_date_listr   arrayindex)
rv   Z
mintpy_dirZcfg_filer%   rw   r   	date_listA_stdZflag_stdref_indrG   rG   rH   get_design_matrix4std  s&    

r:  Fc           B   	   C   s
  t | }|jdd tj| \}}|rJ|d |d  }|d |d  }n|j}|j}|| }|jdd}t|}t	
t|d t	jd	 }t	|d
d}|jdd}|j|ddd \}}d}d}|dr@|dkrt|||ddd}|
r0t|dd \}}|d }|dkr(d| }ndt||dddd }nd| kr"|
s^|dkr0td|d |t| |j|d |dddt|d
}d|t	|< d||dk < td d| }|
rt|dd \}}|d }d| }|dkrd}n"|dkr
ntd| d| dntd| t||||dd}d| krlt	j||d k< td!| t||||||dd"\}}t	|t	j}|r<td#tj | t!"|}t#|d$ t#|d%  } }!| |!f|j|jfkrtd&t!$|}"d'd( |"D d }#t!j||#|d)d % }$|t	j
|$t	jd*9 }~$td+| |t	j&t	|dd, 9 }d| krd-}%tj'|d.}&n2|d/rd0}%tj'|d1}&nd0}%tj'|d2}&tj(|&r:t!"|&}'t#|'d$ t#|'d%  }(})|(|)f|j|jfkr:td3tj |& t!j|&|d4d % }*||*d k9 }~*t#t	)|}+t	*|d },td5|+||+| d6  t	+||ft	j}-|
rt	+|||ft	jnd}.t	+|t	j}/d| kr|/t	j9 }/t	+|t	j,}0|+dk r,|-|||}-|
r|.||||n|.}.|/||}/|0||}0|-|.|/|0|fS |||||	|%d7}1|dkrd8| d9}2t	j&t	| dd,}3|3|9 }3||3A }4~t	)|3dkrt#t	)|3}5t|2 d:|5 d;|5|+ d6 d<d= t-f |dd|3f dd>|1\}6}7}8|6|-dd|3f< |7|/|3< |8|0|3< t	)|4dkrt#t	)|4}9t	*|4d }:t|2 d?|9 d;|9|+ d6 d<d= tj.|9d@};t/|9D ]x}<|:|< }=t-f |dd|=f dd>|1\}6}7}8|6% |-dd|=f< |7|/|=< |8|0|=< |;j0|<d dAdB|<d |9dC qh|;1  ntdD tj.|+d@};t/|+D ]}<|,|< }=t-f |dd|=f |dd|=f d>|1\}6}7}8|6% |-dd|=f< |7|/|=< |8|0|=< |;j0|<d dAdB|<d |+dC q|;1  ~|
rtdE tj.|+d@};t/|+D ]}<|,|< }=t2||dd|=f |dd|=f |	dF}>|>d|d|f |.d|d||=f< |>d||df |.d||d|=f< |>|dd|f |.|dd||=f< |>|d|df |.|d|d|=f< |;j0|<d dAdB|<d |+dC q|;1  ~~|-|||}-|
r|.||||n|.}.|/||}/|0||}0|d	rHd
t3|j4dG  dHt	j5  }?|-|?9 }-|
	r:|.t	6|? n|.}.tdI n|dJk|j4dK dLk@ 	rt78|j4}@|@t3|j4dM  }@|-|@9 }-|
	r|.|@ n|.}.tdN|@ nd|dOk|j4dK dLk@ 
rt3|j4dP }A|At3|j4dQ  }A|-d
|A 9 }-|
	r|.|A n|.}.tdR|A |-|.|/|0|fS )SaS  Invert one patch of an ifgram stack into timeseries.

    Parameters: ifgram_file       - str, interferograms stack HDF5 file, e.g. ./inputs/ifgramStack.h5
                box               - tuple of 4 int, indicating (x0, y0, x1, y1) of the area of interest
                                    Set to None for the whole image
                ref_phase         - 1D array in size of (num_pair), or None
                obs_ds_name       - str, dataset to feed the inversion.
                weight_func       - str, weight function, choose in ['no', 'fim', 'var', 'coh']
                water_mask_file   - str, water mask filename if available, to skip inversion on water
                min_norm_velocity - bool, minimize the residual phase or phase velocity
                mask_ds_name      - str, dataset name in ifgram_file used to mask unwrapPhase pixelwisely
                mask_threshold    - float, min coherence of pixels if mask_dataset_name='coherence'
                min_redundancy    - float, the min number of ifgrams for every acquisition.
                calc_cov          - bool, calculate the time series covariance matrix.
    Returns:    ts                - 3D array in size of (num_date, num_row, num_col)
                ts_cov            - 4D array in size of (num_date, num_date, num_row, num_col) or None
                inv_quality       - 2D array in size of (num_row, num_col)
                num_inv_obs       - 2D array in size of (num_row, num_col)
                box               - tuple of 4 int
    Example:    ifgram_inversion_patch('ifgramStack.h5', box=(0,200,1316,400))
    FrR   r"   r   r   r   Tr   g     v@r   )r   N)rM   rW   )r,   Zsbasr   )r   r   r   r*   r7   rT   r  Stdr  g      Y@g{Gzt?z,convert std. dev. to the inverse of variancezun-supported weight_func = z for !z(un-recognized observation dataset name: )r  r   phaser   z/convert zero value in {} to NaN (no-data value))r  r  r  r   z6skip pixels (on the water) with zero value in file: {}LENGTHWIDTHz?Input water mask file has different size from ifgramStack file.c                 S   s   g | ]}|d kr|qS ))	waterMaskr4   rG   rz   rG   rG   rH   r}     s      z*ifgram_inversion_patch.<locals>.<listcomp>)r  r  r   z/skip pixels with {} = NaN in all interferogramsr   r   z../avgSpatialSNR.h5rW   r   z../avgSpatialCohIon.h5z../avgSpatialCoh.h5z'skip pixels with zero value in file: {})r  z2number of pixels to invert: {} out of {} ({:.1f}%)d   )r   r   r   r   r   r   z-estimating time-series for pixels with valid z inz all  ifgrams (z	 pixels; z.1fz%) ...)r   r   z some ifgrams ()maxValue   z{}/{} pixels)everysuffixz1estimating time-series via WLS pixel-by-pixel ...zepropagating std. dev. from network of interferograms to time-series (Yunjun et al., 2021, FRINGE) ...)r   r   r   
WAVELENGTHg      @z.converting LOS phase unit from radian to meterrX   	PROCESSORcosicorrr"  z=converting azimuth offset unit from pixel ({:.2f} m) to meterrY   RANGE_PIXEL_SIZEr#  z;converting range offset unit from pixel ({:.2f} m) to meter)9r   rj   rd   re   r=   lengthwidthr4  r   r   r5  r	   date_list2tbaser   diffr   r   r   rl   r-  r:  rh   rc   r]   r  r   r\   r  r   r  r  r  rm   r   r[   r   get_dataset_listr   r   r1  rf   r   wherer   int16r   progressBarr   updatecloser   rB   r(  pir   r   azimuth_ground_resolution)Br   r  r
  r  r   water_mask_filer   r  r  r   calc_covrv   Z	stack_dirZ
stack_basenum_rownum_colr   r7  r   tbaser   r   r   r   r   r  r8  r0r1r  r4   Zatr_mskZlen_mskZwid_mskdsNamesdsNamer@  r   Zstack_quality_fileZ	atr_stackZ	len_stackZ	wid_stackqualitynum_pixel2invidx_pixel2invr   r   r   r   kwargsrw   Zmask_all_netZmask_part_netZnum_pixel2inv_allZtsiZ	inv_qualiZnum_obsiZnum_pixel2inv_partZidx_pixel2inv_partprog_barr|   idxZts_coviphase2rangeaz_pixel_sizeZrg_pixel_sizerG   rG   rH   ifgram_inversion_patch$  s   




 




  




$$$
$&&&&$
rg  c           *      C   s6  | s
t  } t }td}t| j}|jdd |jdd}|jdd}|j	|j
 }}|j| j| jdd| _||d }|jd |jd d  }	}
|	| _| jrt|d	 }d
| }nd}d}| jrd}nd}|d|7 }|d| j7 }|d| j7 }|d| j|7 }| jr| jdkr4d| j}nN| jdkrRd| j| j}n0| jdrrd| j| j}ntd| j|d|7 }n|d7 }tj||jd k r|d7 }|d7 }|d7 }|d7 }t| td |	 td!|
 td"| td#| t |j!}t"D ]}t#t$| | |t%| < q d$|d%< d&|d'< |d |d(< tj&|tj'd)}|j(dd}|j)|
f|gtj*|
f|gtj*|
||fd*gd+}t+j,| j-||d, | jr0t.j/0| j-d }|| j1d-rd.nd7 }| d/}||d(< |j)|
f|gtj*|
|
||fd*gd0}t+,||| d1t.j/2| j34 krVd1}d2|d'< nd3}d|d'< ||d%< |5d( |d% tj*||fgi}t+j,| j3||d, d4|d%< d|d'< d4tj*||fgi}t+j,| j6||d, |j7| j8d5\}}| j| j| j| j| j| j9| j| j| j| jd6
}t:|D ]&\}}|d	 |d  }|d7 |d  }|dkr|td8|d | td9| td:| ||d;< | jst;f |d*d< \}}} }!ntd= t<|
||ftj*}| jrt<|
|
||ftj*nd*}t<||ftj*} t<||ftj*}!tj=| j| j>| j?d>}"|"  |"j@t;|||| |!gd?\}}} }!|"A  td@ d|
|d |d7 |d |d	 g}#t+jB| j-|d$|#dA | jrd|
d|
|d |d7 |d |d	 g}#t+jB||d$|#dA |d |d7 |d |d	 g}#t+jB| j3| ||#dA t+jB| j6|!d4|#dA |dkrtCt | dB\}$}%tdC|$|% q| jstD|j!dD }&tD|j!dE }'tdF tdG|&|' |d1krdnd}(tdH||( tEF| j3dI})|(|)| |&|'f< W 5 Q R X tdJ|	 tEF| j6dI})|	|)d4 |&|'f< W 5 Q R X tG| tCt | dB\}$}%tdC|$|% d*S )KzPhase triangulatino of small baseline interferograms

    Parameters: inps - namespace
    Example:    inps = cmd_line_parse()
                ifgram_inversion(inps)
    rL   FrR   Tr   )unwDatasetNameskip_referencer   r   r   r   z with REF_DATE = rQ   zP-------------------------------------------------------------------------------
zdeformation velocityzdeformation phasez/least-squares solution with L2 min-norm on: {}
zminimum redundancy: {}
zweight function: {}
zcalculate covariance: {} {}
r  z{} == 0r  z{} < {}r  z{} > {}r  zmask out pixels with: {}
z	mask: no
z0***WARNING: the network is NOT fully connected.
z!	Inversion result can be biased!
zF	Continue to use SVD to resolve the offset between different subsets.
zO-------------------------------------------------------------------------------znumber of interferograms: {}znumber of acquisitions  : {}znumber of lines   : {}znumber of columns : {}r   rK   mUNITREF_DATEr   N)datebperpr   )r(  rM   ZDecorzCov.h5)rm  r   r   pixelr   r4   )
max_memory)
r   r
  r  r   r   rV  r  r  r   rW  r"   z5
------- processing patch {} out of {} --------------zbox width:  {}zbox length: {}r  r   z6

------- start parallel processing using Dask -------)config_name)func	func_dataresultsz.------- finished parallel processing -------

)datar  block<   z(time used: {:02.0f} mins {:02.1f} secs.
rV   rU   r   z.update values on the reference pixel: ({}, {})z$set {} on the reference pixel to {}.zr+z3set  # of observations on the reference pixel as {})Hrx   timer   set_num_threadsr   r   rj   r   r4  rJ  rK  get_reference_phaser   r&   r  r   r   r   r3   r:  r   r]   r   r   r   r   r  r\   r   r   r   rc   r_   r(  r   r@   r   ry   r5  string_get_perp_baseline_timeseriesr   r   r   layout_hdf5rn   rd   re   splitextrl   rm   ro   rh   poprp   split2boxesr   r    r   rg  r   r`   rb   r   r   rS  write_hdf5_blockdivmodr   r   r   roll_back_num_threads)*rr   
start_timenum_threads_dictrv   r   r7  rJ  rK  r   r   r   Zref_date4stdZref_msgrw   rE  metaru   datespbaseds_name_dictfbaseZ	tsStdFiler   box_listnum_boxdata_kwargsr|   r  box_widbox_lenr   r   r   r   cluster_objrv  rj  sref_yref_xref_valr   rG   rG   rH   ifgram_inversiont  sD   






"
 $

r  c                 C   s@   t | }|jr t|dkr |jS |jdkr4t| ntdd S )Nr   r1   z)L1 norm minimization is not fully tested.)rx   r8   r   r!   r0   r  NotImplementedError)rq   rr   rG   rG   rH   mainw  s    

r  __main__r   )N)N)NTr   r7   r   T)r   r7   )r   NT)r*   )rM   TT)Nr6   NTT)TT)r*   Tr   )
NNrM   r*   NTNr6   r7   F)N)N)/rd   sysrx  r   numpyr   scipyr   mintpy.objectsr   r   Zmintpy.simulationr   r+  mintpy.defaults.templater   mintpy.utilsr   r   r	   r
   r   r   ry   r   r:   r9   r;   rI   rx   r^   r   r   r   r   r   r  r  r  r  r-  r:  rg  r  r  r<   argvrG   rG   rG   rH   <module>   s   
	
G
J(5       
 
&
M
  
*      
<

/'             
  R
  

